第一次填充 QTableWidget 时,一切都很好,但是当我重新填充它时,它明显变慢了
The first time a QTableWidget is populated, everything is fine, but when i repopulate it, it's significantly slower
代码:
populateTable()
{
tableWidget->clearContents();
tableWidget->setRowCount(stringList.size());
for(int i = 0; i < stringList.size(); ++i)
{
tableWidget->setItem(i, 0, new QTableWidgetItem(stringList.at(i)));
}
}
问题:
第一次运行 populateTable() 时,一切都很好。但接下来的时间,它的运行速度比以前慢得多。
讨论:
经过仔细测试,我怀疑clearContent()是问题所在。因为只需将代码从
tableWidget->clearContents();
自:
tableWidget->setRowCount(0);
解决了问题,但现在它又出现了另一个问题;将行计数设置为"0"似乎不会删除分配的堆 QTableWidgetItems,它似乎只是保留了项目的所有权,因此会留下内存泄漏。(或者至少我只是这么认为...
Qt在QTableWidget中的文档相当模糊,所以我并不完全知道clearContent()实际上做了什么。在文档中,它说"从视图中删除不在标题中的所有项目",这让我不禁要问,表格的内容只是隐藏吗?它被删除了吗?我不太确定。我的理论是 clearContent() 只隐藏项目,任何下一次填充表的尝试实际上都会删除并删除每个项目,然后分配一个新项目以在表上设置,这反过来又是一项昂贵的操作。
另一个有趣的事情是,Qt关于QTableWidget的文档表明,填充QTableWidget的正确方法是在堆上分配一个QTableWidgetItem,然后使用setItem()将其设置在表单元格上,就像我在上面的代码中介绍的那样,我觉得这很奇怪......
总结:
有没有另一种方法来填充和重新填充Qt表而不会遇到所有这些问题? 如果没有,有没有办法解决这些问题?
"Qt 关于 QTableWidget 的文档表明,填充 QTableWidget 的正确方法是在堆上分配一个 QTableWidgetItem,然后使用 setItem() 将其设置在表单元格上,就像我在上面的代码中介绍的那样,我觉得这很奇怪..."
我不觉得奇怪,考虑到 QTableWidget::setItem 的文档明确指出小部件拥有该项目的所有权!
"将行计数设置为'0'似乎不会删除堆分配的QTableWidgetItems,它似乎只是留下了项目的所有权,因此会留下内存泄漏。(或者至少我是这么认为的...
与其猜测它是否泄漏,不如创建自己的QTableWidgetItem子类...并将代码放在其析构函数中,以便您有一个放置断点的地方并确定。 或者,Qt源非常清晰。 setRowCount
调用removeRows
,这确实删除了QTableWidgetItems:
http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/itemviews/qtablewidget.cpp#line370
http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/itemviews/qtablewidget.cpp#line100
但这再次与QTableWidget的文档一致::setRowCount
将此模型中的行数设置为行。如果此值小于 rowCount(),则丢弃不需要的行中的数据。
你真的不应该看到clearContent()和setRowCount(0)之间的太大区别。 您是否生成了一个可重现的小示例,该示例未与任何大型程序纠缠在一起,以证明这种现象?
我注意到不仅在重新填充 QTableWidget 时普遍缓慢,而且在进行任何更改时也是如此。
例如,我有一个大约 1000 个单元格,通过 setCheckState() 在其上显示复选框。第一次通过检查/取消选中它们,它们很快。第二次通过,需要~15s,这是完全不能接受的。我在桌子上尝试了块信号(真/假),但没有任何效果。
诀窍是阻止模型上的信号,而不是桌子上的信号。该模型正在消耗CPU。
auto table = ui.tableWidget;
auto rows = table->rowCount();
auto cols = table->columnCount();
table->model()->blockSignals(true);
for (auto row = 0; row < rows; row++)
for (auto col = 0; col < cols; col++)
if (auto cb = table->item(row, col))
cb->setCheckState(Qt::CheckState::Checked);
table->model()->blockSignals(false);
table->model()->layoutChanged();//Required, or else you won't see your changes immediately.
- 在c++中用vector填充一个简单的动态数组
- 如何使用用户输入在C++中正确填充2D数组
- 如何找到大小'x'数组是否完全填充,在C++?
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 通过for循环使用用户输入填充列表
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 如何正确填充在堆上分配的二维数组?
- 将数字转换为填充字符串
- 有没有办法在一行中填充矢量图
- 在循环(C++)中用新指针填充映射
- 究竟什么是"位填充"或"填充位"?
- 如何创建一个新的二进制文件并用常量值填充它?
- 有没有一种方法可以全局填充新分配/删除分配
- 矢量填充比创建新矢量慢
- 马洛克与新 - 不同的填充
- WTableView中的QueryModel:请举例说明如何添加一行并用刚刚创建的新记录填充它
- 在单独的线程上填充、填充QTreeView树
- [C++]在此代码之前不存在的析构函数中引发的内存错误。尝试创建一个新的动态数组并填充它
- 在调整大小的动态数组中填充新元素
- 可以为新创建的对象自动填充protobuffer默认值