Python,Qt,ComboBox,两列?

Posted

技术标签:

【中文标题】Python,Qt,ComboBox,两列?【英文标题】:Python, Qt, ComboBox, two columns? 【发布时间】:2020-05-12 15:25:42 【问题描述】:

问题很简单,但是目前的答案有问题:

我将 QT 与 Python 和 SQL 结合使用。 我得到了一些查询数据:“从部门中选择 ID,部门” 我想创建包含两列(id、department)的组合框,它将只显示“department”(department 1、department 2 .. etc),但选择后,它应该返回“id”。

换句话说:我正在为 c# 中的组合框寻找与 displaymembervaluemember 相同的功能。

我设法在 Combobox 中创建了一个 Qtableview,但是一个问题会导致另一个问题(视图、读取“id”等)。 还有其他更简单的方法吗?

【问题讨论】:

你用什么库发出 SQL 请求? 通常我使用 PYODBC 进行 SQL 连接。在这种情况下,我将 QSqlTableModel 用于组合框模型(我记得 - 我现在没有代码在我面前)。 【参考方案1】:

正如 OP 指出它使用 QSqlTableModel,那么模仿 C# 行为的可能解决方案是建立将通过 modelColumn 属性显示的列,然后使用与所选行关联的 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_())

另一种解决方案是,基于 pyodbc 获得的数据,您可以构建一个 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_())

【讨论】:

谢谢!它似乎按我的意愿工作。我明天会实施它:) 第二个解决方案比第一个更好:-)

以上是关于Python,Qt,ComboBox,两列?的主要内容,如果未能解决你的问题,请参考以下文章

Qt 按键控制combobox

Qt 学习笔记 2. ComboBox

QT中ComboBox如何获取选中的文本内容??下面程序出错了,如何改正?

linux下Qt Designer中的combobox控件 怎么使用?

QML中的ComboBox SQL QT 5.10.1

Qt Quick:如何从 ComboBox 获取当前文本