英文:
QML - problem on updating rectangle after valueChanged signal
问题
我想要创建一个基于两个矩形的百分比显示。
如果我手动测试显示(为p_value设置固定值),那么百分比条将正确显示。
如果我拦截一个信号,当达到最大值时,条和文本才会更改。
中间值被正确接收,但显示保持不变。
p_value = 0
p_value = 30(手动设置)
p_value = 100
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
p_value = 30 (set manually)
p_value = 100
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 来重现你的示例,它没有问题。你的逻辑错误在你程序的其他部分。
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.
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
我想提一下关于 Timer
的 interval
和 onTriggered
。 interval
是一个提示,但是 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 < 100
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论