I have a big problem with my classes: I will use the Q_OBJECT macro in my subclasses. But if I define Q_OBJECT in my subclasses, it throws an exception. This is the exception:
undefined reference to `vtable for SubClassOne'
undefined reference to `vtable for SubClassTwo'
My SubClassOne and SubClassTwo inherits from BaseClass.
Here some Code: (All #includes are correct)
\\baseclass.h
class BaseClass
{
public:
BaseClass(QWidget *widget=0);
QHBoxLayout *mainLayout;
};
\\subclassone.h
class SubClassOne : public BaseClass, public QWidget
{
Q_OBJECT
public:
explicit SubClassOne(QWidget *widget=0);
};
\\subclasstwo.h
class SubClassTwo : public BaseClass, public QDialog
{
Q_OBJECT
public:
explicit SubClassTwo(QWidget *dialog=0);
};
Here comes the .cpp Files
//baseclass.cpp
BaseClass::BaseClass(QWidget *widget)
{
mainLayout = new QHBoxLayout();
}
//subclassone.cpp
SubClassOne::SubClassOne(QWidget *widget):BaseClass(widget)
{
setWindowTitle("Widget");
}
//subclasstwo.cpp
SubClassTwo::SubClassTwo(QWidget *dialog):BaseClass(dialog)
{
setWindowTitle("Dialog");
QPushButton *btn = new QPushButton();
QObject::connect(btn,SIGNAL(clicked()),SLOT(close()));
mainLayout->addWidget(btn);
setLayout(mainLayout);
}
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SubClassTwo *s = new SubClassTwo();
s->show();
return a.exec();
}
How can I use Q_OBJECT in my subclasses?
Your Q_OBJECT placement is fine in your code.
What you are hitting is that you forgot to include the generated moc file in your source such as:
baseclass.cpp (at the end of the file)
#include "baseclass.moc"
subclassone.cpp (at the end of the file)
#include "subclassone.moc"
subclasstwo.cpp (at the end of the file)
#include "subclasstwo.moc"
You need to make sure moc is generating these files for you though. You have not shown your buildsystem yet.
Also, please make sure to have one header and source file per "Q_OBJECT" classes. It is not strictly necessary, but it is a good practice.
You can of course resolve that at link time as well, but you will need to do either of those.
Moreover, once you have multiple inheritance, at least with Qt 4, you will need to inherit from the QObject subclass first, which is QWidget in your case. You can find the correct inheritance below.
subclassone.h
class SubClassOne : public QWidget, public BaseClass
subclasstwo.h
class SubClassTwo : public QDialog, public BaseClass
etc. Hope it helps.
Q_OBJECT must be the firs declaration in your class and any class inheriting QObject must be first in the list
class SubClassOne : public QWidget, public BaseClass
{
Q_OBJECT
public:
explicit SubClassOne(QWidget *widget=0);
};
\\subclasstwo.h
class SubClassTwo : public QDialog, public BaseClass
{
Q_OBJECT
public:
explicit SubClassTwo(QWidget *dialog=0);
};
you also need to run the moc on the header to generate the code needed to implement the slots and signals
Related
I've created base class - MainWindow. In this class I create object of another class "SecondWindow". By using object of SecondWindow I want to use function() method that is defined in base class. How can I do this?
I've tried to transfer my base class as a parameter to SecondWindow object but that wasn't working (probably becouse in MainWindow I have included "secondWindow.h" and in SecondWindow I tried to include "mainwindow.h" header files). Is there way to simply use functions/variables of base class?
mainwindow.h
#include<QMainWindow>
#include "secondwindow.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
SecondWindow *secondWindow;
void function();
}
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow()
{
secondWindow = new secondWindow();
function();
}
void MainWindow::function()
{
qDebug()<<"yes";
}
secondwindow.h
class SecondWindow : public QMainWindow
{
Q_OBJECT
public:
SecondWindow();
}
secondwindow.cpp
#include "secondwindow.h"
SecondWindow::SecondWindow()
{
//here I want to use function();
}
You would want to inherit your MainWindow class, which would then inherit QMainWindow()
So in secondwindow.h you would change
class SecondWindow : public QMainWindow
{
Q_OBJECT
public:
SecondWindow();
};
to
#include "mainwindow.h"
class SecondWindow : public MainWindow
{
Q_OBJECT
public:
SecondWindow();
};
And you will then be able to use function() in secondwindow.cpp
Also, you have another issue at hand and it's that your mainwindow uses a pointer to second window, but you will then have a circular dependence issue. (You need SecondWindow in order to compile MainWindow, however, you want SecondWindow to be able to use function()).
To resolve this, you need to forward-declare SecondWindow in your MainWindow class.
In mainwindow.h remove #include "secondwindow.h" and replace it with class SecondWindow;
I am new both QT and QML. I have a class, which instantiates subclasses. I would like to expose the methods within these subclasses to my UI with some qml binding.
For example
class MainClass: QObject
{
Q_OBJECT
Subclass subclass;
MainClass();
}
class Subclass:QObject
{
Q_Object
Subclass();
public slots:
void someMethod();
}
Main.C
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQuickView *view = new QQuickView;
MainClass mainclass;
view->rootContext()->setContextProperty("MainClass", &mainClass);
view->setSource(QUrl("qrc:/main.qml"));
view->show();
}
In this case I would like to access mainclass.subclass.someMethod() from within the QML UI.
Is there a good way to do this? Should I provide wrapper methods in MainClass for each function/property I would like to access.
It is possible by making SubClass a property of MainClass. For example:
class MainClass : public QObject
{
Q_OBJECT
Q_PROPERTY(SubClass *subClass MEMBER subClass CONSTANT)
public:
MainClass();
private:
SubClass *subclass;
};
These are called "grouped properties" in QML.
I have a function which I am trying to connect via signals and slots but the function isn't being called when I run the executable file. I have put a debug error in my function so I know it isn't being called. My code is shown below:
My header file:
#include "MyWidget.h"
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass: public QObject{
Q_OBJECT
public:
MyClass( QObject *parent = nullptr);
MyWidget *myWidget;
public slots:
void setTranslation(int value);
};
#endif
My source file:
#include "MyClass.h"
MyClass::MyClass(QObject *parent): QObject(parent)
{
some code here....
QSlider *xSlider = new QSlider(Qt::Vertical);
xSlider->setRange(0, 10);
QObject::connect(xSlider, SIGNAL(valueChanged(int)),
this, SLOT(setTranslation(int)));
some code here...
}
void MyClass::setTranslation(int value)
{
some code here...
}
You forgot to add the Q_OBJECT macro immediately after the class declaration. It is what the MOC (Meta Object Compiler) uses to generate additional meta information for your code.
class MyClass: public QObject
{
Q_OBJECT
// all other class data, member function declaration
public:
MyClass( QObject *parent = nullptr );
};
This should be good enough.
EDIT:
Also remember to take a nullptr defaulted QObject pointer in your default constructor.
This class no problem:
#include <QThread>
class LiveImageItem : public QThread
{
Q_OBJECT
public:
LiveImageItem(QPixmap pimg);
signals:
public slots:
};
BUT this class get problem associated with "Q_OBJECT" macro defined in header file
#include <QGraphicsPixmapItem>
class LiveImageItem : public QGraphicsPixmapItem
{
Q_OBJECT //this line will generate many errors in compiling
public:
LiveImageItem(QPixmap pimg);
signals:
public slots:
};
both their cpp file is the same:
#include "LiveImageItem.h"
LiveImageItem::LiveImageItem(QPixmap pimg)
{
}
I thought every QT object essentially inherited from QObject so if I inherit any of the subclass of QObject, I could have all the magics QObject offers. The 2nd version of the above (which is inherited from, say, QGraphicsPixmapItem) seems proved I was wrong. It turns out to be having lots of errors while compiling, all from moc files(automatically generated by QT). What happens?
Some of these errors are:
[qobject.h] error: 'QScopedPointer QObject::d_ptr' is
protected
[moc_LiveImageItem.cpp] error: within this context
...
According to the documentation QGraphicsPixmapItem is not a QObject, thus you cannot treat it as if it is. I would try to extend your class inheritance and do:
class LiveImageItem : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT //this line will generate many errors in compiling
[..]
As #vahancho said, QGraphicsPixmapItem is not a QObject. In fact, that can be said of most of the QGraphics*Item classes.
However, if you want to use signals and slots with QGraphicsSystem classes, you can inherit from QGraphicsObject: -
class LiveImageItem : public QGraphicsObject
{
Q_OBJECT
public:
private:
QPixmap m_pixmap;
};
You would then override the paint function in this class and draw the pixmap from there.
I'm studying the Qt4 library and I want to add some functionality to all the children of QWidget in my project. I need all widgets to have mousePressEvent overridden. Obviously I do not need to override it in every particular widget I use(I use many of them and I they to follow DRY rule) , instead I create a Foo class:
class Foo : public QWidget
{
Q_OBJECT
protected:
/* implementation is just a test */
virtual void mousePressEvent(QMouseEvent*) { this->move(0,0); }
};
And derive my button from it:
class FooButton : public QPushButton , public Foo
{
public:
FooButton (QWidget* parent) : QPushButton(parent) { };
};
But the event seems to be not overridden... What am I doing wrong?
Thanks in advance.
For the mousePressEvent access, try QObject::installEventFilter().
http://doc.qt.digia.com/stable/qobject.html
You are inheriting twice now from QWidget. This is problematic (see diamond problem).
Instead, drop your Foo class and move your custom mouse press event handler to your FooButton class:
class FooButton : public QPushButton
{
Q_OBJECT
protected:
/* implementation is just a test */
virtual void mousePressEvent(QMouseEvent*) { this->move(0,0); }
public:
FooButton (QWidget* parent) : QPushButton(parent) { };
};
If this doesn't suit the design of your application, then try using virtual inheritance instead. That is, change Foo to:
class Foo : public virtual QWidget
If that doesn't help, you should follow the advice of the other answers and install an event handler.
(You can read about virtual inheritance in its Wikipedia article.)
I suspect that the problem is that you're inheriting from QWidget twice, once through QPushButton and once through Foo.
From the way you phrased the question, I'm assuming that you want to do this for varying kinds of widgets, and thus don't want to have to subclass QPushButton, QLabel, QCheckBox, etc. If this is not the case then you should use Nikos's answer.
If not, your best bet is probably doing to be to use an event filter.
class MousePressFilter : public QObject {
Q_OBJECT
public:
MousePressFilter(QObject *parent) : QObject(parent) { }
protected:
bool eventFilter(QObject *watched, QEvent *event) {
QWidget *widget = dynamic_cast<QWidget*>(watched);
widget->move(0,0);
return false;
}
};
And then in your Foo class constructor:
class Foo {
Foo() {
installEventFilter( new MousePressFilter(this) );
}
};