Qt signals & inheritance question

16,983

Solution 1

I guess the problem is the multiple inheritance:

class matLinePlot : public QObject, public Plot3D
...

I assume that Plot3D is a subclass of QObject? In this case, you should do

class matLinePlot : public Plot3D
...

instead.

Solution 2

SIGNAL(x) and SLOT(x) are macros that generate string literals. At runtime, slots and signals are matched up using string compares of those generated literals.

(I would have added a comment to mdec's comment, but I don't have enough rep)

Solution 3

I believe that will work if the Plot3D::rotationChanged signal is public or protected. Are you sure the signal is not private?

Edit:

Although I could not find a specific reference, I'll have to conclude that signals are always public. At least a test I did here seemed to indicate that I could connect to a signal even if it was declared in the private section of a class.

I also verified that a signal declared in QObject could be connected using a subclass of QObject in the connect statement so signals are definitely inheritable. As I see in other answers and comments here, the issue must be elsewhere.

Share:
16,983
Pete
Author by

Pete

Co-Author of the PRT - Pattern Recognition Toolbox for MATLAB. A free, permissively licensed toolbox for pattern recognition and machine learning for MATLAB. Completely free for commercial and academic use: http://www.mathworks.com/matlabcentral/linkexchange/links/2947-pattern-recognition-toolbox How easy is it to use? % 3-Fold Cross-Validation on a simple data set: dataSet = prtDataGenUnimodal; class = prtClassFld; yOut = class.kfolds(dataSet,3); prtScoreRoc(yOut); Also, check out our little blog, which shows some examples of using the PRT: http://www.newfolderconsulting.com/blog

Updated on June 04, 2022

Comments

  • Pete
    Pete about 2 years

    I am relatively new to programming with Qt and had a question. Short version:

    How do I inherit signals defined in superclasses?

    I am trying to subclass someone else's nicely made QTWidgets to change some of the default behavior:

    
    //Plot3D is a QWidget that defines a signal "rotationChanged"
    class matLinePlot : public QObject, public Plot3D {
    
        Q_OBJECT;
            //etc...
    public:
           //etc...
    
            //Catch Plot3D's signal "rotationChanged" and do some magic with it:
        void initPlot(){
                  QObject::connect(this, SIGNAL(rotationChanged( double , double , double )),
                this, SLOT(myRotationChanged(double, double, double)));
        }
    };
    

    The problem is in the QObject::connect line. What I would like to do is connect the rotationChanged SIGNAL (from qwt3D_plot.h) to a local function/SLOT - "myRotationChanged". However whenever I do this, at run time I get:

    Object::connect: No such signal matLinePlot::rotationChanged(double, double, double)

    in C:...\matrixVisualization.h. Of course, I know that rotationChanged isn't in matrixVisualization.h - it's in qwt_plot3D.h, but I thought that since I inherit from Plot3D everything should be fine. But, now that I think about it, since SIGNAL and SLOT are macros, I assume MOC doesn't know/care about inheritance.

    Which leads me to my question - since MOC and SIGNALS / SLOTS don't seem to know about inheritance etc: how can I subclass a widget defined somewhere else and get access to the widget's signals?

    I have a lot of examples of how to use encapsulation to accomplish something like this, but I'm afraid I don't understand how to do this with inheritance.

    Sorry if this is a ridiculous question - I feel like I'm missing something obvious.

  • Pete
    Pete about 15 years
    Hi, I tried putting a public keyword before the signal keyword, but Qt MOC did not like that: 1>MOC include\qwt3d_plot.h 1>include\qwt3d_plot.h(143): Error: Signals cannot have access specifier 1>Project : error PRJ0019: A tool returned an error code from "MOC include\qwt3d_plot.h"
  • Pete
    Pete about 15 years
    Oops. Obviously I should have used "public: signals:", but that hasn't helped.
  • Pete
    Pete about 15 years
    I now have: public: signals: //! Emitted, if the rotation is changed void rotationChanged(double xAngle,double yAngle,double zAngle); In the header and the plotting library, and QObject::connect(this,SIGNAL(rotationChanged(double,double,d‌​ouble)), this,SLOT(myRotationChanged(double,double,double))); In my derived class... still same error. I have included the header: #include <qwt3d_plot.h> //has Plot3D class
  • Pete
    Pete about 15 years
    Right - I think that's the heart of this problem; because the string matching MACRO/MOC combo is looking in only the current header file for the signal, it doesn't know to look in my other library of compiled code.
  • Mudasir Nazir
    Mudasir Nazir about 15 years
    When you declare the signals, do not declare a name for the parameter, only the types. That is public: signals: void rotationChanged(double, double, double); Hopefully that should fix your error.
  • AntonyFalegk
    AntonyFalegk about 15 years
    Spacing does not effect signals & slots, what you heard is signal/slot normalization which just little-bit speeds up code but thats hardly noticable anyway.
  • Mudasir Nazir
    Mudasir Nazir about 15 years
    Thanks for the clarification =]
  • Idan K
    Idan K about 15 years
    Pete, I'm pretty sure you're wrong. The signals and slots are kept somewhere (moc generates the code for this, you can see it in the *_moc file), it has nothing to do with the current header file.
  • Pete
    Pete about 15 years
    That makes things into a link error: 1>moc_matrixVisualization.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const Qwt3D::Plot3D::staticMetaObject" (?staticMetaObject@Plot3D@Qwt3D@@2UQMetaObject@@B) The QT doc suggests using multiple inheritance: doc.trolltech.com/4.3/uitools-multipleinheritance.html Although they extend QWIdget, I need QObject.
  • sean e
    sean e about 15 years
    (curses! - I don't have enough rep to add to Pete's last comment about the link error) It looks like you are not linking in moc_qwt3D_plot.cpp.
  • ashcatch
    ashcatch about 15 years
    The link you posted is showing an example on how to use .ui files (those files created by Qt Designer). One important difference is that Ui::CalculatorForm is not a subclass of QObject. The rule when subclassing from QObject (and using multiple inheritance) is that only one of the superclasses can be a QObject and that the QObject has to be the first part in the inheritance.
  • Idan K
    Idan K about 15 years
    the doc suggests multiple inheritance in a different scenario. when using Qt Designer you'll get a .ui file, then a tool called uic will take that .ui file and generate a class that's basically a translation of the .ui file, only in actual C++. so what they're basically suggesting is to inherit from that class, instead of having it as a member.
  • ashcatch
    ashcatch about 15 years
    Under doc.trolltech.com/4.3/moc.html you can find the info about multiple inheritance. And when it comes to the compiler error, this is probably caused by a missing moc step of your header file for Plot3D.
  • Pete
    Pete about 15 years
    ashcatch, this was correct. Thanks, I did not understand the difference between the UI inheritance and the regular inheritance. Once I linked with the moc_*.cpp and also only inherited from Plot3D this worked.
  • sean e
    sean e about 15 years
    Qwt3D is a namespace? Is your matLinePlot in the same namespace or do you have a using directive somewhere?
  • Pete
    Pete about 15 years
    Yeah, I had the namespaces settled, the issue was a) the multiple inheritance and b) a linking issue - see above. thanks.
  • cbuchart
    cbuchart about 6 years
    @ashcatch just updating the link (broken since Trolltech is not Qt's owner anymore): doc.qt.io/archives/qt-4.8/moc.html