Preventing GUI freeze while loading a large 'library' widget
-
That's probably coincidence, because of blocking code. If you want the
QSplashScreen
to show immediately, instantiate it directly inmain.cpp
and process events manually after callingshow()
. Code wise not ideal, but it works and ensures your splash screen is up.I have something like this in mind:
int main(int argc, char *argv[]) { QApplication a(argc, argv); // Always show splash screen const QPixmap pixmap(":/someStartupPic.png"); QSplashScreen splash(pixmap); splash.show(); a.processEvents(); // I'll deny that I told you so! // do your stuff // ... someWidget.show(); // Tell splash screen that you're done splash.finish(&someWidget); return a.exec(); }
-
If you have stacked layouts you should only create the widgets that are visible and create the other stacked widgets only when switching over to them. Creating all widgets (even invisible ones) at start up is a bad idea (speaking from experience).
Using a timer won't really work because this is all still the same thread and you have to wait for the thread to be available. The only option is to use processEvents() (which in general you shouldn't) to process the pending show event.
-
And then we don't know, what drives complexity and consumes time creating these widgets. If it's about a lot of data, large downoads or generating a complex pixmap, it may actually be possible to spawn worker threads for parts of the heavy lifting.
-
@SimonSchroeder the timer suggestion was just for the OP to have the "initial" widget shown not something that would avoid the blocking behavior.
-
@SGaist
True, but nonetheless the OP should be aware that if loading all stacked widget pages really takes "quite some time" at start up, and even with a splash screen the OP does not want to make the user wait that long, there is something to be said for @SimonSchroeder's suggestion that one can delay the population of each page until each page is shown initially. Though one small "gotcha": I found in the past that the size of pages in stacked widgets is set to the size of the largest page. If you populate some pages later on and they are "larger" I am not sure whether either the user would see the overall page size grow or it would not adjust the size of a new page and would limit it to whatever the current size is. -
@RemDup What I use is actually a 2nd executable, that launches and shows the please wait sign and a little animation, while the main application loads in the background.
Once that is finished, I use QSharedMemory/QLocalSocket to tell the other program to close itself. Or sending kill to the QProcess.
-
@JonB said in Preventing GUI freeze while loading a large 'library' widget:
@SGaist
True, but nonetheless the OP should be aware that if loading all stacked widget pages really takes "quite some time" at start up, and even with a splash screen the OP does not want to make the user wait that long, there is something to be said for @SimonSchroeder's suggestion that one can delay the population of each page until each page is shown initially. Though one small "gotcha": I found in the past that the size of pages in stacked widgets is set to the size of the largest page. If you populate some pages later on and they are "larger" I am not sure whether either the user would see the overall page size grow or it would not adjust the size of a new page and would limit it to whatever the current size is.Totally agree, I was just pointing that this suggestion was at best to be considered a workaround to achieve what was originally requested: get the "please wait" widget in the front of the user.
By all means, if it's possible, loading only what is necessary at the point of use will be a better use of resource. -
@SimonSchroeder I tried the processEvents() but, even then, the black screen stayed during the loading time. That's what drove me to ask about the issue on this forum!
The best solution so far for me is a QTimer (as @SGaist suggested) with a 50ms period. But even then, I sometimes still see a black screen.
I did not go through with the QSplashScreen suggestion, since the problem must be solved while the main window is visible (the user can indeed decide to reload another set of widgets at any time through the main window menu). -
@RemDup
The alternative way which should work is not to load the stacked widget initially. Show the main window and set off a 0 duration singleshot timer before entering the main event loop. In the slot, which will be run just after the main window (or whatever) is shown, create and load the other widgets.