[SOLVED] QSplashScreen doesn't show unless I run QApplication::processEvents() 1000 times !?
-
In my application I have a lot of data loading when it starts, so I want to have a splash screen that says what's loading. The issue I'm having is when I show the splash screen it doesn't show. This is the code I was using originally:
@
QPixmap pixmap(config->getSplashPath());
splash_screen = new SplashScreen(pixmap);
splash_screen->show();
QApplication::processEvents();
@And this is the only way I can get it to show:
@
QPixmap pixmap(config->getSplashPath());
splash_screen = new SplashScreen(pixmap);
splash_screen->show();
for(int i = 1; i <= 1000; i++) QApplication::processEvents();
@Later I use this:
@
splash_screen->showMessage("Some text I want to show");
QApplication::processEvents();
@If I don't have the processEvents() run 1000 times then the splash screen only shows for a second AFTER everything has already be finished. I know I can put my "initialization" code in a second thread, but from what I've been reading I shouldn't need to, the QSplashScreen examples themselves show only using processEvents(), so what's the best way to handle this?
-
Hi,
Since your splash screen is a custom class, are you doing anything unusual in it ?
-
No, right now my SplashScreen class is very empty, it's essentially as if I'm directly using QSplashScreen, the only reason I created a class is so I can play with it once I get it working properly.
-
When are you creating this splash screen ? In your main function ?
Can you show the code where you use it ? -
No, it's created in the constructor of my QMainWindow.
I'll post some of my code, sorry about the syntax, I just copied and pasted, my editor is set to about 100 columns.Here's the constructor:
@
MainWindow::MainWindow() {
// Initialize config singleton
Config::init();setWindowIcon(QIcon(config->getIconPath()));
// If config is empty, launch first run dialog
if(config->isEmpty()) {
int result = FirstRunDialog::run(this);// If FirstRunDialog was cancelled then free memory and quit app
if(!result) {
Config::destroy();
// This 'exiting' status needs to be passed back to main() function and then 'return 0'
// Using exit(0) here sometimes results in strange segfault with no real stack trace o_O
exiting = true;
return;
}
}// Initialize splash screen
SplashScreen::start();// Initialize global actions
eComics::Actions::init(this);// Initialize library right after Config and Actions are finished, but before everything else
Library::init();// Initialize child widgets
status_bar = statusBar();
main_splitter = new QSplitter(this);
MainSidePane::init(main_splitter);
MainView::init(main_splitter); // Must be initialized after MainSidePane
MenuBar::init(this);
main_side_pane->initSelectedList(); // Must happen after MainView is initialized// Add widgets to window
setCentralWidget(main_splitter);
main_splitter->addWidget(main_side_pane);
main_splitter->addWidget(main_view);
main_splitter->setSizes( {150, 650} );
main_splitter->setCollapsible(1, false);resize(800, 600);
// Initialize comic info dialog
ComicInfoDialog::init(this);// Initialize preferences dialog
PreferencesDialog::init(this);// Connect signals to actions
connect(eComics::actions->statusBar(), SIGNAL(toggled(bool)), this,
SLOT(toggleStatusBar(bool)));
connect(eComics::actions->quit(), SIGNAL(triggered()), qApp, SLOT(quit()));
connect(eComics::actions->fullScreen(), SIGNAL(toggled(bool)), this,
SLOT(toggleFullscreen(bool)));SplashScreen::finish();
}
@And here's the implementation of my SplashScreen (it's a singleton):
@
#include "SplashScreen.hpp"#include <QApplication>
#include "Config.hpp"
#include "MainWindow.hpp"SplashScreen *splash_screen = nullptr;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
SPLASHSCREEN PUBLIC METHODS *
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
//THIS IS A STATIC METHOD
void SplashScreen::start() {
if(splash_screen == nullptr) {
//THIS PRINTS RIGHT AWAY NO PROBLEM
qDebug() << config->getSplashPath();
QPixmap pixmap(config->getSplashPath());
splash_screen = new SplashScreen(pixmap);
splash_screen->show();
/for(int i = 1; i <= 1000; i++)/ QApplication::processEvents();
}
}//THIS IS ALSO STATIC
void SplashScreen::finish() {
splash_screen->QSplashScreen::finish(main_window);
delete splash_screen;
splash_screen = nullptr;
}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
SPLASHSCREEN PRIVATE METHODS *
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) : QSplashScreen(pixmap, f) {
// Don't allow clicking on splash screen to close it
setEnabled(false);
}SplashScreen::SplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f) :
QSplashScreen(parent, pixmap, f) {
setEnabled(false);
}SplashScreen::~SplashScreen() {}
@ -
-
Also, I tried putting it in my main.cpp, but it didn't make a difference.
-
Well I figured out the only thing that seems to work, I just have to put all my initialization work in a worker QThread, I was hoping to avoid that using processEvents(), but that doesn't look like it's going to happen.
-
Does it also happen if you use the same code without any modification as the example provided in the documentation ?
By the way, what are you doing in your initialization ? Anything involving the event loop ?
-
The initialization code is loading the library from XML, and it scans user selected directories for new content, it is fairly intensive (if they have a lot of content), but there is nothing GUI related (I double checked in case I forgot about something).
-
There is use of signals and slots in the initialization, that is separate from the event loop right?
-
I should also note that I don't even run app.exec() until after the initialization and the splash screen disappears.
-
Ok, then it's clearer now. The event loop is mandatory for signals and slots to work. That's why it's working if you use a secondary thread: QThread starts it's own event loop.
Anyway, following your description, it sounds that using a secondary thread would be best. QFileSystemModel uses one to populate its data and a signal to let the developer know it's ready to be used.
-
OK, awesome, thanks for the info! :D
-
You're welcome !
If that answers your question then please update the thread title prepending [solved] so other forum users may know a solution has been found :)