Consider this JS code:
function handleSig() {
emitter.someSig.disconnect(handleSig);
// do some work here
}
emitter.someSig.connect(handleSig);
Can it be written without the explicit disconnect and the named function?
Ideally, I'd like something like this:
emitter.someSig.connect(
function() {
// do some work here
},
Qt.SingleShotConnection
);
Near-duplicate: Automatically disconnect after first signal emission - but that question is about Python and mine is about QML and C++.
You can create a small helper function, which does the disconnecting for you, like such:
function connectOnce(sig, slot) {
var f = function() {
slot.apply(this, arguments)
sig.disconnect(f)
}
sig.connect(f)
}
As demonstration of the usage:
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)
}
}
The upper two Buttons will connect slot
and slot2
in single-shot mode to the signal action
.
The Button action will fire the signal action
which will execute the slots as many times as they are connected. Then they will be immediately disconnected.
You might put the function connectOnce
into a library to have it to your avail where ever you need it.
This solution is easily extended to a more general form, that will connect a function to be executed n
times by introducing a counter in the closure:
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)
}
I found an answer for C++ here, though it's a bit inelegant:
https://forum.qt.io/topic/67272/how-to-create-a-single-shot-one-time-connection-to-a-lambda/2
Code from that link:
QMetaObject::Connection * const connection = new QMetaObject::Connection;
*connection = connect(_textFadeOutAnimation, &QPropertyAnimation::finished, [this, text, connection](){
QObject::disconnect(*connection);
delete connection;
});
I'm still holding out for better C++ answers, and for a QML answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With