我正在尝试在我的UI项目中使用信号。我想要一个按钮来启动一些进程。虽然我这样做,但我意识到我并不了解发生了什么,所以我写了下面的代码来试图指出发生了什么。
运行时,main.qml会创建一些彩色框作为控件,还有一些白色框用于输出(由SubOne.qml制作)。
如果您点击绿色框,它会发出信号'广播',并且每个白框都连接到该信号。
On' broadcast'每个白框都调用其功能栏。
酒吧开始循环。在循环结束时,它打印迭代次数,并更改text属性以显示相同的数字。
第一个和第三个白框执行1次循环,但第二个框执行足够的循环以引起明显的延迟。
好的,一切似乎都很好。正如预期的那样,顺序调用三个函数栏,并按顺序输出它们的打印。但我很惊讶地发现文本属性没有按顺序更新。相反,所有条形完成,然后所有三个文本属性一起更新。换句话说,在SubOne.qml第17行中,直到ALL循环完成才生效,但第18行在EACH循环完成时生效。
谁能告诉我发生了什么事? qml是否正在做一些优化写入显示的东西?如果是这样,可以控制它。
主要是,如何在EACH循环退出后一起进行打印和文本更新。
感谢您的帮助。
// qml.main
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
visible: true
Rectangle {
Rectangle {
x: 50
y: 50
width: 50
height: 50
color: "green"
Text {
text: "Start"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: start
signal broadcast()
anchors.fill: parent
onClicked: broadcast();
}
}
Rectangle {
function set() {
first.thisText = "---";
second.thisText = "---";
third.thisText = "---";
}
id: reset
x: 110
y: 50
width: 50
height: 50
color: "yellow"
Text {
text: "Reset"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
onClicked: reset.set();
}
}
Rectangle {
id: exit
x: 170
y: 50
width: 50
height: 50
color: "red"
Text {
text: "Exit"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
onClicked: Qt.quit();
}
}
}
SubOne {
id: third
thisName: "third"
x: 50
y: 110
loop: 1
}
SubOne {
id: second
thisName: "second"
x: 50
y: 170
loop: 100000000
}
SubOne {
id: first
thisName: "first"
x: 50
y: 230
loop: 1
}
}
// SubOne.qml
import QtQuick 2.0
Rectangle {
id: rectangle1
property string thisName: ""
property string thisText: "nothing yet"
property int loop: 1
height:50
width:170
function bar() {
print("looping " + thisName + " with: " + loop);
for (var counter=0; counter<loop; counter+=1){
//do nothing much
}
thisText = counter;
print("looped " + thisName + " to: " + counter);
}
Text {
text: thisText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
Connections {
target: start
onBroadcast: bar()
}
}
这是使用WorkerScript的新代码,如建议的那样。
// SubOne.qml
import QtQuick 2.0
Rectangle {
id: rectangle1
property string thisName: ""
property string thisText: "nothing yet"
property int loop: 1
height:50
width:170
WorkerScript {
id: myWorker
source: "script.js"
onMessage: thisText = messageObject.reply
}
Text {
text: thisText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
Connections {
target: start
onBroadcast: {
myWorker.sendMessage({'loopVal':loop, 'nameVal':thisName});
}
}
}
//的script.js
WorkerScript.onMessage = function(obj) {
print("looping " + obj.nameVal + " to: " + obj.loopVal);
for (var counter=0; counter<obj.loopVal; counter+=1){
//do nothing much
}
print("finished " + obj.nameVal + " at: " + counter);
WorkerScript.sendMessage({ 'reply': counter})
}
值得注意的是,SubOne.qml第26行的sendMessage不会被SubOne第14行的onMessage处理,它将由script.js第1行的WorkerScript.onMessage处理,类似于WorkerScript script.js第7行的.sendMessage在第14行的SubOne.qml文件中处理。此外,发送到新线程的消息只获取一个参数,因此要发送nameVal和loopVal,我将它们放在一个对象中,在SubOne.qml第26行内联创建
也许这很明显,但它让我困惑了一段时间;)
有趣的是,如果你按下红色&#39;在循环期间,主线程立即退出,但第二个线程完成它首先执行的操作。
希望这有助于某人。
感谢BaCaRoZzo和Kuba Ober。
答案 0 :(得分:3)
QML在这里做了很多事情 - 你是,因为你正在阻止事件循环。当您的代码正在运行时,事件循环不是,并且QML无法进行任何显示更新。您必须将控制权交还给事件循环才能更新显示。这与基于窗口小部件的UI没有什么不同。你也有同样的行为。