Python定时刷新QTableView实现QSortFilterProxyModel持久过滤
问题根因
你遇到的定时刷新后过滤失效问题,核心是代码逻辑把一次性初始化操作放到了周期执行的刷新方法里:
- 每次
updateAccountTable触发时都会新建一个全新的mysortingproxy实例,新实例默认过滤规则为空,自然不会保留之前的过滤状态 - 每次刷新都重复给输入框绑定
textChanged信号,运行时间长了会出现一次输入触发多次过滤的性能问题 - 每次刷新都重新给表格视图绑定模型,完全属于冗余操作,视图只需要在初始化时绑定一次模型即可,后续数据变更通过模型的信号通知视图刷新。
修复步骤
1. 把模型、代理、信号绑定逻辑移到窗口初始化阶段
所有只需要执行一次的逻辑,全部放到MainUi的构造函数中,不要放到周期刷新的方法里:
class MainUi(QMainWindow): def __init__(self, parent=None): super().__init__(parent) # 省略其他界面初始化代码... # 初始化源数据模型,仅创建一次 self.accountTableModel = AccountTableModel(self.data, self.scalping, self) # 初始化自定义排序过滤代理,仅创建一次 self.proxyModel = mysortingproxy(self) self.proxyModel.setFilterKeyColumn(0) # 指定第一列为过滤列 self.proxyModel.setSourceModel(self.accountTableModel) # 给表格视图绑定模型,仅设置一次 self.tableView_Account.setModel(self.proxyModel) self.tableView_Account.setSortingEnabled(True) self.tableView_Account.verticalHeader().setVisible(False) # 绑定过滤输入框信号,仅绑定一次 # 普通文本匹配推荐用setFilterFixedString性能更好,需要正则匹配再换setFilterRegExp self.lineEdit_Find.textChanged.connect(self.proxyModel.setFilterFixedString)
2. 改造周期刷新方法,仅更新源模型数据
把updateAccountTable里所有重建模型、代理、绑定信号的代码全部删除,只保留数据更新逻辑,不要新建任何模型实例:
def updateAccountTable(self): # 仅更新源模型内部存储的数据,不要新建模型/代理实例 self.accountTableModel.updateData(self.data, self.scalping)
给自定义的AccountTableModel新增数据更新方法,更新内部数据后通知视图刷新,代理模型会自动复用已有的过滤、排序规则:
class AccountTableModel(QAbstractTableModel): # 省略你已实现的rowCount/columnCount/data等方法... def updateData(self, new_data, new_scalping): # 更新内部持有的数据引用 self.data = new_data self.scalping = new_scalping # 通知视图数据已变更,触发界面重绘、代理重新过滤排序 self.layoutChanged.emit()
3. 特殊场景兼容方案
如果你的业务场景确实需要每次刷新重建源模型(比如数据列结构会动态变化),那重建代理后必须手动把当前输入框的过滤值重新设置给新代理,否则新代理默认过滤规则为空:
# 不推荐,性能比复用模型差,仅作为兼容方案 def updateAccountTable(self): self.accountTableModel = AccountTableModel(self.data, self.scalping) proxyModel = mysortingproxy() proxyModel.setFilterKeyColumn(0) # 手动把当前输入框的过滤值设置给新代理 proxyModel.setFilterFixedString(self.lineEdit_Find.text()) proxyModel.setSourceModel(self.accountTableModel) self.tableView_Account.setModel(proxyModel) self.tableView_Account.setSortingEnabled(True) self.tableView_Account.verticalHeader().setVisible(False)
注意用这个方案必须先断开之前的信号连接,否则会出现信号重复绑定问题,优先选择第一种复用模型的方案。
内容的提问来源于stack exchange,提问作者Stéphane REY
相关产品推荐
相关产品推荐

