2017-11-09 9 views
0

QtableViewを使用してログを表示し、列でフィルタリングするためにQSortFilterProxyModelが使用されています。特定の値を使用して1つの列をフィルタリングし、フィルタリングされたデータで2番目の列をフィルタリングしようとすると、最後のフィルタがリセットされ、2番目の列のフィルタに対応するデータが表示されます。 Qtableviewで複数の列フィルタを実現したい。Qtableviewで複数の列をフィルタリングする方法は?

コードスニペット:

self.tableView = QTableView() 
self.model = QtGui.QStandardItemModel(self) 
self.proxy = QtGui.QSortFilterProxyModel(self) 
self.proxy.setSourceModel(self.model) 
self.tableView.setModel(self.proxy) 

def updateTable(self): 
    self.model.invisibleRootItem().appendRow(,,,,) 

def filterTable(self, stringAction, filterColumn): 
    filterString = QtCore.QRegExp( stringAction, 
            QtCore.Qt.CaseSensitive, 
            QtCore.QRegExp.FixedString 
            ) 

    self.proxy.setFilterRegExp(filterString) 
    self.proxy.setFilterKeyColumn(filterColumn) 

答えて

2

あなたはQSortFilterProxyModelから継承するクラスを作成し、少なくとも一つの項目がすべて満たされた場合に満足し、真でない場合はFalseが返されfilterAcceptsRowメソッドを上書きする必要があります。

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 

例:

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_()) 
+0

クールな男,,,,それが動作,,,感謝:) –

+0

ねえか一度にすべての列フィルタをクリアするには?フィルターのリセットやフィルターのクリアなどのオプションはありますか? @eyllanesc –

+1

個々の場合と同じですが、空の文字列をフィルタリングする列に渡す必要があります – eyllanesc

関連する問題