Qt 将信号连接到插槽,但只调用插槽一次,然后自动断开连接

Qt 将信号连接到插槽,但只调用插槽一次,然后自动断开连接,qt,qml,qtquick2,observer-pattern,signals-slots,Qt,Qml,Qtquick2,Observer Pattern,Signals Slots,考虑以下JS代码: function handleSig() { emitter.someSig.disconnect(handleSig); // do some work here } emitter.someSig.connect(handleSig); 是否可以在没有显式断开连接和命名函数的情况下编写它 理想情况下,我想要这样的东西: emitter.someSig.connect( function() { // do some work h

考虑以下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
);

近乎重复:但是,关于Python的问题是我的,关于QML和C++。

< P>我在这里找到了C++的答案,虽然有点不雅:

来自该链接的代码:

QMetaObject::Connection * const connection = new QMetaObject::Connection;
*connection = connect(_textFadeOutAnimation, &QPropertyAnimation::finished, [this, text, connection](){
    QObject::disconnect(*connection);
    delete connection;
});

我仍然坚持更好的C++答案,对于qML回答。

你可以创建一个小助手函数,它为你断开连接,比如:

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)
    }
}
上面两个按钮将在单次触发模式下将
插槽
插槽2
连接到信号
操作
。 按钮操作将触发信号
操作
,该信号将在插槽连接时多次执行插槽。然后,它们将立即断开连接

您可以将函数
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)
}
功能连接n(信号,插槽,n){

如果(n调用
disconnect()
有什么问题?@folibis:1.那么
handleSig
名称是三倍的,2.更难阅读,3.无法在
connect
调用中定义处理程序。为什么我没有想到这一点!:)您可以使用
shared\u ptr
进行连接,这样就不必
delete
,因为生命周期是在capture子句中管理的