如何在 QTableView 中应用过滤器后显示特定行

How to show specific row after apply filter in QTableView

如何在 QTableView 中应用过滤器后显示隐藏行。我附上了下面的代码,并为过滤值“2”的第二列应用了过滤器。它正在按要求工作。如果要在第二列中显示包含值“3”的隐藏行。它没有显示该行。我使用匹配命令来查找行。一切正常。但行没有显示。请帮我解决这个问题。

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

class TableModel(QAbstractTableModel):
    def __init__(self, data):super().__init__();self._data = data
    def data(self, index, role):
            if role == Qt.ItemDataRole.DisplayRole or role == Qt.EditRole :return self._data[index.row()][index.column()]
    def rowCount(self, index):return len(self._data)
    def columnCount(self, index):return len(self._data[0])

class tableview(QTableView):
    def __init__(self):
        super().__init__()
        self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
        self.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self.horizontalHeader().setStyleSheet("::section{Background-color:lightgray;border-radius:10px;}")
        self.smodel = QSortFilterProxyModel()
        self.smodel.setFilterKeyColumn(1)
        self.setModel(self.smodel)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
        self.smodel.setSourceModel(TableModel([[1,2],[1,2],[1,3],[1,4]]))
        self.smodel.setFilterFixedString('2')
    def find(self,key):
        start = self.smodel.index(0, 1)
        matches = self.smodel.sourceModel().match(start,Qt.DisplayRole,key,hits=-1,flags=Qt.MatchExactly)
        for match in matches:self.showRow(match.row())

app = QApplication([])
table=tableview()
table.show()
b=QPushButton();b.clicked.connect(lambda:table.find('3'))
b.show()
app.exec_()

当前结果

按下按钮所需的结果

我认为 filtershowRow()/hideRow() 可以以不同的方式工作 - 所以他们一起工作可能会有问题。

Filter 在发送到 TableView 之前删除数据,showRow()/hideRow() 直接删除 TableView 中的行。如果您想使用 showRow,那么您可能需要清除 filter、隐藏所有行并显示带有 23

的行

但是使用过滤器可能更简单

仅显示具有选定值的行 (key = "3")

smodel.setFilterFixedString(key)

清除过滤器并显示所有行

smodel.setFilterFixedString("")

要过滤少数值,您可以使用 regex

self.smodel.setFilterRegExp("2|3")

或者您可以将值保留在列表中

filtered = ["2", "3"]

self.smodel.setFilterRegExp( "|".join(filtered) )

最少的工作代码。

我的按钮切换行 "3" - 第一次点击显示行,第二次点击隐藏行,依此类推

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

class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super().__init__()
        self._data = data
        
    def data(self, index, role):
        if role == Qt.ItemDataRole.DisplayRole or role == Qt.EditRole :
           return self._data[index.row()][index.column()]
        
    def rowCount(self, index):
        return len(self._data)
    
    def columnCount(self, index):
        return len(self._data[0])

class tableview(QTableView):
    def __init__(self):
        super().__init__()
        self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
        self.setFocusPolicy(Qt.FocusPolicy.NoFocus)

        self.horizontalHeader().setStyleSheet("::section{Background-color:lightgray;border-radius:10px;}")
        self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)

        self.smodel = QSortFilterProxyModel()
        self.setModel(self.smodel)
        self.smodel.setSourceModel(TableModel([[1,2],[1,2],[1,3],[1,4]]))
        self.smodel.setFilterKeyColumn(1)

        self.filtered = ["2"]
        
        #self.smodel.setFilterFixedString("2")
        self.smodel.setFilterRegExp( "|".join(self.filtered) )
        
    def find(self, key):
        print('find:', key)
        
        if key in self.filtered:
            self.filtered.remove(key)
        else:
            self.filtered.append(key)

        #self.smodel.setFilterFixedString("")   # clear filter - show all rows
        #self.smodel.setFilterFixedString(key)  
        #self.smodel.setFilterRegExp("2|3")
        
        self.smodel.setFilterRegExp( "|".join(self.filtered) )
        
# --- main ---

app = QApplication([])

table = tableview()
table.show()

button = QPushButton(text="Toggle: 3")
button.clicked.connect(lambda:table.find('3'))
button.show()

app.exec()

顺便说一句:

我只看到一个问题:有些字符在 regex 中有特殊含义,所以添加 ie。点 .filtered 可能会隐藏所有行,因此可能需要使用 \..

| ( ) [ ] ^ $ 等也会出现同样的问题