使用QSortFilterProxyModel过滤QTableView中的结果

时间:2018-08-16 11:57:59

标签: python python-3.x pyqt5

我有一个问题,实际上有很多问题,但是我希望您可以帮助我解决这个问题:)

我正在尝试从数据库中过滤列,但我成功地在一个列中进行了过滤,但是如果第一个= 0的结果转到另一个,则我需要同时过滤三个列,如果第二个列的result = 0转到了第三栏...

这是我尝试过的代码: 脚本显示来自数据库的数据,但不过滤结果。我哪里错了?

代码:

from PyQt5 import QtWidgets,QtSql,QtGui,QtCore
from PyQt5.QtCore import *

def createConnection():
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("imenik.db")
    if not db.open():
        QtWidgets.QMessageBox.critical(None, "Cannot open database",
                    "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
    return True

class MySortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self, parent=None):
        super(MySortFilterProxyModel, self).__init__(parent)

    def filterAcceptsRow(self, sourceRow, sourceParent):
        index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
        index1 = self.sourceModel().index(sourceRow, 1, sourceParent)
        index2 = self.sourceModel().index(sourceRow, 2, sourceParent)

        return ((self.filterRegExp().indexIn(self.sourceModel().data(index0)) >= 0
                 or self.filterRegExp().indexIn(self.sourceModel().data(index1)) >= 0
                or self.filterRegExp().indexIn(self.sourceModel().data(index2)) >= 0))



class Klasa(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Klasa, self).__init__(parent)
        #podesavanje velicine okvira ujedno i velicine treevjuva jer se tri vjuv razvlaci do ivica Boksa

        self.proxyModel = MySortFilterProxyModel(self)
        self.verLW = QtWidgets.QWidget(self)
        self.verLW.setGeometry(QtCore.QRect(60,120,1000,490))
        #dodjeljuje tri vjuv prethodno definisanom okviru
        lay = QtWidgets.QVBoxLayout(self.verLW)
        #kreira liniju za unos teksta za pretragu
        self.lineEdit = QtWidgets.QLineEdit(self)
        self.lineEdit.setGeometry(QtCore.QRect(70, 100, 351, 20))
        self.lineEdit.textChanged.connect(self.textFilterChanged)

        self.tableView = QtWidgets.QTableView()

        #dodjeljuje okviru self.tableView
        lay.addWidget(self.tableView)
        #pravi promjenjivu za pretragu baze podataka
        self.model = QtSql.QSqlQueryModel()
        self.model.setQuery("SELECT Lokacija,Kancelarija,Prezime,Ime,Telefon,Lokal,Fax,Oblast FROM telImenik")
        #upisuje rezultate pretrage baze u self.tableView
        self.tableView.setModel(self.model)

        #odredjuje sirinu kolona u self.tableView-u prva kolona je 0-nulta,id nema potrebe dodavati jer ga sam odredjuje
        self.tableView.setColumnWidth(0, 150)
        self.tableView.setColumnWidth(1, 65)
        self.tableView.setColumnWidth(2, 100)
        self.tableView.setColumnWidth(3, 80)
        self.tableView.setColumnWidth(4, 80)
        self.tableView.setColumnWidth(5, 40)
        self.tableView.setColumnWidth(6, 80)
        self.tableView.setColumnWidth(7, 340)

    def setSourceModel(self):
        self.proxyModel.setSourceModel(self.model)
        self.tableView.setModel(self.proxyModel)

    def textFilterChanged(self,text):
        regExp = QRegExp(self.lineEdit.text())
        self.proxyModel.setFilterRegExp(regExp)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    if not createConnection():
        sys.exit(-1)
    w = Klasa()
    w.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

问题很简单:您从未使用过代理,因此永远也不会进行过滤,在下一部分中,我向您展示了一种更为优雅的解决方案:

from PyQt5 import QtCore, QtGui, QtWidgets, QtSql

def createConnection():
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("imenik.db")
    if not db.open():
        QtWidgets.QMessageBox.critical(None, "Cannot open database",
                    "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
    return True

class MySortFilterProxyModel(QtCore.QSortFilterProxyModel):
    def filterAcceptsRow(self, sourceRow, sourceParent):
        ixs = [self.sourceModel().index(sourceRow, i, sourceParent) for i in range(3)]
        return any(self.filterRegExp().indexIn(ix.data()) >= 0 for ix in ixs)


class Klasa(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Klasa, self).__init__(parent)
        #podesavanje velicine okvira ujedno i velicine treevjuva jer se tri vjuv razvlaci do ivica Boksa

        self.proxyModel = MySortFilterProxyModel(self)
        #dodjeljuje tri vjuv prethodno definisanom okviru
        lay = QtWidgets.QVBoxLayout(self)
        #kreira liniju za unos teksta za pretragu
        self.lineEdit = QtWidgets.QLineEdit()
        self.lineEdit.textChanged.connect(self.textFilterChanged)

        self.tableView = QtWidgets.QTableView()

        #dodjeljuje okviru self.tableView
        lay.addWidget(self.lineEdit)
        lay.addWidget(self.tableView)
        #pravi promjenjivu za pretragu baze podataka
        self.model = QtSql.QSqlQueryModel()
        self.model.setQuery("SELECT Lokacija,Kancelarija,Prezime,Ime,Telefon,Lokal,Fax,Oblast FROM telImenik")
        #upisuje rezultate pretrage baze u self.tableView
        self.proxyModel.setSourceModel(self.model)
        self.tableView.setModel(self.proxyModel)

        #odredjuje sirinu kolona u self.tableView-u prva kolona je 0-nulta,id nema potrebe dodavati jer ga sam odredjuje
        for i, width in enumerate([150, 65, 100, 80, 90, 40, 80, 340]):
            self.tableView.setColumnWidth(i, width)

    def setSourceModel(self):
        self.proxyModel.setSourceModel(self.model)
        self.tableView.setModel(self.proxyModel)

    def textFilterChanged(self,text):
        regExp = QtCore.QRegExp(self.lineEdit.text(), QtCore.Qt.CaseInsensitive)
        self.proxyModel.setFilterRegExp(regExp)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    if not createConnection():
        sys.exit(-1)
    w = Klasa()
    w.show()
    sys.exit(app.exec_())

或者就像我说的,最简单的方法是使用WHERELIKE进行SQL过滤:

from PyQt5 import QtCore, QtGui, QtWidgets, QtSql

def createConnection():
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("imenik.db")
    if not db.open():
        QtWidgets.QMessageBox.critical(None, "Cannot open database",
                    "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
    return True

class Klasa(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Klasa, self).__init__(parent)
        #podesavanje velicine okvira ujedno i velicine treevjuva jer se tri vjuv razvlaci do ivica Boksa
        #dodjeljuje tri vjuv prethodno definisanom okviru
        lay = QtWidgets.QVBoxLayout(self)
        #kreira liniju za unos teksta za pretragu
        self.lineEdit = QtWidgets.QLineEdit()
        self.lineEdit.textChanged.connect(self.textFilterChanged)

        self.tableView = QtWidgets.QTableView()

        #dodjeljuje okviru self.tableView
        lay.addWidget(self.lineEdit)
        lay.addWidget(self.tableView)
        #pravi promjenjivu za pretragu baze podataka
        self.model = QtSql.QSqlQueryModel()
        #upisuje rezultate pretrage baze u self.tableView
        self.tableView.setModel(self.model)

        #odredjuje sirinu kolona u self.tableView-u prva kolona je 0-nulta,id nema potrebe dodavati jer ga sam odredjuje
        for i, width in enumerate([150, 65, 100, 80, 90, 40, 80, 340]):
            self.tableView.setColumnWidth(i, width)
        self.textFilterChanged("")

    def setSourceModel(self):
        self.proxyModel.setSourceModel(self.model)
        self.tableView.setModel(self.proxyModel)

    def textFilterChanged(self,text):
        query = QtSql.QSqlQuery()
        query.prepare("SELECT * FROM telImenik WHERE Lokacija LIKE ? OR Kancelarija LIKE ? OR Prezime LIKE ?")
        query.addBindValue("{}%".format(text))
        query.addBindValue("{}%".format(text))
        query.addBindValue("{}%".format(text))
        query.exec_()
        self.model.setQuery(query)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    if not createConnection():
        sys.exit(-1)
    w = Klasa()
    w.show()
    sys.exit(app.exec_())
相关问题