Implementing a Splash Screen with Qt Quick
This article explains how to implement a splash screen in Qt Quick using pure QML, or a combination of Qt C++ and QML. In addition, it provides tips and tricks on how to avoid the common pitfalls.
Article Metadata
Tested with
Article
Contents |
Introduction
The main purpose of the splash screen is to improve the user experience during application launch – displaying a screen immediately makes the app appear responsive, while attractive animations can distract the user from the wait time for full application boot (which takes at least three seconds for a Symbian application using Qt Quick Components). The splash screen is also an opportunity to promote application (or company) branding, and to provide other basic information like versioning.
When implementing a splash screen with Qt Quick, there are two choices: use either a Qt C++ and QML combination (referred to as "Combination approach" in this document) or to stick with QML only. The pure QML solution has the limitation that animations cannot be played while the main file is loaded - so some apps may need to restrict themselves to splash screens without animations to reduce the overall load time. The "Combination approach" requires the use of C++ but is even more straightforward, and does not block the UI while the main file is loaded.
The most important aspects you need to address when implementing a splash screen are the following:
- How to show the splash screen as fast as possible during app launch?
- How to design an efficient splash screen?
- How to handle the loading of the main application?
- How to switch the content with style (e.g. transitions) and how to clean up afterwards ( i.e. free the resources that are no longer needed)?
Combination approach
Launching the splash screen
The simplest solution is to set the splash screen QML file as the source for QDeclarativeView in your main.cpp as soon as possible:
QDeclarativeView view;
...
view.setSource("MySplashScreen.qml");
view.showFullScreen();
This can be also done by a Qt C++ helper class:
// mView is a pointer to QDeclarativeView instance
QDeclarativeComponent splashScreenComponent(mView->engine(), QUrl::fromLocalFile("MySplashScreen.qml"));
QDeclarativeItem splashScreenItem = qobject_cast<QDeclarativeItem*>(splashScreenComponent.create());
splashScreenItem->setWidth(mView->width());
splashScreenItem->setHeight(mView->height());
mView->scene()->addItem(splashScreenItem); // The view takes ownership
Loading the main application
The main application is typically loaded using a Qt C++ helper class:
// mView is a pointer to QDeclarativeView instance
QDeclarativeComponent component(mView->engine(), QUrl::fromLocalFile("main.qml"));
QDeclarativeItem *mainItem = qobject_cast<QDeclarativeItem*>(component.create());
mView->scene()->addItem(mainItem); // The view takes ownership
This approach doesn't block the UI so using animations in your splash screen is not a problem.
Hiding and deleting the splash screen and showing the main content
There are several ways to hide the splash screen when implementing a combination approach. The simplest solution is to just delete the splash screen item but from a UX point of view, a simple transition like fading is preferred. You can implement the transition in your splash screen QML file:
Item {
id: splashScreen
signal hidden()
function startHideAnimation() {
hideAnimation.start();
}
...
SequentialAnimation {
id: hideAnimation
PropertyAnimation {
target: splashScreen
property: "opacity"
duration: 800
to: 0
}
ScriptAction { script: splashScreen.hidden(); }
}
}
Then connect the signal in your Qt C++ helper class:
// mSplashScreenItem is a member variable and a pointer to QDeclarativeItem
connect(mSplashScreenItem, SIGNAL(hidden()), this, SLOT(destroySplashScreen()));
After the main QML item is created, invoke the hiding animation of the splash screen:
QMetaObject::invokeMethod(mSplashScreenItem, "startHideAnimation");
And finally, once the animation is executed, hidden() signal is emitted which triggers your destroySplashScreen() method:
void MyMainAppLoader::destroySplashScreen()
{
mView->scene()->removeItem(mSplashScreenItem);
delete mSplashScreenItem;
}
Pure QML approach
The best way to architect an app with a splash screen in pure QML is to have a separate element to handle the loading of the splash screen and the main application, and to manage the content switching between them. This app loader is the QML file that you set as the source in C++, referred to below as MainAppLoader:
view.setSource("MainAppLoader.qml");
view.showFullScreen();
Care must be taken with the implementation of MainAppLoader to ensure that the splash screen is loaded and displayed quickly.
Launching the splash screen
The splash screen could be a static child element of the MainAppLoader but this would make it difficult to de-allocate its resources. Instead use the QML Loader element to dynamically allocate the splash screen. For example, in the MainAppLoader we load the splash screen as shown:
Loader {
id: splashScreenLoader // ID needed for so we can later delete the item
width: parent.width
height: parent.height
source: Qt.resolvedUrl("MySplashScreen.qml");
}
Setting the source property loads the splash screen as soon as the Loader has been constructed.
Loading the main application
There's not enough CPU time for the UI to do anything while the Loader element loads the main QML content. This means that any splash screen animations would stop while the main QML file is loaded. As a result, you need to delay loading the main file until the splash screen can be rendered on the screen and you should not have any animations running when the main file is loaded.
In your MainAppLoader you will have a Loader element for loading the main QML file:
Loader {
id: mainLoader
width: parent.width
height: parent.height
}
And a timer to delay the start of the loading procedure:
Timer {
id: firstPhaseTimer
interval: 700
running: true
repeat: false
onTriggered: {
if (!mainLoader.Loading) {
// Start to load the main application
mainLoader.source = Qt.resolvedUrl("main.qml");
secondPhaseTimer.start();
}
}
}
The second timer (secondPhaseTimer in the snippet above) is needed for hiding and deleting the splash screen, and will be covered in the last step.
Hiding and deleting the splash screen and showing the main content
Hiding the splash screen is implemented with a simple "Behavior on <property>" method:
Item {
id: splashScreen
...
Behavior on opacity { NumberAnimation { duration: 500 } }
}
The Timer elements can be used as described earlier. The second phase timer is needed because Timer elements are affected by the loading too; they stop while loading takes all the CPU time and when the loading is completed they try to catch up. Using two different timers solves this issue. The first timer was used to start the loading and the second is used to hide and delete the splash screen:
Timer {
id: secondPhaseTimer
property int phase: 0
interval: 1000
running: false
repeat: true
onTriggered: {
if (phase == 0) {
// Hide the splash screen
if (splashScreenLoader.item) {
splashScreenLoader.item.opacity = 0;
}
phase += 1;
}
else {
// Delete the splash screen.
//
// By setting the source property to an empty string destroys
// the loaded item.
splashScreenLoader.source = "";
secondPhaseTimer.stop();
}
}
}
You can, of course, use the same trigger for deleting the splash screen as described in Qt C++ approach earlier: make the splash screen emit a signal when it is hidden so you do not have to have "phases" in your timer.
Splash screen content
The splash screen must be displayed quickly in order to be effective. The splash screen QML element should only contain elements and graphics that can be loaded and displayed quickly. Do not use Qt Quick Components in a splash screen, as loading the Components takes a long time. Use only the general QML elements. You can still use graphics like small images, gradients in the background and even animations. There is no rule on the number of elements or images to use; the best way to evaluate the performance is by testing on the device. If your splash screen takes two seconds or more to load, you should consider optimising it. Note that the more elements and graphics you use, the more important it is to free the allocated resources afterwards.
Here are a few examples of different splash screens:
FileList example: Background gradient, application title and a custom progress bar
ToDo Lists example: A simple splash screen with a nice background image
Weather Forecast example: Animated background gradient, application title and animated PathView element
Back button
If the splash screen stays on the screen for a long time, for example while data is being retrieved over the network, it is recommended to provide not only information to the user about what is going on but also a possibility to cancel the launch. UX-wise the most straightforward approach is to provide a back button. Like discussed before, the button should not be implemented with Qt Quick Components, unless it is shown only after the Components have been loaded. Placing a custom button, with similar icon to Component's back button icon, to the bottom-left corner of the screen is easy:
Item {
width: ...
height: ...
anchors {
left: parent.left
bottom: parent.bottom
margins: 10
}
Image {
id: backIcon
anchors.fill: parent
source: "my-back-icon.png"
}
MouseArea {
anchors.fill: parent
onClicked: Qt.quit();
}
}
Make sure that the the quit() signal of the QDeclarativeEngine instance associated with the view is connected to the QApplication before showing the back button because otherwise tapping the button does nothing:
connect(mView->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
If your main application is doing something that should not be interrupted, you should implement communication between the splash screen and the main application. This can be done, for example, with signals. When the user decides to cancel the loading by exiting, notify your main application and take appropriate measures and then do the exit. Fortunately, there is seldom need for implementing this.
Summary
This article covers the two main approaches for creating a splash screen with Qt Quick. The pure QML approach may not be suitable if you have an app with a long load time, and you want to use animations in your splash screen. The C++ approach is more flexible, but does require a bit more knowledge of C++.
Within these approaches there are possibilities for many different solutions. Just keep in mind the few basic rules: display the splash screen as quickly as possible, provide the user with relevant information or just a nice experience, and finally gracefully transition to the actual application content without adding delays unless necessary, e.g. in case you have some important information in your splash screen or your application needs to access data over network.
Finally, take advantage of the full source code of these examples with splash screens:
- FileList: QML and Symbian only
- ToDo Lists: Qt C++ & QML
- Video Streamer: Qt C++ & QML, splash screen used to also handle the delay caused by loading data from the network
- Weather Forecast: Qt C++ & QML, splash screen implemented for Symbian build only


Babylongreece -
Why this code won't work for app the use qmlapplicationviewer?Only half of the splashscreen work and it mess up the ui in main app with weird rendering for app menubabylongreece 14:20, 30 March 2013 (EET)
Hamishwillee - There should be enough here for you to work it out yourself
Hi Babylongreece
There are three working example projects linked above and the code samples appear to show the key parts of any integration with app code. Given that, I suspect that your integration probably has an error which will require you to do more debugging (ie this is not a question the author could answer given the information provided).
I suggest you do so some debugging, then provide more specific explanation of the problem in the discussion boards.
Regards
Hamishhamishwillee 05:55, 2 April 2013 (EEST)