Reputation: 820
In my Application, I have a QWidget MyWidget
which I need to construct after a PushButton click. Now, MyWidget is a heavy widget with many children components and those children components have many components too. Now, when I try to construct the widget after the push button press, it takes sometimes for the widget to appear, which I don't like. So, I need to construct the widget before the PushButton clicked and keep an instance ready at hand. Thread seems perfect for this job. But I have little idea about Qt Thread.
Now can somebody suggest me how to approach the problem and what can be done to solve the problem?
Note: To say explicitly why is my widget so heavy, in MyWidget, I have 7*24 widgets, each having a stacked Widget with two widgets stacked on it each having a button.
Upvotes: 3
Views: 2458
Reputation: 2239
First of all Qt and pretty much every other framework (at last those that I know) that deals with UI elements have very specifics requirements for multi-thread support.
Qt needs every QObject
descendant (like QWidget
) to be assigned to a thread (see QObject::thread()
).
This property is automatically assigned on object creation to the thread where the object is being created.
The problem with this is that Qt also requires that a widget receive events only if it belongs to the same thread where the event loop is running (and it is correctly added to a parent widget).
If you are creating you huge widget at some different thread, it will not receive events until it is moved to the thread with the event loop and re-parented.
You can move the QWidget
to another thread by calling the QObject::moveToThread()
method. Suppose mParent
is your QMainWindow
and mMyWidget
is your huge widget:
mMyWidget->setParent(0);
mMyWidget->moveToThread(mParent->thread());
mMyWidget->setParent(mParent); // change this to match your layout requirements.
Check QWidget::setParent()
for more info.
The creation of your huge widget should be performed not at the same thread as your main thread. This is left as an exercise, since it is pretty much straight forward and Qt docs are extensive on threads.
Take care if your button is pressed before the creation of the widget is completed: you must synchronize the access to variable to avoid undefined behavior.
This is a very high level look at the problem, but is a start, and since you did not provide any code, I'm giving you a minimum ;D
Another option (and probably a better one) is to look why your widget is so time consuming to create, but without more information I can not help.
Upvotes: 1
Reputation: 98505
Qt does not support creation of widgets in non-gui threads. The reason is simple: widget constructors are free to access thread-unsafe APIs that can be used by the main thread at any time. Thus even if it might appear to work, it's really a bug in your code if you do it.
Generally speaking, in your heavyweight widget classes, parallelize the non-graphical, long-running initialization tasks. You can use QtConcurrent::run
for this purpose. Of course you need to make your implementation thread-safe for this purpose.
You must also ensure that you absolutely, positively don't use any blocking APIs in your widget code. No GUI code generally, but no widget constructor specifically, should ever:
wait for any file accesses to finish,
wait for any networking to finish,
wait for any database access to finish,
use any waitForXxxx
methods in Qt,
use things that may indirectly access the file system, such as QSettings
.
Upvotes: 4