Search code examples
c++multithreadingqtqwidget

use QGridLayout::addWidget with mutythread


Since creating widgets takes a lot of time, I try to create widgets in different threads and add them to the main layout, but that fails. When creating widgets and then adding them sequentially, the program works normally. Notifications I received: "QObject::setParent: Cannot set parent, new parent is in a different thread" Is there a way to do it?


Solution

  • No, there is no way to do it.

    Qt GUI classes including QWidget must be used only from the main thread. Quoting Qt documentation:

    Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.

    This is enforced in Qt code by a Q_ASSERT_X when you construct a QWidget:

    Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
        "Widgets must be created in the GUI thread."); 
    

    So, even if you would find some work around to make it work, you would not have any guarantee that your code will work in a reproducible way and that any Qt update will not break your code.

    Regarding your specific problem, creating widgets should not be time consuming. I can think of 2 reasons why it would be time consuming:

    • Your widgets are doing heavy computation when you create them. Then you shoul put the computation, and only the computation, in another thread.
    • You are creating a lot of widgets in one shot. The you can deffer the creation using the event loop. Basically, you create some widgets then post an event or set a timer that will create some more widget, etc. until you meet some stop conditions.