【问题标题】:How to link an editable QComboBox to a database如何将可编辑的 QComboBox 链接到数据库
【发布时间】:2018-02-27 18:59:49
【问题描述】:

我正在使用 Pyside 创建一个从 sqlite 数据库中提取的组合框。用户可以选择现有项目之一或添加新项目。用户看到项目名称(称为“参数”),但我需要访问数据库中的项目 ID。所以,有两个步骤:

阅读项目:我可以从数据库中读取,但在后台访问项目 ID 时无法显示项目名称。

添加项目:我是否需要检测组合框中的更改,然后使用 SQL 插入命令或模型是否为我处理?

此代码从数据库中读取,但显示不正确:

param_model = QSqlQueryModel()
param_model.setQuery("select id, param from partable order by param")
param_model.setHeaderData(0, Qt.Horizontal,"id")
param_model.setHeaderData(1, Qt.Horizontal,"param")

param_view = QTableView()
param_view.setColumnHidden(0,True)

self.paramfield = QComboBox()
self.paramfield.adjustSize()
self.paramfield.setEditable(True)
self.paramfield.setModel(param_model)
self.paramfield.setView(param_view)

【问题讨论】:

    标签: python pyside qcombobox qsqldatabase


    【解决方案1】:

    您的代码存在几个问题。首先,您需要使用可编辑的QSqlTableModel,而不是只读的QSqlQueryModel。其次,您不需要在组合框上设置标题或视图。第三,您必须在组合框上设置正确的模型列才能显示适当的值。

    关于添加项目的问题:只需通过模型提交更改即可。但是,通常还需要找到添加的项目的 id 或索引(例如,为了重置当前索引)。如果模型已排序和/或允许重复条目,这可能会有点棘手。

    下面的演示脚本向您展示了如何处理上述所有问题:

    import sys
    from PySide import QtCore, QtGui, QtSql
    
    class Window(QtGui.QWidget):
        def __init__(self):
            super(Window, self).__init__()
            self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
            self.db.setDatabaseName(':memory:')
            self.db.open()
            self.db.transaction()
            self.db.exec_(
                'CREATE TABLE partable'
                '(id INTEGER PRIMARY KEY, param TEXT NOT NULL)'
                )
            self.db.exec_("INSERT INTO partable VALUES(1, 'Red')")
            self.db.exec_("INSERT INTO partable VALUES(2, 'Blue')")
            self.db.exec_("INSERT INTO partable VALUES(3, 'Green')")
            self.db.exec_("INSERT INTO partable VALUES(4, 'Yellow')")
            self.db.commit()
            model = QtSql.QSqlTableModel(self)
            model.setTable('partable')
            column = model.fieldIndex('param')
            model.setSort(column, QtCore.Qt.AscendingOrder)
            model.select()
            self.combo = QtGui.QComboBox(self)
            self.combo.setEditable(True)
            self.combo.setModel(model)
            self.combo.setModelColumn(column)
            self.combo.lineEdit().returnPressed.connect(self.handleComboEdit)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.combo)
    
        def handleComboEdit(self):
            if self.combo.lineEdit().isModified():
                model = self.combo.model()
                model.submitAll()
                ID = model.query().lastInsertId()
                if ID is not None:
                    index = model.match(
                        model.index(0, model.fieldIndex('id')),
                        QtCore.Qt.EditRole, ID, 1, QtCore.Qt.MatchExactly)[0]
                    self.combo.setCurrentIndex(index.row())
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.setGeometry(800, 50, 200, 50)
        window.show()
        sys.exit(app.exec_())   
    

    PS:这里是如何从组合框中获取id,使用它的当前索引:

    model = self.combo.model()
    index = self.combo.currentIndex()
    ID = model.index(index, model.fieldIndex('id')).data()
    

    【讨论】:

    • 非常感谢您提供如此详细的解释和示例。我会调整我的代码并报告它是否有效。
    • 您的代码运行良好。当我根据您的建议调整我的代码时,新的组合框条目被添加到具有 NULL id 的数据库中,并且我收到此错误:“handleComboEdit Qt.EditRole, ID, 1, Qt.MatchExactly)[0] IndexError: list index超出范围”。但是,“ID = model.query().lastInsertId()”的结果是一个整数。因此,model.match 可能还没有工作。我会尽快回来报告...
    • 实际上,问题似乎是我错误地定义了sqlite表。 “id INT PRIMARY KEY”会生成一个看起来不错但无法正常工作的表。 “id INTEGER PRIMARY KEY”工作正常。谢谢!
    • 当用户在combo-box中输入内容后按下return键时,会添加一个新项目,并更新底层模型。这会发出一个信号,由handleComboEdit 插槽处理。此时,模型数据可能与数据库不同步。所以打电话给submitAll() 可以解决这个问题。 (严格来说,我应该将 edit stategy 设置为 OnManualSubmit 以使其完全有意义,因为默认值为 OnRowChange - 但这并不会真正影响示例的整体逻辑)。
    • 如果你想自己控制一切,你应该将组合框的insert policy设置为NoInsert,这样它就不会自动添加新的项目。然后由您来更新模型(可能还有数据库,取决于编辑策略)。组合框将自动反映您对模型所做的任何更改。
    猜你喜欢
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    相关资源
    最近更新 更多