I need to create a widget in a separate thread and to set MainWindow for it as a parent widget. Creation of a thread cannot be avoided.
In the constructor of a new widget I am specifying a pointer to MainWindow, but give
QObject::setParent: Cannot set parent, new parent is in a different thread
How to solve this?
P.S. Child widgets may be numerous.
You cannot create UI widgets outside of main thread
This is not possible. See the following code reference for details why not:
QObject source code
In particular, you would need to pay attention to this warning:
"qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");"
which you got on the command line based on your question, so this is all expected.
As the warning says, you need to make sure that the parenting happens in the same thread between the parent and child.
Creation of a thread cannot be avoided. How to solve this?
I am afraid you will need to refactor the code by either moveing this out of your thread into the same where the parent is or/and not have the separate thread at all.
Based on the information in your question, currently, it is not possible to say more since we do not yet completely know the functionality of your other thread.
Hope this helps with explaining it.
Related
I have the follow constellation:
A qt gui thread with MainWindow
Another thread which essentially is a CameraManager...everytime a camera is added/removed the MainWindow will be informed.
It roughly looks like this:
Mainwindow derives from ICameraAddedConsumer
MainWindow implements ConsumeCameraAdded and creates widget inside this function. It subscribes itselv as a consumer to the CameraManager
CameraManager calls ConsumeCameraAdded of all it's consumers (MainWindow) when a new camera is added.
The problem is that CameraManager lives in a different thread and Qt will obviously complain about this since a widget is not created in the same thread as the mainwindow was.
Any suggestions how I can solve this?
As per comments, using signals/slots between QObjects in different threads should take care of the issue "automagically."
Barring that, and assuming MainWindow/ICameraAddedConsumer is a QObject, one idea could be to use something like:
QMetaObject::invokeMethod(consumer, "ConsumeCameraAdded", Qt::QueuedConnection, ...)
where consumer is a pointer to the MainWindow/ICameraAddedConsumer instance.
There's QWaitCondition but I'm not sure that makes sense in this case (though it could be adapted I suppose).
Otherwise... don't create the widget in ConsumeCameraAdded() but set some flag there (and return) and then use a QTimer or QObject::timerEvent() to periodically check the flag and create widget if it is set. Unfortunately I'm pretty sure you will not be able to create or start a timer within ConsumeCameraAdded() itself because of threading issues.
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?
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.
I am new in Qt.I have a QTableWidget which is suppose to get continuous data from different threads of RTI DDS subscriber.I was using setUpdatesEnabled() property of the QTableview for updating values from another class.
But it also blocks the QTableWidget for in-between operations like selecting another row and whenever i try to add QPushButton in a certain column of QTableWidget with the help of setCellWidget(),it is making a separate PushButton instead of placing it inside that cell.
As commented, you should do no GUI update from anywhere but the main thread. So use a signal/slot connection to go back from a worker thread to the main thread and then do the GUI update (emit the signal from the worker thread and make sure the slot is being executed from the main thread, this should behave like this with default connection). Be careful to the lifetime of the variables passed to the emited signal if slot is executed through a Qt::QueuedConnection.
Then, for your QPushButton not being in the cell. Make sure its parent is the QTableWidget upon creation (but I doubt this is really mandatory because I expect QTableWidget will make itself parent of the widget when setCellWidget is called).
It's hard to hep more with no code being posted in the OP.
QMenu can be created by using popup() or exec(). The former creates it asynchrously while the latter blocks. But this isn't useful when you're using a QMenuBar (AFAIK).
My question is, is it possible to tell QMenuBar to only popup asynchrous/modeless QMenus? I'm not sure the terms are correct, but all I want is a Menu that won't block the rest of the application when users click on it.
The workaround you're looking for is to move your objects that can't live with such "abuse" to a separate QThread. If you have a clean interface using signals and slots, this is trivial. Just use moveToThread() and you're done. You don't need to worry about anything else.
I'm wondering if it is possible to capture an event that is generated when all
Qt objects are initialized and ready ?
It seems that some things can't be done in window's constructor. And they work fine in slot implementation.
For example, when I want to access root window of my application I do it like that
// in *.h
MainWindow* rootWindow
// in *.cpp
rootWindow = qobject_cast<MainWindow *>(this->window());
If it is done in the contructor I can't use rootWindow object - it couses runtime error.
There is no relevant slot to implement. And create event in QMainWindow class is not virtual.
Thanks for help :)
You can use a single-shot timer for this. In your main window class, define a slot function called say, appReady(). In the constructor, create and connect a single shot timer using QTimer::singleShot(0, this, SLOT(appReady())); This timer should fire as soon as the event loop is up and running and there are no more startup events pending.
How can you be sure that root window is in fact MainWindow? Later in the project lifetime you could feed your widget to a different parent (for example a few layers of QFrame decorations for layouting purposes) and this code will fail.
Pass it in as an explicit parameter in the constructor instead.
Unless it is MainWindows all the way down :)