Python, Qt, ComboBox, две колонки? - PullRequest
       26

Python, Qt, ComboBox, две колонки?

0 голосов
/ 27 января 2020

Вопрос довольно прост, но пока что есть проблема с ответом:

Я использую QT с Python и SQL. Я получаю некоторые данные запроса: «выберите идентификатор, отдел из отделов». Я хочу создать комбинированный список с двумя столбцами (идентификатор, отдел), который будет отображать только «отдел» (отдел 1, отдел 2 и т. Д. c) , но после выбора он должен вернуть «id».

Другими словами: я ищу ту же функциональность, что и displaymember и valuemember для комбинированного списка в c#.

Мне удалось создать Qtableview в Combobox, но одна проблема создает другую (просмотр, чтение "id" и т. Д. c.). Есть ли другой способ проще?

1 Ответ

1 голос
/ 27 января 2020

Поскольку OP отмечает, что использует QSqlTableModel, то возможным решением mimi c поведения C# является установление sh столбца, который будет отображаться через свойство modelColumn, а затем доступ к соответствующим элементам (id и другие поля), используя QSqlRecord, связанный с выбранной строкой.

from PyQt5 import QtCore, QtWidgets, QtSql


def createConnection():
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(":memory:")
    if not db.open():
        QtWidgets.QMessageBox.critical(
            None,
            QtWidgets.qApp.tr("Cannot open database"),
            QtWidgets.qApp.tr(
                "Unable to establish a database connection.\n"
                "This example needs SQLite support. Please read "
                "the Qt SQL driver documentation for information "
                "how to build it.\n\n"
                "Click Cancel to exit."
            ),
            QtWidgets.QMessageBox.Cancel,
        )
        return False

    query = QtSql.QSqlQuery()
    query.exec_(
        "CREATE TABLE  Departments (id INTEGER PRIMARY KEY AUTOINCREMENT, department TEXT);"
    )

    query.exec_("INSERT INTO Departments(department) VALUES('department1')")
    query.exec_("INSERT INTO Departments(department) VALUES('department2')")
    query.exec_("INSERT INTO Departments(department) VALUES('department3')")
    query.exec_("INSERT INTO Departments(department) VALUES('department4')")
    query.exec_("INSERT INTO Departments(department) VALUES('department5')")
    return True


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.model = QtSql.QSqlTableModel(self)
        self.model.setTable("Departments")
        self.model.select()

        self.tableview = QtWidgets.QTableView()
        self.tableview.setModel(self.model)

        self.combo = QtWidgets.QComboBox()
        self.combo.setModel(self.model)
        column = self.model.record().indexOf("department")
        self.combo.setModelColumn(column)

        self.combo.currentIndexChanged.connect(self.onCurrentIndexChanged)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.tableview)
        lay.addWidget(self.combo)

    @QtCore.pyqtSlot(int)
    def onCurrentIndexChanged(self, index):
        column = self.model.record().indexOf("id")
        r = self.model.record(index)
        value = r.value(column)
        print(value)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    if not createConnection():
        sys.exit(1)

    w = Widget()
    w.show()

    sys.exit(app.exec_())

Другое решение состоит в том, что на основе данных, полученных pyodb c, вы можете построить QStandardItemModel (или другую модель), где скрытое поле связано с ролью, которую затем можно получить.

from PyQt5 import QtCore, QtGui, QtWidgets

IdRole = QtCore.Qt.UserRole + 1000


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        d = (
            (1, "department1"),
            (2, "department2"),
            (3, "department3"),
            (4, "department4"),
            (5, "department5"),
        )

        self.model = QtGui.QStandardItemModel(self)

        for id_, value in d:
            it = QtGui.QStandardItem(value)
            it.setData(id_, IdRole)
            self.model.appendRow(it)

        self.combo = QtWidgets.QComboBox()
        self.combo.setModel(self.model)

        self.combo.currentIndexChanged.connect(self.onCurrentIndexChanged)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.combo)

    @QtCore.pyqtSlot(int)
    def onCurrentIndexChanged(self, index):
        id_ = self.combo.itemData(index, IdRole)
        # or
        # id_ = self.model.item(index).data(IdRole)
        print(id_)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = Widget()
    w.show()

    sys.exit(app.exec_())
...