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?



  • Hi and welcome to devnet,

    keep in mind that QApplication::exec() never returns.

    In your code everything is executed in the main thread; Qt suggest to create the application object and the GUI in the main thread.


  • Moderators

    @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.


  • Moderators

    @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:

    1. Emit a signal from your secondary thread.
    2. 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.