QWidget: Must construct a QApplication before a QWidget error
-
So I am trying to separate the instantiation of QApplication from main and put it in a class member function.
I have a class that allows me to instantiate as many Qt windows as I want on a separate thread:
class QtWindowInit: public QWidget { Q_OBJECT public: QtWindowInit(QWidget* parent = 0) { /* Initialize stuff */ } inline void Init() { boost::thread (StartThread()); } private: inline void StartThread() { char *argv[] = {"program name", "arg1", "arg2", NULL}; int argc = sizeof(argv) / sizeof(char*) - 1; QApplication app(argc, argv); // Code to initialize window and add QWidgets in here app.exec(); } // Other class member variables here }
Then I have other classes to use this QtWindowInit class to create a button for example. They do not depend on Qt, all the Qt is done in the QtWindowInit class
class CreateButton { public: CreateButton() { /* Do stuff */ } // Other functions private: QtWindowInit _QtWindowInit; // Here is the problem }
So the issue here is that the CreateButton class does not create a QApplication. When we create a CreateButton object it will then create a QtWindowInit object and will fail because QApplication has not been called yet and QtWindowInit constructor takes in the default QWidget* parent = 0 constructor. I end up with this error "QWidget: Must construct a QApplication before a QWidget". Anyone know how I can work around this problem?
-
So I am trying to separate the instantiation of QApplication from main and put it in a class member function.
I have a class that allows me to instantiate as many Qt windows as I want on a separate thread:
class QtWindowInit: public QWidget { Q_OBJECT public: QtWindowInit(QWidget* parent = 0) { /* Initialize stuff */ } inline void Init() { boost::thread (StartThread()); } private: inline void StartThread() { char *argv[] = {"program name", "arg1", "arg2", NULL}; int argc = sizeof(argv) / sizeof(char*) - 1; QApplication app(argc, argv); // Code to initialize window and add QWidgets in here app.exec(); } // Other class member variables here }
Then I have other classes to use this QtWindowInit class to create a button for example. They do not depend on Qt, all the Qt is done in the QtWindowInit class
class CreateButton { public: CreateButton() { /* Do stuff */ } // Other functions private: QtWindowInit _QtWindowInit; // Here is the problem }
So the issue here is that the CreateButton class does not create a QApplication. When we create a CreateButton object it will then create a QtWindowInit object and will fail because QApplication has not been called yet and QtWindowInit constructor takes in the default QWidget* parent = 0 constructor. I end up with this error "QWidget: Must construct a QApplication before a QWidget". Anyone know how I can work around this problem?
Hi, and welcome to the Qt Dev Net!
@justiliang said:
Anyone know how I can work around this problem?
Don't let QtWindowInit inherit QWidget (or even QObject, for that matter).
There are two rules to follow:
- QApplication must be the first QObject created in your program.
- All GUI-related classes (QWidget, in particular) must be created in the same thread as QApplication, and all their methods must be called from that thread only.
-
I would also add to JKSH's answer that the docs state clearly:
For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.
This means that your classes using a QtWindowInit object are totally wrong because each QtWindowInit instance will create a new QApplication object+instance, which will conflict with the previous one(s) (they would not know which QApplication object should manage the events) -- unless you make it static, but then other problems arise, definitely thread unsafe.
That's why in most Qt applications it is very often to find a QApplication (or QCoreApplication) object declaration in the very first lines of main(), and then forget about it at all.Although I am not a threads expert, I can think of creating a main thread containing the QApplication object and the methods to create new widgets. Then, in the other threads of your application, you should just give the main thread a hint on which widget to create.