我想设置800ms的延迟时间来运行一个函数,所以我用一个计时器来处理它。代码如下。但是我发现,第一次,函数运行正常,它只显示一个console.log("这里是控制台....."); ,但是当我再次点击它时,它会显示2个控制台,而在第三次点击时,它会显示3个控制台,依此类推......
我无法理解为什么会发生这种情况,任何朋友都能为我解释一下吗?
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: {
delayTimer(800,function(){
console.log("here is console.....");
var t= Math.random();
console.log(t);
})
}
}
Timer{
id:dtimer
}
function delayTimer(delayTime, cb) {
console.log("delayTimer is starting");
dtimer.interval = delayTime;
dtimer.repeat = false;
dtimer.triggered.connect(cb);
dtimer.start();
}
}
点击几下后,当我再次点击它时,输出为:
qml: delayTimer is starting
qml: here is console.....
qml: 0.27777099609375
qml: here is console.....
qml: 0.407012939453125
qml: here is console.....
qml: 0.60552978515625
qml: here is console.....
qml: 0.360107421875
qml: here is console.....
qml: 0.21942138671875
qml: here is console.....
qml: 0.252288818359375
qml: here is console.....
qml: 0.88134765625
qml: here is console.....
qml: 0.63092041015625
qml: here is console.....
qml: 0.5125732421875
答案 0 :(得分:6)
每次拨打delayTimer()
时,您都会将信号连接到插槽,因此连接会累积并且会多次调用插槽。我不熟悉qml / js,但是你需要在触发超时后断开插槽:
function delayTimer(delayTime, cb) {
console.log("delayTimer is starting");
dtimer.interval = delayTime;
dtimer.repeat = false;
dtimer.triggered.connect(cb);
dtimer.triggered.connect(function(){
dtimer.triggered.disconnect(cb);
});
dtimer.start();
}
答案 1 :(得分:1)
正如@ w1ck3dg0ph3r指出的那样,你有一个函数多次绑定到信号。但是,正如QML假设的那样,所有的插槽都是同时执行的,没有保证的顺序,所以我认为,如果QML决定在执行它之前首先断开你的函数cb
,他的解决方案可能会失败。
可能会采取一些预防措施,但它们似乎并不太安全,正如您在此示例中所看到的那样:
Button {
onClicked: {
clicked.connect(clicked)
console.log('here')
}
}
这会在第一次单击时产生无限循环,但可能会预期连接仅在下次运行时执行,而不是已在同一次运行中。
另一方面,这个例子:
Button {
onClicked: {
clicked.connect(function() {console.log('here'); clicked.connect(function() {console.log('there')})});
}
}
根据我们上面的了解,您可能希望这两个函数在第一次运行时执行,输出为here
和there
- 这不是(至少在我的机器上)
因此,在执行过程中将绑定更改为信号时的行为定义不太明确。
更好的解决方案取决于您的用例。您想要将多个函数绑定到信号上,还是只想一个?
我建议将您的函数存储在变量中,并在onClicked
- 事件中处理断开连接:
Button {
property var myCB
onClicked: {
delayTimer(delayTime, cb) {
if (myCB) dtimer.triggered.disconnect(myCB)
myCB = cb
dtimer.triggered.connect(myCB)
...
}
}
}
像这样,您可以确保在正确的时间执行断开连接。但是,如果计时器由某些其他源重新启动,则该函数仍然受约束。如果你不想这样,你需要自己的功能来确保断开连接。
要提供量身定制的解决方案,您需要添加更多有关您的用例以及您期望的内容的详细信息。