响应式QGraphicsWidget

时间:2017-02-02 11:07:16

标签: qt qgraphicsitem qgraphicsscene qlayout qgraphicswidget

我的问题是一个简单但令人烦恼的用户体验损坏一个。我试图在QGraphicsItem上展示大量(10万)自定义QGraphicsScene。我还需要QGraphicsLayout,但据我所知,不能简单地在场景上放置布局,因为必须在QGraphicsWidget上设置布局,然后将小部件添加到场景中。

现在,当我需要加载大量项目并准备显示时,场景只是空着,因为我无法无效重绘前面提到的QGraphicsWidget。只有最后它才能被添加到场景中,否则将不会显示任何后续更改。

目标:为场景添加某种布局管理 - > {准备项目 - >将项目添加到布局 - >显示 - >准备一个项目 - >}重复...

但我拥有的是: {准备一个项目 - >准备另一个项目 - >}重复... - >将所有内容添加到布局中 - >在场景上设置布局管理 - >显示

所以问题是:有什么方法可以为场景创建一个响应式布局/容器,一个在添加新子项后重新绘制自己的布局/容器?

2 个答案:

答案 0 :(得分:0)

从Qt手册:

  

当场景改变时(例如,当项目移动或被转换时)   QGraphicsScene发出changed()信号。

没有提到addItem()和removeItem()。希望这些也包括在内。

如果是这样,您可以应用以下内容:

信号处理程序可以“捕获”该变化并请求重新绘制(例如,通过invalidate())场景。 (Un-)幸运的是,这不会立即重新绘制场景(使用其父视图),但会对重绘事件进行排队。因此,在事件循环再次通过之前,不会执行实际的重绘。

(事件循环是QApplication的一部分。如果你在用户界面发起的命令中停止你的应用程序,你会在callstack中找到这样的东西:

Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags)
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags)
Qt5Cored.dll!QCoreApplication::exec()

您可以通过调用QApplication :: processEvents()来强制执行此操作。 (它甚至是静态的。)AFAIK,如果事件循环是嵌套的,通常没有问题,因为它们已经为此做好了准备(只要没有形成非终止的递归)。

然而,这可能需要进行一些微调,因为太多的重绘可能会大大减慢您的应用程序。

答案 1 :(得分:0)

管理找到我的错误。它是我为QGraphicsWidget创建的自定义布局。

正如doc所说的设置布局:

  

当前由布局或其所有子布局管理的所有窗口小部件都会自动重新分配给此项目。然后布局无效,并根据此项的geometry()和contentsMargins()调整子窗口小部件几何。未按布局明确管理的子项在分配给此窗口小部件后仍不受布局影响。

将布局设置为窗口小部件后,添加到窗口小部件的任何新项目都不会重新设置到窗口小部件,因此它们不会受到影响而不会显示。

在插入布局的每个项目上调用QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem* newItem) link解决了我的问题。