考虑这个JS代码:
function handleSig() {
emitter.someSig.disconnect(handleSig);
// do some work here
}
emitter.someSig.connect(handleSig);
可以在没有显式断开连接和命名函数的情况下编写吗?
理想情况下,我喜欢这样的事情:
emitter.someSig.connect(
function() {
// do some work here
},
Qt.SingleShotConnection
);
近似重复:Automatically disconnect after first signal emission - 但这个问题是关于Python而我的是关于QML和C ++。
答案 0 :(得分:5)
您可以创建一个小辅助函数,为您执行断开连接,如:
function connectOnce(sig, slot) {
var f = function() {
slot.apply(this, arguments)
sig.disconnect(f)
}
sig.connect(f)
}
作为使用说明:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: myWindow
visible: true
width: 600
height: 600
color: 'white'
signal action(string name)
function slot(name) {
console.log(name)
}
Button {
text: 'connect'
onClicked: {
connectOnce(action, slot)
}
}
Button {
y: 80
text: 'action'
onClicked: {
action('test')
}
}
function connectOnce(sig, slot) {
var f = function() {
slot.apply(this, arguments)
sig.disconnect(f)
}
sig.connect(f)
}
}
上面两个按钮会在单次模式下将slot
和slot2
连接到信号action
。
按钮操作将触发信号action
,它将执行插槽的次数与连接的次数相同。然后他们会立即断开连接。
您可以将函数connectOnce
放入库中,以便随时随地使用它。
此解决方案很容易扩展为更通用的形式,通过在闭包中引入计数器来连接要执行的函数n
次:
function connectN(sig, slot, n) {
if (n <= 0) return
var f = function() {
slot.apply(this, arguments)
n--
if (n <= 0) sig.disconnect(f)
}
sig.connect(f)
}
答案 1 :(得分:3)
我在这里找到了一个C ++的答案,虽然它有点不优雅:
https://forum.qt.io/topic/67272/how-to-create-a-single-shot-one-time-connection-to-a-lambda/2
该链接的代码:
QMetaObject::Connection * const connection = new QMetaObject::Connection;
*connection = connect(_textFadeOutAnimation, &QPropertyAnimation::finished, [this, text, connection](){
QObject::disconnect(*connection);
delete connection;
});
我仍然坚持要求更好的C ++答案和QML答案。