How to filter Multiple column in Qtableview?

后端 未结 2 560
悲哀的现实
悲哀的现实 2020-12-18 08:52

I\'m using QtableView to show my logs and to filter them by column, QSortFilterProxyModel is used. If i filter one column using certain value, and with the filtered data, i

2条回答
  •  清歌不尽
    2020-12-18 08:58

    You must create a class that inherits from QSortFilterProxyModel, and overwrite the filterAcceptsRow method where False is returned if at least one item is not satisfied and True if all are satisfied.

    class SortFilterProxyModel(QSortFilterProxyModel):
        def __init__(self, *args, **kwargs):
            QSortFilterProxyModel.__init__(self, *args, **kwargs)
            self.filters = {}
    
        def setFilterByColumn(self, regex, column):
            self.filters[column] = regex
            self.invalidateFilter()
    
        def filterAcceptsRow(self, source_row, source_parent):
            for key, regex in self.filters.items():
                ix = self.sourceModel().index(source_row, key, source_parent)
                if ix.isValid():
                    text = self.sourceModel().data(ix).toString()
                    if not text.contains(regex):
                        return False
            return True
    

    Example:

    def random_word():
        letters = "abcdedfg"
        word = "".join([choice(letters) for _ in range(randint(4, 7))])
        return word
    
    
    class Widget(QWidget):
        def __init__(self, *args, **kwargs):
            QWidget.__init__(self, *args, **kwargs)
            self.setLayout(QVBoxLayout())
    
            tv1 = QTableView(self)
            tv2 = QTableView(self)
            model = QStandardItemModel(8, 4, self)
            proxy = SortFilterProxyModel(self)
            proxy.setSourceModel(model)
            tv1.setModel(model)
            tv2.setModel(proxy)
            self.layout().addWidget(tv1)
            self.layout().addWidget(tv2)
    
            for i in range(model.rowCount()):
                for j in range(model.columnCount()):
                    item = QStandardItem()
                    item.setData(random_word(), Qt.DisplayRole)
                    model.setItem(i, j, item)
    
            flayout = QFormLayout()
            self.layout().addLayout(flayout)
            for i in range(model.columnCount()):
                le = QLineEdit(self)
                flayout.addRow("column: {}".format(i), le)
                le.textChanged.connect(lambda text, col=i:
                                       proxy.setFilterByColumn(QRegExp(text, Qt.CaseSensitive, QRegExp.FixedString),
                                                               col))
    
    
    if __name__ == '__main__':
        import sys
    
        app = QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

提交回复
热议问题