Yes, I know that you cannot use GUI things from non-GUI threads. However, it seems reasonable to be able to create a QWidget object, send it to the GUI thread, and then send
Qt insists that widgets be created within the GUI thread. It disables moving widgets to different threads to prevent them from existing outside of the GUI thread. Your example above does not, in fact, move the BasicViewer
to a different thread; it only moves BasicViewerWrapper
to a different thread. You can see this if you print out the pointer to the containing thread within BasicViewerWrapper::Function
and BasicViewer::Function
:
std::cout << std::hex << thread() << std::endl;
If you really wish to trigger the creation of widgets from outside the GUI thread, it is more advisable for other threads to notify the GUI thread to create the widgets that you desire. You can either emit a signal from the non-GUI thread that connects to a slot in the GUI thread that creates the widgets, or you can invoke a function within the GUI thread to create the widgets for you using QMetaObject::invokeMethod.
EDIT
Unfortunately, there is no way to invoke a method in a different thread other than QMetaObject::invokeMethod
if you are attempting to perform the invocation outside of a QObject
. In the past, I've tried to tackle readability by placing the method invocation in a separate class or function, but admittedly, it's not perfect.
Your 3rd example is not working because QObject::moveToThread
is not synchronous. Control must return to the destination thread's event loop before the object is actually moved to the destination thread. As such, you probably need a combination of a sleep statement and a call to QCoreApplication::processEvents
after calling moveToThread
. After these calls, you should probably call basicViewerWrapper::create()
and basicViewerWrapper::exec()
via QMetaObject::invokeMethod
.