如何 link 一个可编辑的 QComboBox 到数据库
How to link an editable QComboBox to a database
我正在使用 Pyside 创建一个从 sqlite 数据库中提取的组合框。用户可以 select 现有项目之一或添加新项目。用户看到项目名称(称为 "param"),但我需要从数据库访问项目 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)
您的代码存在几个问题。首先,您需要使用可编辑的 QSqlTableModel
,而不是只读的 QSqlQueryModel
。其次,您不需要设置 headers 或 combo-box 上的视图。第三,您必须在 combo-box 上设置正确的模型列才能显示适当的值。
关于添加项目的问题:只需通过模型提交修改即可。但是,通常也希望找到添加的项目的 ID 或索引(例如,为了重置当前索引)。如果模型排序 and/or 允许重复条目,这可能有点棘手。
下面的演示脚本向您展示了如何处理上述所有问题:
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:这里是如何从 combo-box 中获取 id
,使用其当前索引:
model = self.combo.model()
index = self.combo.currentIndex()
ID = model.index(index, model.fieldIndex('id')).data()
我正在使用 Pyside 创建一个从 sqlite 数据库中提取的组合框。用户可以 select 现有项目之一或添加新项目。用户看到项目名称(称为 "param"),但我需要从数据库访问项目 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)
您的代码存在几个问题。首先,您需要使用可编辑的 QSqlTableModel
,而不是只读的 QSqlQueryModel
。其次,您不需要设置 headers 或 combo-box 上的视图。第三,您必须在 combo-box 上设置正确的模型列才能显示适当的值。
关于添加项目的问题:只需通过模型提交修改即可。但是,通常也希望找到添加的项目的 ID 或索引(例如,为了重置当前索引)。如果模型排序 and/or 允许重复条目,这可能有点棘手。
下面的演示脚本向您展示了如何处理上述所有问题:
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:这里是如何从 combo-box 中获取 id
,使用其当前索引:
model = self.combo.model()
index = self.combo.currentIndex()
ID = model.index(index, model.fieldIndex('id')).data()