【问题标题】:QML progress bar is not updating smoothlyQML 进度条更新不顺畅
【发布时间】:2022-10-18 20:10:42
【问题描述】:

我想每 5 毫秒更新一次进度条,以使进度条看起来平滑。我创建了计时器和进度条。问题是我的进度条看起来像是从 100-80-60-40-20 “跳跃”,一点也不顺畅。

  import QtQuick 
import QtQuick.Controls 6.3

ApplicationWindow {
    id: root
    visible: true
    minimumWidth: 840
    minimumHeight: 600

    property real prgVal1:100

    Timer{
        id:timProgress
        interval: 5
        running: true
        repeat: true
        onTriggered: {
            updateProgress()
        }
    }

    function updateProgress(){
            if(prgVal1>0){
                prgVal1 = prgVal1-0.1
            }
            else{
                prgVal1 = 100
            }
    }
         
    ProgressBar{
        id: progressBar1
        visible: true
        width: 120
        height: 40
        x: 20
        y: 50
        value: prgVal1
        from:0
        to: 100
    }

}

*/

任何人都可以帮助我吗? 可以在这里看到 Gif:https://ibb.co/Wk4w2bn

【问题讨论】:

  • ProgressBar 无法自动识别最大值和最小值。要设置范围,请使用 fromto 属性;默认情况下,它介于01. (例如,from: 0; to: 100)。
  • 谢谢!现在 proressbar 有效,但是:它看起来像这样跳跃:100/80/60/40/20/0 。没有平滑的步骤。我为 prgVal1 添加了 console.log,它真的从 100 到 0 一个一个地变化。它应该每 10 ms 更新一次进度条。
  • 我相信10ms数量非常少;它等于100赫兹(100 帧/秒)。将值更改为16或者33以获得更人眼可观察的帧速率。
  • 不幸的是,这不是一个解决方案,我改成 10 fps(100 毫秒),但它的跳跃仍然大致相同。也许在更改进度值之后调用一些函数来更新所有 QML 可视组件?
  • 我觉得它相当平滑,但您可以尝试将值减小 0.1 步。 (例如prgVal1 -= 0.1 | Preview gif

标签: qml pyside qt-quick


【解决方案1】:

只需使用现有的组件,而不是重新发明事物。认为声明性不是强制性的。

您所需要的只是分配值,仅此而已。这里的Timer 仅作为示例。

ProgressBar {
    id: progressBar
    width: parent.width * 0.8
    anchors.centerIn: parent
    from: 0
    to: 100
    value: 0
    Behavior on value {
        PropertyAnimation { duration: 300; easing.type: Easing.OutBack }
    }
}

Timer {
    interval: 1000;
    running: true;
    repeat: true
    onTriggered: {
        var val = Math.floor(Math.random() * (progressBar.to - progressBar.from + 1) + progressBar.from);
        progressBar.value = val;
    }
}

【讨论】:

  • 有趣,但不明智的形式。仍然不明白为什么我的解决方案不起作用-应该不是吗?
  • 不是……嗯,聪明吗?当然,我不会假装自己是一个出色的解决方案,但至少这段代码完全符合您的需要。但我理解你的方向。无论如何,我祝你好运,找到一个真正巧妙的解决方案。
  • ...如果我理解,您必须生成随机 val,因为当我始终设置 const= 0 并希望将动画设置为 100 时它不起作用?在我看来是这样的...
【解决方案2】:

[编辑:原始答案已删除]

@WITC 好的,我已经在 Ubuntu 20 上安装了 pyside6(它似乎基于 Qt6.3.0)并使用以下 Python 来启动我的应用程序。

# main.py
import sys
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.quit.connect(app.quit)
engine.load('main.qml')
sys.exit(app.exec_())

然后我对你的 QML 程序做了一些小改动,这样我就可以将我看到的所有图像帧捕获到关键帧 PNG 中。

// main.qml
import QtQuick
import QtQuick.Controls 6.3

ApplicationWindow {
    id: root
    visible: true
    minimumWidth: 840
    minimumHeight: 600

    property real prgVal1:100
    property int count: 0

    Frame {
        id: frame
        background: Rectangle {
           color: "white"
           border.color: "black"
        }
        ProgressBar {
            id: progressBar1
            visible: true
            implicitWidth: 120
            implicitHeight: 40
            value: prgVal1
            from:0
            to: 100
        }
    }

    function step() {
        frame.grabToImage(function (res) {
            res.saveToFile(`/tmp/img/grab${count}.png`);
            count++;
            if (prgVal1 >= 1.0) {
                prgVal1 -= 1.0;
                Qt.callLater(step);
                return;
            }
        } );
    }

    Component.onCompleted: step()
}

为了将上述图像帧组合成动画 GIF,我使用了ffmpeg,如下所示:

# mkanim.sh
ffmpeg -y -framerate 20 -i '/tmp/img/grab%d.png'  -vf fps=20,palettegen /tmp/img/pal.png
ffmpeg -y -framerate 20 -i '/tmp/img/grab%d.png' -i /tmp/img/pal.png -lavfi "fps=20 [x]; [x][1:v] paletteuse" anim.gif

你注意到我得到的动画很流畅。

【讨论】:

  • 有趣,但结果是一样的,计时器现在有 100 毫秒的周期,在回调中我在这里减少 prgVal = prgVal-1 GIF:ibb.co/27hnSHp
  • 感谢您的尝试。我今晚要再检查一次。我看不到它,但是,我只能假设存在某种控制组件更新频率的默认步骤属性。
  • 如果它对您有用,问题可能出在 Qt 版本中?我使用我的 qml 代码和 Pyside6 ......
  • @WITC 如上所述,我在 Ubuntu 20 和 pyside6 下重新运行了答案。看来我正在使用 Qt6.3.0。
  • 再次感谢你 :-)。但仍然无法正常工作...您在我的 Windows 上的代码:ibb.co/RHRcyZQ
【解决方案3】:

这不是由您的硬件引起的问题,而是由操作系统引起的。因为您没有在应用程序中指定特定样式,所以它将采用您操作系统的本机样式,这就是它在 Ubuntu 上而不是在 Windows 上工作的原因。出于某种原因,QQuickProgressBar 的原生 Windows 样式仅以 5% 的倍数更新。我在代码中找不到要在此处共享的相关位置。

您可以通过默认使用不同的style(如QtQuick.Controls.Universal)来解决此问题。

import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Universal

ApplicationWindow {
    id: root
    visible: true
    minimumWidth: 320
    minimumHeight: 240

    property real prgVal1: 100

    Timer {
        interval: 5
        running: true
        repeat: true
        onTriggered: updateProgress()
    }

    function updateProgress() {
        if (root.prgVal1 > 0)
            root.prgVal1 = root.prgVal1 - 0.1
        else
            root.prgVal1 = 100
    }

    ProgressBar {
        visible: true
        width: 120
        height: 40
        x: 20
        y: 50
        value: prgVal1
        from: 0
        to: 100
    }
}

【讨论】:

    猜你喜欢
    • 2017-12-23
    • 2013-07-18
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多