首页 > 解决方案 > 如何使用 QSqlRelationalTableModel 过滤 tableview 中的组合框项目?

问题描述

我有一个设置如下的表格视图:

self.table = QTableView()  
self.model = QSqlRelationalTableModel(self)  
self.model.setTable('main')
self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
self.model.setRelation(1, QSqlRelation("Names", "nameOfCm", "nameOfCm"))
self.model.setRelation(2, QSqlRelation("Types", "type_IDs", "typeOfCm"))
self.model.setRelation(8, QSqlRelation("Places", "placeName", "placeName"))
self.model.select()   
self.table.setModel(self.model)
self.table.setItemDelegate(QSqlRelationalDelegate(self.table))

通过使用 QSqlRelationalDelegate,我在表的某些列中有组合框。

第 1 列是一些电子元件(如晶体管或 IC 等)的名称。

第 2 列是这种电子元件的类型(例如,对于晶体管,我有 PNP、NPN 等。对于 IC,我有 Op-Amp、Micro 等)。

当我单击“类型”列中的组合框时,无论我在组合框“名称”列中选择了什么,它都会显示所有类型的电子元件。我想过滤这些项目,以便只有组合框“名称”的相关项目显示在组合框“类型”中。

例如,如果我从“名称”中选择晶体管,则组合框“类型”显示:NPN、PNP。如果我选择 IC,组合框“类型”显示:Micro、Op_Amp。

这是简化的代码:

 import sys
 from PyQt5.QtCore import Qt
 from PyQt5.QtWidgets import *
 from PyQt5.QtSql import *

connectDB = QSqlDatabase.addDatabase("QSQLITE")
connectDB.setDatabaseName('test.db')
connectDB.open()
query = QSqlQuery()
createNameTable='CREATE TABLE IF NOT EXISTS "Names" ("nameOfCm" TEXT,   PRIMARY KEY("nameOfCm"))'
createTypeTable='CREATE TABLE IF NOT EXISTS "Types" ("type_IDs" TEXT,   "typeOfCm"  TEXT,PRIMARY KEY("type_IDs"))'
createMainTable='CREATE TABLE IF NOT EXISTS "main" ("partnumber" TEXT,"name" TEXT,"type" TEXT,PRIMARY KEY("partnumber"))'

query.exec(createNameTable)
query.exec(createTypeTable)
query.exec(createMainTable)
query.exec("INSERT INTO Names (nameOfCm) VALUEs ('IC')")
query.exec("INSERT INTO Names (nameOfCm) VALUEs ('Transistor')")
query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('Transistor1','NPN')")
query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('Transistor2','PNP')")
query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('IC1','Op_AMP')")
query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('IC2','Micro')")

class main (QMainWindow):
def __init__(self):
    super(main,self).__init__()
    self.setWindowTitle('My Electronic Inventory v: 0.1')
    self.setGeometry(10, 10, 400 , 500)
    self.UI()
    self.show()        
    self.databaseIsConect()

def UI(self):

    self.mainCentralWidget =        QWidget()
    self.mainLayout =               QVBoxLayout()
    self.setCentralWidget(self.mainCentralWidget)
    self.centralWidget().setLayout(self.mainLayout)

    self.newComponentButton=         QPushButton("Add component")
    self.newComponentButton.clicked.connect(self.newComponentButtonClicked)

    self.table=   QTableView()  
    self.model = QSqlRelationalTableModel(self) 
    self.model.setTable('main')
    self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
    self.model.setRelation(1, QSqlRelation("Names", "nameOfCm", "nameOfCm"))
    self.model.setRelation(2, QSqlRelation("Types", "type_IDs", "typeOfCm"))
    self.model.select()   
    self.table.setModel(self.model)
    self.table.setItemDelegate(QSqlRelationalDelegate(self.table))
    self.table.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.AnyKeyPressed)
    self.model.setHeaderData(0,Qt.Horizontal,('Part Number'))
    self.model.setHeaderData(1,Qt.Horizontal,('Name'))
    self.model.setHeaderData(2,Qt.Horizontal,('Type'))

    self.mainLayout.addWidget(self.newComponentButton)
    self.mainLayout.addWidget(self.table)

def databaseIsConect(self):
    if connectDB.isOpen():
        print("Databsae Is Connected")
    else:
        print("Erorr!. Databsae Is Not Connected")
def newComponentButtonClicked(self):
    row = self.model.rowCount()
    self.model.insertRow(row)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = main()
    sys.exit(app.exec_())

经过一番尝试,我设法通过继承 QSqlRelationalTableModel 解决了部分问题:

class mysqlmodel(QSqlRelationalTableModel):
    def __init__(self, parent):
        super().__init__()

    def setData(self, item, value, role):

        super().setData(item,value, role)
        a= item.siblingAtColumn(1).data()
        self.relationModel(2).setFilter("type_IDs like '"+a+"%'")
        return True

这适用于我的问题,但存在问题:

  1. 在第一次运行时,如果您想更改组合框 2 中的项目,它会显示所有选项,但修改后它显示只有项目属于组合框 1 中的项目。
  2. 如果您更改第 2 行的组合框 2 中的项目,那么您想更改第 3 行的组合框 2 中的项目,它会显示“上一个”行的选项,除非您提交该选项(例如通过按 Enter 按钮或单击某处else 在表中)然后自动更改为当前行的选项,现在您可以选择正确的项目。

标签: pythonpyqt5qtableviewqcombobox

解决方案


您必须为组合框类型创建一个 qsqlrelationaltablemodel 以设置与名称为表的关系。当名称选择时,Combobox类型的过滤器模型。


推荐阅读