Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Multiple inheritance and signals/slots



  • I understood multiple inheritance is ok, as long as only one of the base classes is derived from QObject and this class is inherited first. But I can't get it to work.

    My code looks like this:

    class DelayedEditSpinBox : public QSpinBox
    {
    Q_OBJECT
    
    protected slots:
    
        void onValueChanged();
       ...
    };
    
    DelayedEditSpinBox::DelayedEditSpinBox( QWidget* parent )
    : QSpinBox( parent )
    {
        connect( this, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) );
    }
    
    class ParameterWidget
    {
    public:
    
        ParameterWidget( Parameter* parameter );
    
        virtual ~ParameterWidget();
        ...
    };
    
    class IntParameterWidget : public DelayedEditSpinBox, public ParameterWidget
    {
    Q_OBJECT
    
    public:
    
        explicit IntParameterWidget( QWidget* parent, Parameter* parameter );
        ...
    };
    

    The issue is that in the DelayedEditSpinBox::onValueChanged() slot never receives the DelayedEditSpinBox::valueChanged( int ) signal when DelayedEditSpinBox is derived from IntParameterWidget . But it does if DelayedEditSpinBox is 'standalone'.

    Everything works fine if IntParameterWidget is derived from QSpinBox instead of DelayedEditSpinBox and I connect to the SpinBox::valueChanged( int ) signal.

    Any ideas?



  • @AndyBrice said in Multiple inheritance and signals/slots:

    connect( this, SIGNAL( valueChanged( int ) ), this, SLOT( onValueChanged() ) );

    Idk if just a typo, but the slot has to accept intvalues, if signal passes an integer.

    Nevermind. Was confused because of parameter differences :)
    (e.g. Int + String wont work)

    Is your class DelayedEditSpinBox pure virtual or do you actually create instances?



  • @Pl45m4 A slot can ignore the parameters in a signal. I do it all the time.


  • Moderators

    @AndyBrice said in Multiple inheritance and signals/slots:

    @Pl45m4 A slot can ignore the parameters in a signal. I do it all the time.

    That's indeed the case, however, I would suggest using the "new" Qt5 Signal Slot Syntax

    You can even specify the signal/slot to use, if to use it from the parent class or not

    DelayedEditSpinBox::DelayedEditSpinBox( QWidget* parent )
    : QSpinBox( parent )
    {
        connect( this, QOverLoad<int>::of(&QSpinBox::valueChanged), this, &DelayedEditSpinBox::onValueChanged);
    }
    

    in case you shadow signals or slots



    • What's the implementation of IntParameterWidget::IntParameterWidget?
    • Does DelayedEditSpinBox have multiple constructors?


  • @VRonin

    What's the implementation of IntParameterWidget::IntParameterWidget?

    IntParameterWidget::IntParameterWidget( QWidget* parent, Parameter* parameter )
    : DelayedEditSpinBox( parent ), ParameterWidget( parameter )
    {
    ...
    }
    

    It connects to a signal from DelayedEditSpinBox. But that signal is never emitted.

    Does DelayedEditSpinBox have multiple constructors?

    No,



  • @J-Hilk I will try that. Thanks!



  • @J-Hilk This syntax doesn't seem to work on MSVC. :0(



  • @AndyBrice

    Qt Version? Compiler Version?
    In general it should work with MSVC
    https://wiki.qt.io/New_Signal_Slot_Syntax



  • @Pl45m4 MSVC 2015 on Windows 7.



  • I tested the below with Qt 5.12.5, MinGW 7.3.0 64bit on Win 10 and it's working

    #include <QSpinBox>
    #include <QApplication>
    class Parameter;
    class DelayedEditSpinBox : public QSpinBox
    {
    public:
        explicit DelayedEditSpinBox( QWidget* parent =nullptr )
            : QSpinBox( parent )
            {
                connect( this,static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &DelayedEditSpinBox::onValueChanged );
            }
        void onValueChanged(){
            qDebug("onValueChanged");
        }
    };
    
    class ParameterWidget
    {
    public:
        ParameterWidget( Parameter* parameter =nullptr ){}
        virtual ~ParameterWidget()=default;
    };
    
    class IntParameterWidget : public DelayedEditSpinBox, public ParameterWidget
    {
    
    public:
    
        explicit IntParameterWidget( QWidget* parent=nullptr, Parameter* parameter=nullptr )
            :DelayedEditSpinBox(parent),ParameterWidget(parameter)
        {}
    
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        IntParameterWidget w;
        w.show();
        return a.exec();
    }
    


  • @VRonin I will try it, thanks. It might be a while, because I am going to be away from my dev PC.



  • It turns out that I was later calling QObject::disconnect() on IntParameterWidget, which also disconnected signals in the base classes, including the QComboBox valueChanged( int ) signal. So it isn't a Qt bug/issue. Just my stupidity. Oops.


Log in to reply