2017-11-09 2 views
0

QtableView를 사용하여 내 로그를 표시하고 열별로 필터링하려면 QSortFilterProxyModel이 사용됩니다. 특정 값을 사용하여 하나의 열을 필터링하고 필터링 된 데이터로 두 번째 열을 필터링하려고하면 마지막 필터가 재설정되고 두 번째 열의 필터에 해당하는 데이터가 표시됩니다. 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에서 상속하는 클래스를 만들고, 모두가 만족하는 경우 하나 개 이상의 항목을 만족하고 사실이 아닌 경우 거짓이 반환되는 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

관련 문제