4.4 使用關(guān)聯(lián)委托
PyQt5編程(44)的程序有一個(gè)缺點(diǎn),在添加新條目或編輯現(xiàn)有記錄時(shí),如果類別的輸入不是代號(hào)而是“耗材”、“存儲(chǔ)介質(zhì)”時(shí),所作的修改是不會(huì)被保存。因?yàn)樵撟侄卧跀?shù)據(jù)庫(kù)表中為整型字段,只能輸入整數(shù)。
為了改變這種情況,我們將被一個(gè)被稱為連接(connected)的特殊委托(delegate)。它能夠第一表中執(zhí)行搜索,提取id字段內(nèi)容并將其存儲(chǔ)到第二個(gè)表的字段中。
關(guān)聯(lián)的委托功能由QSqlRelationalDelegate類實(shí)現(xiàn)。 繼承層次結(jié)構(gòu)如下:
QObject - QAbstractltemDelegate - QltemDelegate - QSqlRelationalDelegate
使用方法:
1. 以要展示的組件(如,TableView)作參數(shù)創(chuàng)建QSqlRelationalDelegate類實(shí)例;
2.調(diào)用setItemDelegate()、setItemDelegateForColumn()或setItemDelegateForRow()。
PyQt5中有個(gè)BUG, 在修改使用委托的某列值,并將焦點(diǎn)移到另一記錄時(shí),有時(shí)會(huì)顯示id而非顯示指定值的情況。要繞開此BUG,需要按如下操作:
1.把展示組件(TableView)的編輯模式設(shè)置為onManualSubmit;
2.處理dataChanged信號(hào),調(diào)用submit()或submitAll()來(lái)實(shí)現(xiàn)修改的數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)。
下面是 PyQt5編程(44)中的例子使用關(guān)聯(lián)委托后的代碼:
from PyQt5 import QtCore, QtWidgets, QtSql
import sys
def addRecord():
stm.insertRow(stm.rowCount())
def delRecord():
stm.removeRow(tv.currentIndex().row())
stm.select()
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QWidget()
window.setWindowTitle("QRelationalSqlTableModel")
con = QtSql.QSqlDatabase.addDatabase('QSQLITE')
con.setDatabaseName('data.sqlite')
con.open()
stm = QtSql.QSqlRelationalTableModel(parent = window)
stm.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
stm.setTable('good')
stm.setSort(2, QtCore.Qt.AscendingOrder)
將good表中的category字段設(shè)置為到category表的鏈接
stm.setRelation(3, QtSql.QSqlRelation('category', 'id', 'catname'))
stm.select()
stm.setHeaderData(1, QtCore.Qt.Horizontal, '名稱')
stm.setHeaderData(2, QtCore.Qt.Horizontal, '數(shù)量')
stm.setHeaderData(3, QtCore.Qt.Horizontal, '類別')
stm.dataChanged.connect(stm.submitAll)
vbox = QtWidgets.QVBoxLayout()
tv = QtWidgets.QTableView()
tv.setModel(stm)
tv.setItemDelegateForColumn(3, QtSql.QSqlRelationalDelegate(tv))
tv.hideColumn(0)
tv.setColumnWidth(1, 150)
tv.setColumnWidth(2, 60)
tv.setColumnWidth(3, 150)
vbox.addWidget(tv)
btnAdd = QtWidgets.QPushButton("添加記錄(&A)")
btnAdd.clicked.connect(addRecord)
vbox.addWidget(btnAdd)
btnDel = QtWidgets.QPushButton("刪除記錄(&A)")
btnDel.clicked.connect(delRecord)
vbox.addWidget(btnDel)
window.setLayout(vbox)
window.resize(430, 250)
window.show()
sys.exit(app.exec_())
