QML 为大量矩形设置动画时性能缓慢

Posted

技术标签:

【中文标题】QML 为大量矩形设置动画时性能缓慢【英文标题】:QML slow performance animating a lot of rectangles 【发布时间】:2021-10-13 11:02:25 【问题描述】:

我正在为我的 QML 应用程序创建一个“虚线纸”组件。本质上,这些组件由用户可以放大的虚线背景组成。为了创建它,我使用了以下代码:

DottedPaper.qml

import QtQuick 2.15

Rectangle
    id: page

    property int spacing: 50
    // this property changes the spacing between the dots
    property real contentScale: 1.0

    Repeater
        id: rowRepeater
        model: 200
        Repeater
            id: row
            property int rowIndex: index
            model: 200
            Rectangle
                id: circle
                color: "red"
                width: 4; height: 4
                x: index * spacing * page.contentScale + width/2;
                y: rowIndex * spacing * page.contentScale+ height/2
                radius: width/2
            
        
    

然后在我的主文件中,我有以下内容:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window 
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Flickable
        clip: true // doesn't improve anything
        anchors.fill: parent
        contentWidth: paper.width
        contentHeight: paper.height
        DottedPaper
            id: paper
            width: 10000; height: 10000;
            clip: true
        
    

    // the slider changes the content scale of the dotted paper
    Slider
        from: 1
        to: 3
        onValueChanged: paper.contentScale = value
    

这段代码的问题是它很慢。检查应用程序后,内容不会以 60 fps 的速度呈现,但我的桌面上的速度约为 45 - 50 fps。我怀疑问题在于 QML 正在重新评估背景中每个圆圈的 contentScale 属性绑定,即使圆圈在屏幕上不可见。防止这种情况的最佳方法是什么?

【问题讨论】:

我建议在一个Canvas 上画出所有的点。 【参考方案1】:

如果您将中继器更改为 ListViews,效果会更好。那是因为 ListView 足够聪明,只能根据需要为可见空间创建足够的委托。 (起初我认为 GridView 可以工作,但这并不能让您对行/列进行足够的控制。)

Rectangle
    id: page

    property int cellWidth: 50 * contentScale
    property int dotWidth: 4
    // this property changes the spacing between the dots
    property real contentScale: 1.0

    ListView 
        id: grid
        model: 200
        anchors.fill: parent
        anchors.leftMargin: page.dotWidth / 2
        anchors.topMargin: page.dotWidth / 2
        spacing: page.cellWidth - page.dotWidth

        delegate: ListView 
            model: 200
            width: window.width
            height: page.dotWidth
            orientation: ListView.Horizontal
            spacing: page.cellWidth - page.dotWidth
            property int rowIndex: index

            delegate: Rectangle
                id: circle
                color: "red"
                width: page.dotWidth; height: page.dotWidth
                radius: width/2
            
        
    

【讨论】:

谢谢,这确实工作得更好,尽管根据网格中的圆圈数量和大小,似乎仍然存在性能损失。 好吧,你要创建 40,000 个点,所以这肯定会给系统带来压力。你也可以试试 Canvas 的想法。一般来说,画布的绘制速度较慢,但​​在这种情况下可能会更快,因为只有 1 个项目而不是 40,000 个单独的项目。 是的,我会试试,或者只是写一个自定义的QQuickItem。我希望 Qt Quick 足够聪明,可以进行一些巧妙的剔除,以便只评估屏幕上的项目。 仅供参考:我刚刚尝试了 Canvas,发现它真的很慢。

以上是关于QML 为大量矩形设置动画时性能缓慢的主要内容,如果未能解决你的问题,请参考以下文章

QML 中的堆栈布局

仅在第一次执行时性能缓慢

QML ListView 填充不透明动画

在 QML 中为 MapQuickItem 设置位置更新动画

几秒后,Jquery动画()响应非常缓慢

PropertyAnimation 与 NumberAnimation