使用 QQuickView 或 QQuickWidget 在 QWidget 应用程序中添加大量 QML 对象会带来性能问题

Posted

技术标签:

【中文标题】使用 QQuickView 或 QQuickWidget 在 QWidget 应用程序中添加大量 QML 对象会带来性能问题【英文标题】:Adding a high number of QML objects in a QWidget application using QQuickView or QQuickWidget poses performance problem 【发布时间】:2021-10-04 09:56:53 【问题描述】:

我正在开发一个 Qt 应用程序,用户可以在其中将 QML 对象添加到 QGraphicsScene 中。列出了可用的 QML 对象,用户可以添加任意数量的对象。

到目前为止,我使用的是 QQuickWidgets。 QGraphicsScene 包含一个***小部件,它是我创建的所有 QQuickWidgets 的父级。它工作正常,但我有一个性能问题。对象数量多时,应用程序开始变慢,并占用过多的 RAM 空间(我创建的第一个示例超过 1.5 GB,包含 400 个对象)。

我认为它来自 Qt 处理 QQuickWidgets 的方式,并想尝试另一种方式,使用 QQuickViews。为此,我创建了一个根视图,在 QWidget 中进行了转换,因此我可以将其嵌入到我的视图中,这是一个 QWidget。然后我在根视图中为每个创建的对象添加一个新的 QQuickView。

创建根视图、它的容器和引擎:

    _rootView = new QQuickWindow();
    _rootView->resize(1024, 720);
    _rootView->show();

    QWidget *container = QWidget::createWindowContainer(_rootView, this);
    container->resize(_rootView->size());
    container->setObjectName("TopLevelQmlViewWidget");
    _layout->addWidget(container);

    _engine = new QQmlEngine(_rootView);

代表对象的 QQuickViews 的创建:

    QQuickView *view = new QQuickView(_engine, _rootView);
    view->setSource(url);
    view->setResizeMode(QQuickView::SizeViewToRootObject);
    view->show();

它可以工作,但问题是每个 QQuickView 都会创建自己的线程,这不会改变我处理它的方式,而是发生在内存中。我不明白为什么,因为我将它们重新设置为根视图。

所以我的问题如下:

1 - 有没有办法阻止 QQuickViews 创建自己的线程?

2 - 使用 QQuickViews 确实比使用 QQuickWidgets 消耗更少的内存吗?

3 - 如果不是,我如何在 QWidget 视图中添加大量 QML 对象而不消耗太多内存?

【问题讨论】:

【参考方案1】:

我认为使用多个 QQuickViews 是个坏主意。一个应用程序通常只需要一个。我会看看QQmlComponent。这是一个例子:

QQmlComponent component(_engine, QUrl::fromLocalFile("MyItem.qml"));
QQuickItem *childItem = qobject_cast<QQuickItem*>(component.create());
childItem->setParentItem(_rootView);

【讨论】:

是的,我正在查看它,但不明白如何实现它。但是你的例子让我走上了一条好的道路,我能够弄清楚。现在我可以添加更多对象以减少内存。谢谢!【参考方案2】:

我绝不是 QML 专家。但是,这里有一些我能想到的指针

    Avoid mixing and matching QQuick: widget/View. Consider creating objects dynamically You can also make use of Loaders,但它们有少量额外开销。 考虑使用 stack/swipe view 之类的东西来尽量减少加载的对象数量。

为了获得最佳投资回报率,我首先尝试实现堆栈视图之类的东西,看看它对 RAM 有多大帮助。然后根据需要继续动态创建其他对象。

最后,我认为 QT 有一个工具可以让您在运行时查看 QML 树的内存量。你可以看看它,看看你最大的记忆猪在哪里。

【讨论】:

以上是关于使用 QQuickView 或 QQuickWidget 在 QWidget 应用程序中添加大量 QML 对象会带来性能问题的主要内容,如果未能解决你的问题,请参考以下文章

将 QML(QQuickView) 添加到现有 UI

避免 QQuickView 延迟 qml 加载

触摸事件未在 QQuickView 上触发

QQuickView 新删除类型不匹配

带有 QQuickView 的 QML 信号 QT 插槽

将 QQuickView 渲染到 QOpenGLFramebufferObject 时缺少对象