Crash on QObject::isWidgetType called in QWidget::showEvent
-
hello. I'm developing a window application and I want to load data from a widget before it is shown to the user.
So, override QWidget::showEvent, load data in it, and block using QEventLoop until it's done(to load data before widget shown to user).
However, I don't want infinite wait, So I connected QTimer::timeout signal to QEventLoop::quit slot.
Here is the example code I described. This example code also occured crash.void myWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); // loading some data... QTimer timer; QEventLoop loop; connect(loader, &dataLoader::finished, &loop, QEventLoop::quit); connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.start(3000); loop.exec(); }Sadly, this code will error with QObject::isWidgetType with high probability. When a crash occurs, the call stack is as follows(in debug mode).
Qt6Cored.dll!QObject::isWidgetType() line 120 Qt6Widgetsd.dll!qobject_cast<QWidget *>(QObject * o) line 785 Qt6Widgetsd.dll!QWidgetPrivate::showChildren(bool spontaneous) line 8319 Qt6Widgetsd.dll!QWidgetPrivate::::show_helper() line 7924 Qt6Widgetsd.dll!QWidget::setVisible(bool visible) line 8265 Qt6Widgetsd.dll!QWidget::show() line 7822 myExe.exe!main(int argc, char * * argv)...I know that a connection is automatically disconnected when the sender or receiver is deleted. Even if QTimer is used as a member variable or pointer rather than a local variable, the error still persists.
I suspected that even a very short block in showEvent would cause an error, but by removing the timer and calling loop.exec(), the error does not occur during infinite waiting (although the program is stopped, of course).
So, I got lost. what am I missing? -
You must not spin an eventloop in another event.
-
You must not spin an eventloop in another event.
@Christian-Ehrlicher Oops, thanks to help. Many answers tell me to use QEventLoop to wait for signals. There may be other ways like load the data before the event, but I'm just curious. Is using a blocking thread the only way to wait for a signal without using a QEventLoop inside the event?
-
@Christian-Ehrlicher Oops, thanks to help. Many answers tell me to use QEventLoop to wait for signals. There may be other ways like load the data before the event, but I'm just curious. Is using a blocking thread the only way to wait for a signal without using a QEventLoop inside the event?
@DeanLee said in Crash on QObject::isWidgetType called in QWidget::showEvent:
Is using a blocking thread the only way to wait for a signal without using a QEventLoop inside the event?
You should not do anything long-lasting in this showEvent which blocks the whole stuff since then your app is blocked and unusable (and e.g. windows will tell the user that the app does not respond). Do your loading or whatever before actually calling show()
-
@DeanLee said in Crash on QObject::isWidgetType called in QWidget::showEvent:
Is using a blocking thread the only way to wait for a signal without using a QEventLoop inside the event?
You should not do anything long-lasting in this showEvent which blocks the whole stuff since then your app is blocked and unusable (and e.g. windows will tell the user that the app does not respond). Do your loading or whatever before actually calling show()
@Christian-Ehrlicher
I was just curious :)
I too think it's the best way for what I want. In practice, the blocking time would be very short, so the app does not respond would not appear, but I understand that blocking within an event is bad design no matter how short it is. Thanks again. -
@Christian-Ehrlicher
I was just curious :)
I too think it's the best way for what I want. In practice, the blocking time would be very short, so the app does not respond would not appear, but I understand that blocking within an event is bad design no matter how short it is. Thanks again.@DeanLee
And I was thinking about this :)If it is required to load data only once
showEvent()is called. I think I would connectdataLoader::finishedto a slot. AllowshowEvent()to exit and widget to be shown, which should allow (show empty or whatever) for data not yet having been loaded. Make slot for data load finished populate the widget as required, instead of duringshowEvent(). -
@DeanLee
And I was thinking about this :)If it is required to load data only once
showEvent()is called. I think I would connectdataLoader::finishedto a slot. AllowshowEvent()to exit and widget to be shown, which should allow (show empty or whatever) for data not yet having been loaded. Make slot for data load finished populate the widget as required, instead of duringshowEvent().