Splashscreen not shown, only when event queue is running
-
Hi,
I want to use a splash screen while starting my application. I have found the following guide: http://www.developer.nokia.com/Community/Wiki/Implementing_a_Splash_Screen_with_Qt_Quick
Basicly I have to do the following:
Show splash screen:
@
QDeclarativeComponent splashScreenComponent(mView->engine(), QUrl::fromLocalFile("MySplashScreen.qml"));
QDeclarativeItem splashScreenItem = qobject_cast<QDeclarativeItem*>(splashScreenComponent.create());
mView->scene()->addItem(splashScreenItem); // The view takes ownership
@Then do some load stuff, for example loading the BIG main qml file:
@
QDeclarativeComponent component(mView->engine(), QUrl::fromLocalFile("main.qml"))
QDeclarativeItem mainItem = qobject_cast<QDeclarativeItem>(component.create());
mView->scene()->addItem(mainItem); // The view takes ownership
@The problem is that I do not see the splash screen. Only when I start the Qt event queue:
@
lApp.exec();
@This is not logical (for this splashscreen thing to work) because the main event queue is blocking.
-
Right before doing your second code snippet, do something like this:
@mView->show(); // Not sure of what your mView is but that's the idea...
lApp.processEvents(); // This will dispatch the show and paint events without really entering the event loop. Your splashscreen will be displayed.@
I guess this could work, however while you are loading the main.qml file, the UI will be frozen, only showing a static MySplashSreen.qml file (no animations whatsoever).
If you need animations, or UI responsiveness during the initial load, you should try to load the main.qml file in a separate thread. -
I already tried:
@
mView->show(); // Not sure of what your mView is but that's the idea...
lApp.processEvents(); // This will dispatch the show and paint events without really entering the event loop. Your splashscreen will be displayed.
@This showed a white screen, no qml file. I don't have any animations in my QML file, it's just a black rectangle.
-
I see... don't know the internals of QML, however your widget is shown. I guess that leaves the second option then. You can use the Qt concurrent framework. You can use a QFutureWatcher to emit a signal when loading is complete and then add it to the mView:
@
QDeclarativeItem* loadComponent(QDeclarativeComponent* component)
{
QDeclarativeItem* item = qobject_cast<QDeclarativeItem*>(component->create());
Q_ASSERT( item ) // Better check that!
item->moveToThread(qApp->thread()); // To move it back to the main thread
return item;
}// -- Then in your code --
QFutureWatcher watch;
watch.setFuture(QtConcurrent::run(&loadComponent, &component));
@
And use the QFutureWatcher finished() signal to catch the end of the loading.There might be some concurrency issues here, I don't know what goes on in the background while loading the QML so... It's worth a try nevertheless.
-
I have found the solution: use a QTimer::singleShot:
@
void main()
{
Qapplication lApp;
QTimer::singleShot(100, this, SLOT(OnLoadApplication()));
ShowSplash();
lApp.exec();
}
@Then:
@
void OnLoadApplication()
{
DoSomeHeavyLoadStuff();
ShowMainWindow();
}
@The lApp.exec() after the ShowSplash() starts up the Qt eventing queue and thus shows the splash screen. The timer causes the OnLoadApplication to be called which can be used to start your app and show the main window.