QML: Show animated splash screen at startup

QML is a great way to make nice interfaces but, currently, suffer a bit in the initial phase of loading since it could take some time if your QML code is complex or there are many image resources to load. In this case show a splash screen can be a good way to "inform" the user the app is started. More better have an animation will inform also the app is alive and still loading.


Full project can be found on GitHub here.

NOTE: in case you are looking for a specific splash screen solution for Android check this post.

Show a splash screen is a quite easy task but keep the animation running require some trick since the initial QML loading take a lot of resources that, in normal case, stop for a bit the main GUI loop (and then the animation too). Basically the main qml file to load have to be divided in the parts, one is the loading of the simple window show the splash screen that, once done, will start a secondary loader set in asynchronous mode for load the main qml app code in a background thread. Follow the code of main.qml:

import QtQml 2.2
import QtQuick 2.6

Item {
    Loader {
        id: mainWindowLoader
        active: false
        source: "qrc:/window.qml"
        asynchronous: true
        onLoaded: {
            item.visible = true;
            splashScreenLoader.item.visible = false;
            splashScreenLoader.source = "";
        }
    }

    Loader {
        id: splashScreenLoader
        source: "qrc:/splashscreen.qml"
        onLoaded: {
            mainWindowLoader.active = true;
        }
    }
}

As you can see there are two Loaders but the first is not active. At program startup the second loader is started. Once finished loading the window splash screen it start the first loader who load the main window (non visible). The splash screen window is quite simple, a text message and BusyIndicator control showing the animation for give the "feel" the app is alive and loading. Please note than once main window has been loaded it is showed and the splash screen window is unloaded by setting an empty string to loader source.

import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Window 2.2

Window {
    id: splashScreen
    modality: Qt.ApplicationModal
    flags: Qt.SplashScreen
    width: 300
    height: 300

    Rectangle {
       id: splashRect
       anchors.fill: parent
       color: "white"
       border.width: 1
       border.color: "black"
  
       Text {
           id: initializationErrorMessage
           text: "This is the splash screen"
           anchors.horizontalCenter: parent.horizontalCenter
           anchors.top: parent.top
           anchors.topMargin: 50
           font.bold: true
           font.pixelSize: 20
           color: "black"
       }

       BusyIndicator {
           id: busyAnimation
           anchors.horizontalCenter: parent.horizontalCenter
           anchors.bottom: parent.bottom
           anchors.bottomMargin: parent.height / 5
           width: parent.width / 2
           height: width
           running: true
       }
    }

    Component.onCompleted: visible = true
}

Here the code of main window. Please note the red part is only a bad trick to make a short delay before window is ready just for simulate an heavy loading:

import QtQml 2.2
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

ApplicationWindow {
    id: mainWindow
    flags: Qt.Window | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint
    width: 300
    height: 400
    visible: false
    title: "Scresh Screen Test"

    Component.onCompleted: {
        var timeout = new Date().valueOf() + 3000;
        while(timeout > new Date().valueOf()) {}
    }

    Text {
        text: "Window ready!"
        anchors.centerIn: parent
        font.bold: true
        font.pixelSize: 20
        color: "black"
    }
}

Please note since the main window is loaded in a background thread the loading priority is lower than main thread. This mean the loading will take more time compared to directly load the main window from main thread. Currently is the best solution I found to have an animated splash screen without animation lags but if you have suggestion to improve this procedure or also a different, better solution each suggestion is welcomed. ^_^

Comments

Post a Comment

Popular posts from this blog

Access GPIO from Linux user space

Launch an app from Android shell terminal