如何在QTableView应用过滤器后显示指定的隐藏行?
问题原因
QSortFilterProxyModel的默认过滤是模型层面的过滤,不符合规则的行不会被代理模型暴露给上层视图,你调用的showRow()是视图层面控制行显隐的API,仅对视图主动隐藏的行有效,对被代理过滤掉的行完全没用。- 你调用源模型的
match()方法时,传入了代理模型的索引作为搜索起点,不同模型的索引不能直接跨用,这部分搜索逻辑本身存在错误。
解决方法
重写QSortFilterProxyModel的过滤逻辑,维护允许显示的关键词集合,需要新增显示内容时更新集合后触发过滤刷新即可,修改后完整代码如下:
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 CustomFilterProxy(QSortFilterProxyModel): def __init__(self): super().__init__() # 存储允许显示的第二列值 self.allowed_vals = {"2"} self.filter_col = 1 def filterAcceptsRow(self, source_row, source_parent): # 重写过滤规则:值在允许集合内就显示 val = str(self.sourceModel().index(source_row, self.filter_col, source_parent).data()) return val in self.allowed_vals def add_allowed_val(self, val): # 新增允许显示的值,刷新过滤 self.allowed_vals.add(str(val)) self.invalidateFilter() 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 = CustomFilterProxy() 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]])) def find(self,key): start = self.smodel.sourceModel().index(0, 1) matches = self.smodel.sourceModel().match(start, Qt.DisplayRole, key, hits=-1, flags=Qt.MatchExactly) if matches: # 匹配到结果就把值加入允许显示集合 self.smodel.add_allowed_val(key) app = QApplication([]) table=tableview() table.show() b=QPushButton() b.clicked.connect(lambda:table.find('3')) b.show() app.exec_()
内容的提问来源于stack exchange,提问作者Viswa
相关产品推荐
相关产品推荐

