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

Adding a high number of QML objects in a QWidget application using QQuickView or QQuickWidget poses performance problem

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

到目前为止,我使用的是 QQuickWidgets。 QGraphicsScene 包含一个顶级小部件,它是我创建的所有 QQuickWidgets 的父级。它工作正常,但我遇到了性能问题。对于大量对象,应用程序开始变慢,并且在 RAM 中占用过多 space(我创建的第一个示例超过 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 对象而不消耗太多内存?

我绝不是 QML 专家。不过,这里有一些我能想到的建议

  1. Avoid mixing and matching QQuick: widget/View.
  2. Consider creating objects dynamically
    • ,但它们有少量的额外开销。
  3. 考虑使用类似 stack/swipe view 的方法来最大程度地减少加载对象的数量。

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

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

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

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