performance - 为什么创建动态 qml 对象这么慢,有哪些合理的替代方案?

标签 performance qt qml

我想实现的类似于棋盘游戏。有一个 100*100 的网格,放置在 Item 中,该 Item 位于 Flickable 中。

“游戏板”的各个矩形是 svg 图像,目前大约有 20 种类型,这可能会增加到数百种。

作为基准测试,我只是尝试用元素填充“世界”:

Component.onCompleted:
{
    var i,j;
    for (i=0; i<100; ++i) 
        for (j=0; j<100; ++j)
        {
            var type = (i+j) % 20;

            Qt.createQmlObject('import QtQuick 2.0; Image {source:"qrc:///icons/img/symbol'+type+'.svg";
                width: 32*scaling.factor;
                height: 32*scaling.factor;
                x:'+i*32+'*scaling.factor;
                y:'+j*32+'*scaling.factor}',
                mainScreen);
        }
}

在性能一般的 PC 上,这需要超过 5 秒

但是,在加载所有内容后,它可以流畅地运行,包括滚动和缩放(scaling.factor 是由 slider 或旋转框设置的 float )。

svg 图像非常简单,它们只包含一些基本形状。如果我尝试只加载一个简单的矩形而不是 svg 图像

Qt.createQmlObject('import QtQuick 2.0; Rectangle {color
     : "red"; width: 32; height: 32; x:'+i*32+'; y:'+j*32+'}',
     mainScreen);

它仍然需要大约 3 秒。即使没有图像,也没有动态缩放。

我记得 20 年前,有在单核、低于 400 MHz CPU 的计算机上运行的策略游戏,那些游戏有更大的 map 、更复杂的图 block 、动画、寻路等。而我们不是甚至谈论 3d。

现代 PC 怎么会因为显示几千个非常基本的形状而窒息?它不应该是从磁盘加载时间,因为元素在资源文件中,甚至使用矩形而不是图像的测试也非常慢。

不保持所有显示,只加载可见屏幕边界附近的元素显然是一种方法,或者如果我有一张 10000*10000 的 map 。我希望 100*100 个项目应该能够同时显示,尤其是在具有良好分辨率的屏幕上时,大多数项目都是可见的。

我是否遗漏了一些明显的东西,或者我应该完全忘记 Qt Quick,我应该在 OpenGL 或某些 2d 引擎中手动完成所有操作吗?

编辑:

如评论所述,Qt.createQmlObject 非常慢。

所以我尝试了

var component = Qt.createComponent("field.qml");
component.createObject(mainScreen, {"x": i*32, "y": j*32 });

其中 field.qml 仅包含一个 Rectangle{},或者在第二个测试中,仅包含一个空的 Item{}。在这两种情况下,10000 次迭代都花费了超过 3 秒的时间。将 svg 添加到 field.qml 仅将时间增加了 0.8 秒。

顺便说一句,图像不是应该被缓存吗?即使我有相同的简单 svg(只包含 3 个简单的矩形)重复一遍,也需要很多时间。

使用 Repeater{} 可以让一切变得更快。空的 Rectangle 在大约 0.2 到 0.3 秒内呈现,svg 图像在一秒钟内呈现。 (但是,这种方法还有其他缺点。我会在完成不同方法的测试后发布答案)

最佳答案

(虽然它不能完美地解决我的具体问题,但我会将其作为答案发布,因为它符合问题的范围并且可能对其他人有用。)

虽然官方示例使用动态创建对象,但该方法仅在对象数量相当少时才有用。对于大量项目,ListViewTableView 具有仅呈现实际位于 View 边界内的项目的优势。

TableView
{
    anchors.fill: parent
    model: ListModel {}
    itemDelegate: MyField{}
    Component.onCompleted:
    {
        var i;
        for (i=0; i<10000; ++i)
        {
            model.append({});
        }
}

Qt.createQmlObjectComponent.createObject 快几个数量级,并且比 Repeater

更容易处理

关于performance - 为什么创建动态 qml 对象这么慢,有哪些合理的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39225315/

相关文章:

c++ - 在 Qt 中如何在用户主目录中打开 QFileDialog::getOpenFileNames

performance - 使用 USB key 加快编译时间?

javascript - ExtJS 能够处理约 1000 个元素的网格/数据存储吗?

mysql - 将mysql慢查询日志更改为public_html路径

linux - QTweetLib 和 request_token

c++ - 从另一个类调用 QQmlApplicationEngine 时的 TableView 和 QAbstracTableModel

android - 如何更高效地绘制Opengl Elements

c++ - QBoxLayout 添加 QTextEdit 全尺寸和 QPushButton

linux - 如何使用 QML 更改系统日期和时间(嵌入式 Linux)?

c++ - QObject 连接 QSystemDeviceInfo::Profile 到 QVariant