gpt4 book ai didi

c++ - Qt:QGraphicsScene::addText 内存泄漏?

转载 作者:行者123 更新时间:2023-11-30 04:13:59 24 4
gpt4 key购买 nike

我正在尝试为这样的时间线制定规则:

Timeline

我有一个 QGraphicsView,我在其中放置了一个 QGraphicsScene,我在其中添加了 QGraphicsItems,例如线条和一些标签。

我仅在缩放发生变化时(而不是在 paintEvent 引发时)才将元素添加到场景中。

为了添加时间标签,我使用:

    QString label = "00:14"; // For example
int posX = ... // Here I calculate the position of the label
scene->addText(label,QFont("Arial",8))->setPos(posX,-1);

当我必须重新绘制规则时,我会:

    qDeleteAll(scene->items());

在开头,然后再次添加标签和线条。

我意识到我的表现很差。我的场景有大约 8k 个元素(在线和标签之间),所以我使用 Valgrind 来检查问题。

它表明“可能”在我向场景添加文本的行中存在内存泄漏。我有一些消息看起来像:

    2,165,760 bytes in 470 blocks are possibly lost in loss record 9,922 of 9,923
in TimelineWidget::drawRule() in Timeline/timelinewidget.cpp:166
1: realloc in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
2: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
3: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
4: QTextDocument::setPlainText(QString const&) in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
5: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
6: QGraphicsTextItem::QGraphicsTextItem(QString const&, QGraphicsItem*, QGraphicsScene*) in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
7: QGraphicsScene::addText(QString const&, QFont const&) in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.3
8: TimelineWidget::drawRule()

这只会发生在 addText 调用中,不会发生在 addLine 调用中。

我正在使用 Qt 4.8,我的问题是:

  • 那些内存泄漏是真的吗?

  • 我做错了什么吗?

  • 是否有其他/更好的方法来实现我的规则?

提前致谢!

最佳答案

我建议以下所有内容:

  1. 代替 qDeleteAll(scene->items()),只需清除场景:

    scene->clear();
  2. 如果您不显示富文本,请使用 scene->addSimpleText

  3. 对于简单、重复的项目,例如一组具有固定间距的行,创建可以重复使用的自定义项目。与为每一行创建图形场景项相比,这些将更快并且开销要低得多。就绘制线的数量而言,内存、索引、树遍历和查找开销将从 O(N) 下降到 O(1)

    假设您创建了一个水平排列的自定义项:| | | | | | | | |。该项目只是绘制固定数量的线条。您可以调整项目的大小以更改线条的高度和它们跨越的水平区域。请记住在您的 paint() 方法中重置画笔,因为默认画笔将重新缩放,因此可能非常宽。

    可以通过叠加三个项目获得带有主要和次要刻度的简单未标记标尺:两个线阵列和一条水平线。

您可能还想重新构建处理场景的方式。到目前为止,您将场景视为整个时间线的模型。相反,您应该至少将其中的一部分视为 View 模型。

时间轴有两个主要元素:规则和剪辑预览。

当您在给定的缩放级别滚动规则时,您会注意到总是有相同数量的线和标签可见。唯一发生变化的是线条的轻微水平偏移,当然标签的值也会发生变化。

因此,不要让所有的线和所有的标签都出现在你的场景中,只需要尽可能多的适合当前 View ,调整它们在场景中的水平位置,使它们在正确的偏移处可见,然后修复标签文字。这就是使它成为 view model 的原因- 这是一个与特定 View 紧密相关的模型。底层抽象模型是一个很长的尺子,但我们只需要它是一个抽象模型,而不是真正的占用内存和其他资源的模型。

剪辑预览也可以在您滚动时从场景中动态添加和删除。这可能会为您节省大量内存,因为我假设您有很 multimap 像,其中大部分是不可见的。

您显示的示例屏幕截图存在一些用户设计问题:显示水平截断的重叠剪辑预览毫无意义。在任何给定的缩放级别,您都应该有一个您愿意显示的最小预览尺寸。显示那些窄的垂直像素条非常昂贵。下面是一个可能的算法来处理它。

假设预览项是从左到右排序的矩形。

  1. 从与视口(viewport)矩形相交的最左边的项目开始(当然,场景坐标中的所有内容)。使其成为 current_item

  2. 显示 current_item(将其添加到场景中)。

  3. 当它们与 current_item 重叠时,继续获取下一个项目。存储 last_overlapping_item(如果没有项目重叠,它可以为空)。

  4. 将当前项目保存在 previous_item 中。获取下一项并将其设为 current_item

  5. 如果 current_itemprevious_item 之间没有间隙,请清除 last_overlapping_item,因为它与相邻的当前项和先前项完全重叠。

  6. 显示 last_overlapping_item(如果有)(将其添加到场景中)。

  7. 如果 current_item 完全在视口(viewport)矩形之外,您就完成了。否则转到 2。

关于c++ - Qt:QGraphicsScene::addText 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19141113/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com