QML – 在valueChanged信号后更新矩形时出现问题

huangapple go评论60阅读模式
英文:

QML - problem on updating rectangle after valueChanged signal

问题

我想要创建一个基于两个矩形的百分比显示。

如果我手动测试显示(为p_value设置固定值),那么百分比条将正确显示。

如果我拦截一个信号,当达到最大值时,条和文本才会更改。

中间值被正确接收,但显示保持不变。

p_value = 0

QML – 在valueChanged信号后更新矩形时出现问题

p_value = 30(手动设置)

QML – 在valueChanged信号后更新矩形时出现问题

p_value = 100

QML – 在valueChanged信号后更新矩形时出现问题

QML - cp_screen是一个屏幕管理器,处理了值和信号

Rectangle {
    property real p_value: cp_screen.progressValue
    property real p_barwidth: Math.round(p_value * 400 / 100)

    Rectangle { id: frame; width: 400; height: 40; color: "grey"; border.width: 1; radius: 0.2 * height
        Rectangle { id: bar
            height: 0.8 * frame.height
            width: p_barwidth
            x: 0.1 * frame.height;
            y: 0.1 * frame.height
            color: "white"
            radius: parent.radius
        }
        Label {
            anchors.centerIn: parent;
            text: p_value + " %";
            color: "black";
            font.bold: true;
        }
    }

    Connections {
        target: cp_screen;
        onProgressValueChanged: {
            console.log("PROGRESSBAR: " + p_value)
            console.log("PROGRESSBAR width: " + p_barwidth)
        }
    }
}

控制台日志

qml: PROGRESSBAR: 95
qml: PROGRESSBAR width: 380
qml: PROGRESSBAR: 96
qml: PROGRESSBAR width: 384
qml: PROGRESSBAR: 97
qml: PROGRESSBAR width: 388
qml: PROGRESSBAR: 98
qml: PROGRESSBAR width: 392
qml: PROGRESSBAR: 99
qml: PROGRESSBAR width: 396
qml: PROGRESSBAR: 100
qml: PROGRESSBAR width: 400

ScreenManager.h

Q_PROPERTY(int progressValue READ getProgressValue NOTIFY progressValueChanged)
英文:

I want to create a percentage display based on two rectangles.

If I test the display manually (fixed value for p_value) then the percentage bar is displayed correctly.

If I intercept a signal, the bar and the text only change when the maximum value is reached.

The intermediate values are received correctly but the display remains unchanged.

p_value = 0

QML – 在valueChanged信号后更新矩形时出现问题

p_value = 30 (set manually)

QML – 在valueChanged信号后更新矩形时出现问题

p_value = 100

QML – 在valueChanged信号后更新矩形时出现问题

QML - cp_screen is a screen manager with handled the values und signals

Rectangle {
 
    property real p_value: cp_screen.progressValue
    property real p_barwidth: Math.round(p_value * 400 / 100)   

    Rectangle { id: frame; width: 400; height: 40; color: "grey"; border.width: 1; radius: 0.2 * height
        Rectangle { id: bar  
            height: 0.8 * frame.height
            width: p_barwidth
            x: 0.1 * frame.height;  
            y: 0.1 * frame.height
            color: "white"
            radius: parent.radius
        }
        Label { 
            anchors.centerIn: parent; 
            text: p_value + " %"; 
            color: "black"; 
            font.bold: true; 
        }
    }

    Connections { 
        target: cp_screen; 
        onProgressValueChanged: { 
            console.log("PROGRESSBAR: " + p_value)
            console.log("PROGRESSBAR width: " + p_barwidth)
        } 
    }
} 

Console log

qml: PROGRESSBAR: 95
qml: PROGRESSBAR width: 380
qml: PROGRESSBAR: 96
qml: PROGRESSBAR width: 384
qml: PROGRESSBAR: 97
qml: PROGRESSBAR width: 388
qml: PROGRESSBAR: 98
qml: PROGRESSBAR width: 392
qml: PROGRESSBAR: 99
qml: PROGRESSBAR width: 396
qml: PROGRESSBAR: 100
qml: PROGRESSBAR width: 400

ScreenManager.h

Q_PROPERTY(int progressValue READ getProgressValue NOTIFY progressValueChanged)

答案1

得分: 1

I just wanted to improve it based on the comments.
只是想根据评论来改进它。

As I said, you can use https://gist.github.com/77140ab5ef0bc219df171506ccb5a9b7.git I reproduced your example, and it has no problem. Your logical error is in other parts of your program.
正如我所说,你可以使用 https://gist.github.com/77140ab5ef0bc219df171506ccb5a9b7.git 来重现你的示例,它没有问题。你的逻辑错误在你程序的其他部分。

QML – 在valueChanged信号后更新矩形时出现问题

Check this sample; your sample has just been completely edited and uploaded.
查看这个示例;你的示例已经被完全编辑并上传。

https://drive.google.com/file/d/1lCnIT582w3sUe3leA5zq_LHhc5bZsfX5/view?usp=sharing

英文:

I just wanted to improve it based on the comments.
As I said, you can use https://gist.github.com/77140ab5ef0bc219df171506ccb5a9b7.git I reproduced your example , and it has no problem. Your logical error is in other parts of your program.

QML – 在valueChanged信号后更新矩形时出现问题

Check this sample; your sample has just been completely edited and uploaded.
https://drive.google.com/file/d/1lCnIT582w3sUe3leA5zq_LHhc5bZsfX5/view?usp=sharing

答案2

得分: 1

I guess thats because you have x offset.
Your bar width is parent.width - 0.2 * frame.height, so your bar width should be (parent.width - 0.2 * frame.height) * p_value / 100

consider the following:

Rectangle { 
  id: bar
  anchors.verticalCenter: parent.verticalCenter
  x: parent.height / 10
  width: (parent.width - 0.2 * parent.height) * p_value / 100
  height: 0.8 * parent.height
  color: "white"
  radius: parent.radius
}
英文:

I guess thats because you have x offset.
Your bar width is parent.width - 0.2 * frame.height, so your bar width should be (parent.width - 0.2 * frame.height) * p_value / 100

consider the following:

Rectangle { 
  id: bar
  anchors.verticalCenter: parent.verticalCenter
  x: parent.height / 10
  width: (parent.width - 0.2 * parent.height) * p_value / 100
  height: 0.8 * parent.height
  color: "white"
  radius: parent.radius
}

答案3

得分: 0

我想提一下关于 TimerintervalonTriggeredinterval 是一个提示,但是 onTriggered 可能会在那之前或之后触发。如果你暂停和恢复你的应用程序,会在你的 onTriggered 事件中出现间隙。为了弥补这些间隙,我们应该基于系统时钟进行归一化,例如:

    MyProgressBar {
        progress: (heartbeat.tick / 100) % 100
    }

    Timer {
        id: heartbeat
        property var tick: Date.now()
        interval: 100
        repeat: true
        running: true
        onTriggered: tick = Date.now()
    }

我已经重构了你的代码。我使用了 Frame 组件,它可以减少用于大小和填充计算的像素数学。这里是一个完整的工作演示:

import QtQuick
import QtQuick.Controls
Page {
    id: page
    MyProgressBar {
        anchors.centerIn: parent
        progress: (heartbeat.tick / 100) % 100
    }
    Timer {
        id: heartbeat
        property var tick: Date.now()
        interval: 100
        repeat: true
        running: true
        onTriggered: tick = Date.now()
    }
}

// MyProgressBar.qml
import QtQuick
import QtQuick.Controls
Frame {
    id: progressBar
    width: 400
    height: 40
    property real progress: 50
    padding: 0
    background: Frame {
        padding: 5
        background: Rectangle {
            anchors.fill: parent
            border.color: "black"
            color: "grey"
            radius: height * 0.2
        }
        Rectangle {
            width: parent.width * (progress / 100.0)
            height: parent.height
            color: "white"
            radius: parent.height * 0.2
        }
    }
    Label { 
        anchors.centerIn: parent 
        text: (progress).toFixed(0) + " %"
        color: "black"
        font.bold: true
    } 
}

你可以在线尝试

英文:

I want to make a point about Timer interval and onTriggered. The interval is a hint but, onTriggered may fire before or after that time. If you suspend and resume your application, there will be gaps on your onTriggered event. To smooth over your gaps, we should normalize based on the system clock, e.g.

    MyProgressBar {
        progress: (heartbeat.tick / 100) % 100
    }

    Timer {
        id: heartbeat
        property var tick: Date.now()
        interval: 100
        repeat: true
        running: true
        onTriggered: tick = Date.now()
    }

I have refactored your code. I used the Frame component, which can reduce the amount of pixel math needed for size and padding calculation. Here's a full working demo:

import QtQuick
import QtQuick.Controls
Page {
    id: page
    MyProgressBar {
        anchors.centerIn: parent
        progress: (heartbeat.tick / 100) % 100
    }
    Timer {
        id: heartbeat
        property var tick: Date.now()
        interval: 100
        repeat: true
        running: true
        onTriggered: tick = Date.now()
    }
}

// MyProgressBar.qml
import QtQuick
import QtQuick.Controls
Frame {
    id: progressBar
    width: 400
    height: 40
    property real progress: 50
    padding: 0
    background: Frame {
        padding: 5
        background: Rectangle {
            anchors.fill: parent
            border.color: "black"
            color: "grey"
            radius: height * 0.2
        }
        Rectangle {
            width: parent.width * (progress / 100.0)
            height: parent.height
            color: "white"
            radius: parent.height * 0.2
        }
    }
    Label { 
        anchors.centerIn: parent 
        text: (progress).toFixed(0) + " %"
        color: "black"
        font.bold: true
    } 
}

You can Try it Online!

答案4

得分: -2

感谢您的反馈。

onProgressValueChanged 信号被正确识别,并且值也在增加(请参阅控制台),但似乎只在最后发射信号后才会更新进度条或屏幕(我通过单独的线程触发发射信号,以避免阻塞 GUI)。

如果我在 progress.qml 中使用一个定时器,它将按预期工作。

Timer {
    id: mytimer
    onTriggered: {
        p_value = p_value + 1
    }
    interval: 100
    repeat: true
    running: p_value < 100
}
英文:

Thanks for your feedbacks.

The onProgressValueChanged signal is recognized correctly and the value is also increased (see console) only the update of the bar or the screen seems to take place only after the last emit (I trigger the emits via a separate thread so that the gui should not blocked).

If I use a timer on the progress.qml it works as espected.

Timer {
    id: mytimer
    onTriggered: {
        p_value = p_value + 1
    }
    interval: 100
    repeat: true
    running: p_value &lt; 100
}

huangapple
  • 本文由 发表于 2023年2月27日 15:54:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75577958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定