Multithreading Qt: Cannot access a Qt object after app.exec()
-
So I have a class called QtWindowInit, that initializes some QWidgets in a seperate thread. It instantiates the QApplicaton object in this seperate thread. In the example below it initializes a LED that I created.
class QtWindowInit { public: inline void Init() { _qtThread = boost::thread(&QtWindowInit::StartThread, this); } inline void StartThread() { char *argv[] = {"program name", "arg1", "arg2", NULL}; int argc = sizeof(argv) / sizeof(char*) - 1; QApplication app(argc, argv); // Some code to initialize the window _led = new QGraphicsEllipseItem(50, 50, 50, 50); _led->setBrush(Qt::gray); // Some code to add it to the window and then call show() app.exec(); }
Then I have a main:
int main(int argc, char *argv[]) { QtWindowInit LED(); LED.StartThread(); LED._led->setBrush(Qt::red); // This line of code causes the gui to show nothing }
With the above line of code where I set the brush color, the gui does not even show up. It doesn't crash and I don't get any errors. Without that line, the gui works and the led shows up but it is gray. Could it be because I am trying to set the color after app.exec()? Is there a work around?
-
@justiliang said:
LED._led->setBrush(Qt::red); // This line of code causes the gui to show nothing
As I said in http://forum.qt.io/topic/53905/ , the methods of GUI-related objects can only be called in the thread that created QApplication.
-
@justiliang said:
LED._led->setBrush(Qt::red); // This line of code causes the gui to show nothing
As I said in http://forum.qt.io/topic/53905/ , the methods of GUI-related objects can only be called in the thread that created QApplication.
@JKSH Do you know of a work around for my case? I need somehow be able to change the color outside of the thread.
-
@JKSH Do you know of a work around for my case? I need somehow be able to change the color outside of the thread.
@justiliang said:
@JKSH Do you know of a work around for my case? I need somehow be able to change the color outside of the thread.
Yes, there are 2 ways to do handle this use-case:
- Emit a signal from your secondary thread.
- Call QMetaObject::invokeMethod() in your secondary thread.
For both ways listed above, use a Qt::QueuedConnection to connect your request to a QObject that lives in the GUI thread. When that QObject receives your request, it should call
setBrush()
for you. This way,setBrush()
is executed in the correct thread.See also the section about QObject thread affinity.