QAbstractItemModel:为什么在将大量项目插入模型时发出 dataChanged 和插入行信号如此缓慢?
Stackoverflow 中的所有 Qt 模型/视图编程专家大家好。我正在从事的项目要求我为 XML 数据定义一个 QAbstractItemModel 派生模型。之前我在实现这个模型的过程中遇到问题的时候曾在这里问过一个问题: 从通过源模型功能的源模型
该模型目前在应用程序中运行得很好,除了一些我不知道如何解决的性能问题。其中的函数之一 应用程序是通过设置 Max Num 和 Rand 数来添加 Frame 元素 xml 节点。每个 Frame 元素将具有分别从 0 到 MaxNum - 1 和 0 到 MaxRand-1 的 Num 和 Rand 编号。此外,我需要为 Rand=0 和 Rand=MaxRand-1 元素分别添加一个子参数元素。简要说明如下:
For Max Num=100, Max Rand=50
<Frame Num="0" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="0" Rand="1"/>
<Frame Num="0" Rand="2"/>
...
<Frame Num="0" Rand="48"/>
<Frame Num="0" Rand="49">
<Parameter Value="true"/>
</Frame>
<Frame Num="1" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="1" Rand="1"/>
<Frame Num="1" Rand="2"/>
...
<Frame Num="1" Rand="48"/>
<Frame Num="1" Rand="49">
<Parameter Value="true"/>
</Frame>
...
<Frame Num="99" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="99" Rand="1"/>
<Frame Num="99" Rand="2"/>
...
<Frame Num="99" Rand="48"/>
<Frame Num="99" Rand="49">
<Parameter Value="true"/>
</Frame>
当 MaxNum 和 MaxRand 都很小时(即 Frame 元素总数约为 50)时,应用程序运行良好。但是,当元素计数超过 500 左右时,通过 QAbstractItemModel 函数添加 Frame 元素变得非常痛苦且困难。指数慢。 GUI 冻结了很长一段时间,以至于我大部分时间都放弃了等待。
主要更新:
我已经找到了在模型中插入大量(例如 1000 个)项目时导致速度变慢的原因。我在插入每个项目时调用一次 insertRow(row,parent) 和 setData() ,由于这些函数内部发出的信号,这非常昂贵。
我已将代码修改为 insertRows(row, 1000, Parent) 并定义了一个新的silentSetData(),它不会发出 dataChanged(currIndex, currIndex)。我还添加了一个名为 notificationDataChanges(startRow, endRow, ParentIndex) 的新公共函数,该函数依次针对给定的数据范围发出一次 dataChanged 信号。一切都很好,但现在调用者类需要在插入整组数据后显式调用notifyDataChanges。
现在我想知道为什么发出 dataChanged 信号如此昂贵?一次在模型中插入/更改大量项目时,是否有人尝试过其他方法来解决这个问题?
Hi to all Qt Model/view programming gurus here in Stackoverflow. The project I am working on requires me to define a QAbstractItemModel-derived model for XML data. I had previously asked a question here when I ran into a problem during implementation of this model:
QSortFilterProxyModel crashes when deleting a row from the source model via the source model function
The model is currently doing its job pretty well in the application except for some performance issues which I do not know how to solve. One of the functions in this
application is to add Frame element xml nodes by setting the Max Num and Rand numbers. Each Frame element will have both Num and Rand numbers running from 0 to MaxNum - 1 and 0 to MaxRand-1 respectively. Furthermore I will need to add a child Parameter element for Rand=0 th and Rand=MaxRand-1 th element each. An abbreviated illustration is as follows:
For Max Num=100, Max Rand=50
<Frame Num="0" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="0" Rand="1"/>
<Frame Num="0" Rand="2"/>
...
<Frame Num="0" Rand="48"/>
<Frame Num="0" Rand="49">
<Parameter Value="true"/>
</Frame>
<Frame Num="1" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="1" Rand="1"/>
<Frame Num="1" Rand="2"/>
...
<Frame Num="1" Rand="48"/>
<Frame Num="1" Rand="49">
<Parameter Value="true"/>
</Frame>
...
<Frame Num="99" Rand="0">
<Parameter Value="false"/>
</Frame>
<Frame Num="99" Rand="1"/>
<Frame Num="99" Rand="2"/>
...
<Frame Num="99" Rand="48"/>
<Frame Num="99" Rand="49">
<Parameter Value="true"/>
</Frame>
The application works fine when both MaxNum and MaxRand are small i.e. total number of Frame elements around 50. However, when the element count goes beyond 500 or so, the adding of Frame elements via QAbstractItemModel functions becomes painfully and exponentially slow. The GUI freezes for a long period of time, to the point where I gave up waiting most of the time.
MAJOR UPDATE:
I have found out what is causing the slowdown when inserting a large number of, say 1000 items into my model. I was calling both insertRow(row, parent) and setData() once per item inserted, which turns out to be very expensive due to the signals emitted inside these functions.
I have modified the code to insertRows(row, 1000, parent) instead and defined a new silentSetData() that does not emit a dataChanged(currIndex, currIndex). I have also included a new public function called notifyDataChanges(startRow, endRow, parentIndex) which in turns emit the dataChanged signal once for the given range of data. All is fine but now the caller class will need to explicitly call notifyDataChanges after the whole set of data is inserted.
Now I am wondering why is emitting dataChanged signals so expensive? Has anyone tried other means to overcome this problem when inserting/changing large number of items in the model at once?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
另一种方法是显式重置模型数据结构。例如,在我的一个模型中,数据用 QStringList 表示。我已经实现了一个重置模型中数据的函数。例如:
我想这种方法也适用于您的情况。
Another way to do that is to explicitly reset the model data structures. For example in one of my models the data is represented with a
QStringList
. I have implemented a function that resets the data in the model. For example:I would imagine this approach is also applicable in your case.