Qt signals & inheritance question
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.
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, 2022Comments
-
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 inmatrixVisualization.h
- it's inqwt_plot3D.h
, but I thought that since I inherit fromPlot3D
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 about 15 yearsHi, 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 about 15 yearsOops. Obviously I should have used "public: signals:", but that hasn't helped.
-
Pete about 15 yearsI 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,double)), 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 about 15 yearsRight - 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 about 15 yearsWhen 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 about 15 yearsSpacing 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 about 15 yearsThanks for the clarification =]
-
Idan K about 15 yearsPete, 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 about 15 yearsThat 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 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 about 15 yearsThe 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 about 15 yearsthe 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 about 15 yearsUnder 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 about 15 yearsashcatch, 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 about 15 yearsQwt3D is a namespace? Is your matLinePlot in the same namespace or do you have a using directive somewhere?
-
Pete about 15 yearsYeah, I had the namespaces settled, the issue was a) the multiple inheritance and b) a linking issue - see above. thanks.
-
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