setModel无法触发modelReset事件的解决方案
前言
在使用PyQt5
时,发现setModel
无法触发modelReset
事件,导致在使用QTableView
时,无法动态更新数据。
发现问题
在这篇文章的基础上,我们将CustomTableView
与MainWindow
分离开。
在进一步实现需求的过程中,需要动态更新QStandardItemModel
。于是在CustomTableView
文件中通过model()
获取QStandardItemModel
,在MainWindow
中直接定义QStandardItemModel
便于获取数值。
这样做似乎是没什么问题的,至少在打印地址的时候,无论是model
还是model()
,地址都是相同的。
但是在后续的过程中我们发现,延时问题依然存在。
例如,我在启动时获得了所有数据存入model
,经过一些业务逻辑后筛选出了一些数据,获得了new_model
。这个过程成功出发了model.modelReset
事件。
在新的业务逻辑需要还原数据的时候,从new_model
还原model
的过程中,并没能触发model.modelReset
事件。
解决方案
实际上解决方案比较简单。如果没能触发,那就手动触发:
1 | model().modelReset.emit() |
在源码部分,Qt
官方并没有做出解释,在QTableView
中没有提到setModel
的使用方法与modelReset
事件的触发过程。
但是呢,相对于直接使用setModel
更新数据,官方看起来似乎更推荐使用insertRows
与removeRows
来对model
进行更新。
以下是官方给定的一个案例。
1 | def removeRows(self, position, rows, parent): |
官方的说明是:
The
beginRemoveRows()
function is always called before any underlying data is removed, and specifies the first and last rows to be removed. This allows other components to access the data before it becomes unavailable. After the rows have been removed, the model emitsendRemoveRows()
to finish the operation and let other components know that the dimensions of the model have changed.
不难看出,在remove
的过程中,model
会通过beginRemoveRows()
和endRemoveRows()
两个信号槽告知其他组件,进而做出其他的操作。
所以相对的,不难猜出在setModel
的过程中,也是需要显式声明,否则无法触发。