Python, Qt, ComboBox, 两列?
Python, Qt, ComboBox, two columns?
问题很简单,但目前答案有问题:
我将 QT 与 Python 和 SQL 一起使用。
我正在获取一些查询数据:'select id, department from departments'
我想创建包含两列(id、部门)的组合框,它将仅显示 "department"(部门 1、部门 2 .. 等),但选择后,它应该 return "id" .
换句话说:我正在为 c# 中的组合框寻找与 displaymember 和 valuemember 相同的功能。
我设法在 Combobox 中创建了一个 Qtableview,但一个问题会导致另一个问题(查看、阅读 "id" 等)。
还有其他更简单的方法吗?
由于 OP 指出它使用 QSqlTableModel,因此模仿 C# 行为的一种可能解决方案是通过 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_())
另一种解决方案是,基于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_())
问题很简单,但目前答案有问题:
我将 QT 与 Python 和 SQL 一起使用。 我正在获取一些查询数据:'select id, department from departments' 我想创建包含两列(id、部门)的组合框,它将仅显示 "department"(部门 1、部门 2 .. 等),但选择后,它应该 return "id" .
换句话说:我正在为 c# 中的组合框寻找与 displaymember 和 valuemember 相同的功能。
我设法在 Combobox 中创建了一个 Qtableview,但一个问题会导致另一个问题(查看、阅读 "id" 等)。 还有其他更简单的方法吗?
由于 OP 指出它使用 QSqlTableModel,因此模仿 C# 行为的一种可能解决方案是通过 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_())
另一种解决方案是,基于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_())