Signals and Slots



  • I have a Qt signal and slot connection:

    QObject::connect(pobjPushButton
                    ,&clsQtPushbtn::clicked
                    ,pobjSubscriber
                    ,&clsXMLnode::pbtnClicked);
    

    I want to replace this code with something like this:

    pSignalClicked = static_cast<some type>(&clsQtPushbtn::clicked);
    pSlotClicked = static_cast<some type>(&clsXMLnode::pbtnClicked);
    QObject::connect(pobjPushButton
                    ,pSignalClicked
                    ,pobjSubscriber
                    ,pSlotClicked);
    

    So far my attempts at replacing the original code with the later has failed.

    I have several signals and slots with the same signal provider and subscriber, I am trying to clean up the code with a single connect statement and then set the pSignalClicked and pSlotClick pointers before the connect.


  • Qt Champions 2018

    void (clsQtPushbtn::* pSignalClicked)(void) = &clsQtPushbtn::clicked;

    As you can see, on the left hand side of the =, the class the signal/slot comes from, its return type and argument types have to be fixed in advance



  • Thank you, however, what I'm looking for is a generic cast where I can assign any signal and slot and then use a single connection call.


  • Qt Champions 2018

    I'm afraid it's not possible, anything more generic than the above causes undefined behaviour on dereferencing the pointer. It might be doable with templates but it really depends on your specific situation


  • Moderators

    @SPlatten
    You could try it with the old qt4 syntax, as long as your Signal and slot names are the same, for all classes, it should work.

    But it's slower - in executing - than the qt5 one and you don't get compile time checks.



  • @J-Hilk , do you mean using the SIGNAL and SLOT macros?


  • Moderators

    @SPlatten yes



  • @J-Hilk , thank you, works a treat:

    const char* cpSignal = nullptr, * cpSlot = nullptr;
    bool blnRc = false;
    
    if ( eSignal == ST_PUSHBUTTON_CLICKED ) {
        cpSignal = SIGNAL(clsQtPushbtn::clicked);
        cpSlot = SLOT(clsXMLnode::pbtnClicked);
        blnRc = true;
    }
    

    The only problem is now a variant of the connect that I'm also using:

            QObject::connect(pobjPushButton
                            ,&clsQtPushbtn::clicked
                            ,[pobjScriptEng, strCall]() {
                                QString strScript = clsMainWnd::strGetScript();
    
                                if ( strCall.isEmpty() != true ) {
                                    strScript += strCall + "();";
                                    pobjScriptEng->evaluate(strScript);
                                }
                            });
    

    I cannot use the SIGNAL() macro in this connect method.


  • Qt Champions 2018

    @SPlatten said in Signals and Slots:

    cpSignal = SIGNAL(clsQtPushbtn::clicked);
    cpSlot = SLOT(clsXMLnode::pbtnClicked);

    This should not work. it should be

    cpSignal = SIGNAL(clicked());
    cpSlot = SLOT(pbtnClicked());
    

    @SPlatten said in Signals and Slots:

    The only problem is now a variant of the connect that I'm also using

    You can use a QSignalMapper as a bridge between the two



  • @VRonin , it does work, I've tried it.


  • Qt Champions 2018

    @SPlatten said in Signals and Slots:

    it does work, I've tried it.

    Are you 100% sure? The below is a minimal example that shows it doesn't work

    #include <QApplication>
    #include <QSpinBox>
    #include <QSlider>
    #include <QHBoxLayout>
    int main(int argc, char ** argv)
    {
        QApplication app(argc, argv);
        QWidget mainWid;
        QHBoxLayout* minLay = new QHBoxLayout(&mainWid);
        QSpinBox* testSpinn=new QSpinBox(&mainWid);
        testSpinn->setRange(0,100);
        testSpinn->setValue(50);
        QSlider* testSlide=new QSlider(Qt::Horizontal,&mainWid);
        testSlide->setRange(0,100);
        testSlide->setValue(50);
        minLay->addWidget(testSpinn);
        minLay->addWidget(testSlide);
    
        // Works
        // QObject::connect(testSpinn,SIGNAL(valueChanged(int)),testSlide,SLOT(setValue(int)));
        // QObject::connect(testSlide,SIGNAL(valueChanged(int)),testSpinn,SLOT(setValue(int)));
    
        // Doesn't Work
        QObject::connect(testSpinn,SIGNAL(QSpinBox::valueChanged),testSlide,SLOT(QSlider::setValue));
        QObject::connect(testSlide,SIGNAL(QSlider::valueChanged),testSpinn,SLOT(QSpinBox::setValue));
    
        mainWid.show();
        return app.exec();
    }
    


  • @VRonin , I'm absolutely positive, I have a QPushButton, which I connected the "clicked" signal using the macro's this was connected to the slot also using the macro's exactly as I posted, it worked...I'm using Qt 5.12


  • Qt Champions 2018

    I checked the current sources. It can't work. But I feel I'm being pedantic and not really helpful.
    Did you manage to use QSignalMapper as a bridge to connect a lambda?



  • No, I've worked around the problem.



  • @SPlatten so is your issue solved? Please don't forget to mark your post as such. Thanks


Log in to reply
 

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