How to emit signal only once. (solved)



  • The problem of the code below, is switch-statement keep on emitting doorOpen or doorClose.
    And both slot doorOpenSlot() & doorCloseSlot() prompted. How to resolve this, so SLOT can be prompted only once.

    @

    switch(e){
    case '0':
    //if (v_stopbit <1) { added a variable init to zero
    qDebug()<<"door open";
    //v_stopbit++; added to be exclude from the loop next round
    emit doorOpen();
    //}
    break;
    case'1'
    qDebug()<<"door closed";
    emit doorClosed();
    break;
    }

    connect(inputudpOpen, SIGNAL(doorOpen()), this, SLOT(doorOpenSlot());
    connect(inputudpClose, SIGNAL(doorClose()), this, SLOT(doorCloseSlot());

    @


  • Lifetime Qt Champion

    Hi,

    Check the state of the door and only emit the signal when applicable.

    Sounds like a state machine would be useful here.


  • Moderators

    you need to be more specific.
    I guess i am not the only one which doesn't understand what you are exactly trying.
    In which method is the switch implemented?



  • How about calling "disconnect", after getting into the slot?

    "Disconnect":http://qt-project.org/doc/qt-4.8/qobject.html#disconnect-3

    This might break the connection.



  • I wrote a singleShotConnect once. It was basically a function that worked like connect, but instead of just making the connection, it would also create a new object in the background that kept track of the connection paramters (who is involved, what signals), and this object also had a slot that was connected to the same signal after the connection that the caller really wanted to make. When this slot was then called, the object would disconnect the original connection, and then delete itself.



  • Andre,

    That looks to be a good implementation. One question, after you delete the object, if you call QObject::dumpObjectInfo(), what does it show? Does it remove the specific signal and slot?

    Thank you.



  • I did not try that. Note that it doesn't remove the signal or the slot, it just disconnects the connection between the two.

    I would not call it a great implementation either. It is a bit of a trick, and it is not a cheap trick to pull off (creating a whole new QObject instance to just monitor a single signal-slot connection). It could be optimized of course to only ever use a single QObject instance to do the management of potentially multiple single-shot connections. But that was more work :)

    Note that with Qt 5, the implementation would be a bit different and cheaper. Because Qt 5 returns a QMetaObject::Connection instance when you call connect, you can just store that connection instance and use that to do your disconnect. If you have C++/11, you can also use a lambda to pull off this trick even cheaper. Something like:

    @
    //this is untested, of course
    inline singleShotConnect(const QObject * sender,
    const char * signal,
    const QObject * receiver,
    const char * method)
    {
    auto connection = QObject::connect(sender,
    signal,
    receiver,
    method);
    if (connection) {
    //only disconnect if the connection worked
    QObject::connect(sender, signal,
    connection {
    QObject::disconnect(connection);
    };
    }
    }
    @

    Of course, you'd probably want to provide all the connect overloads. Perhaps you have to that manually, perhaps with a bit of template magic you can do it in one go. I do think that it would be nicer to just have a connection type singleShot, but a work-around like this would work as well.

    Edit: I have added a "suggestion":https://bugreports.qt.io/browse/QTBUG-44219 to add this to Qt.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.