Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Splashscreen during initialization
Forum Updated to NodeBB v4.3 + New Features

Splashscreen during initialization

Scheduled Pinned Locked Moved QML and Qt Quick
6 Posts 2 Posters 6.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JF002
    wrote on 3 Jan 2014, 16:38 last edited by
    #1

    Hi,

    I'm working on an application which has a quite long initialization procedure (connect to a server, get data from the server, load QML files, images,...).

    I would like to display another QML file (a splashscreen) during the initialization of the application.

    I tried this:
    *

    • Create an QGuiApplication and a QQuickView objects
    • call SetSource() on QQuickView to load the splashscreen QML file and then show()
    • start a QThread that will run the init procedure
    • call the method exec() of the QGuiApplication object.
    • when the thread is finished, call SetSource() on the QQuickView again to make it load the final QML file.

    By doing this, I expect that the application is running, and that the splashscreen is displayed during the execution of the thread but... It's not the case.

    For testing, the initialization thread only call msleep() so, it does nothing

    During the execution of the thread, a blank window is opened, it doesn't display the splashscreen (ConnectingDialog.qml).
    It's only when the thread exits that the windows is updated with the content of the main QML file.

    ConnectingDialog.qml is a simple module that displays a black rectangle with some text

    Here is my code:
    Some declarations:
    @
    QGuiApplication* app;
    QThread* startThread;
    QQuickView* viewer;
    @

    The Start() function of the application
    @
    int MyApp::Start()
    {
    QDir directory(QCoreApplication::applicationDirPath());
    QString path = directory.absoluteFilePath("qml/ConnectingDialog.qml");

    viewer->setSource(QUrl::fromLocalFile(path));
    viewer->show();
    
    this->connect(this->startThread, SIGNAL(started()), SLOT(RunStartSequence()));
    this->connect(this, SIGNAL(finished()), SLOT(OnStartSequenceFinished()));
    this->startThread->start();
    return 0;
    

    }
    @

    The function called by the startThread:
    @
    void MyApp::RunStartSequence()
    {
    this->startThread->msleep(5000);
    emit finished();
    }
    @

    And the slot OnStartSequenceFinished():
    @
    void MyApp::OnStartSequenceFinished()
    {
    QDir directory(QCoreApplication::applicationDirPath());
    QString path = directory.absoluteFilePath("qml/main.qml");

    viewer->setSource(QUrl::fromLocalFile(path));
    

    }
    @

    main()
    @
    QGuiApplication app(argc, argv);
    MyApp myApp;

    myApp.Start();
    return app.exec();
    

    @

    I don't understand why my splashscreen is not displayed during the execution of the init thread.
    Can you help me?

    Thanks in advance!

    1 Reply Last reply
    0
    • J Offline
      J Offline
      JF002
      wrote on 3 Jan 2014, 20:35 last edited by
      #2

      Ok, I think I've found why it's not working as expected.

      With the code from my previous post, RunStartSequence() is executed into the same Thread as the function Start(). That's why the display is not updated during the execution of RunStartSequence().

      It seems that threads in QT do not work as I expected them to work. I'll have to read the documentation more carefully.
      I manage to make it work by using examples from "here.":http://qt-project.org/doc/qt-5.0/qtcore/qthread.html

      So, the example with msleep() is working, but I got into other issues: in my init function, I use object which were created in other threads,... And I get a lot of error messages.

      I think I'll implement my splashscreen in another way ("example":http://developer.nokia.com/Community/Wiki/Splash_screen_while_loading_main_qml )

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JF002
        wrote on 3 Jan 2014, 21:10 last edited by
        #3

        Mhm... I can't find a solution for my issue...
        At first, it seemed easy but... it's not.

        So, how would you do this in QT5/QML?

        • Just after the application starts, display the content of a QML file ("Please wait while connecting to the server...", for example).
        • When the message is displayed, do all the initialization stuffs that take a long time (connect to a server, get data from the server, create objects that will be used by the QML application,...). The init is done in C++.
        • When everything is ready, load another QML file that will use objects that were created during init.

        Thanks for your help!

        1 Reply Last reply
        0
        • J Offline
          J Offline
          JF002
          wrote on 4 Jan 2014, 15:29 last edited by
          #4

          After a good night of sleep... I still cannot find a solution :/

          I found this "example":http://developer.nokia.com/Community/Wiki/Implementing_a_Splash_Screen_with_Qt_Quick but

          • It's a QT4 example, and some objects/methods do not exist anymore in Qt5
          • I don't understand how this could work, as the UI is updated only when calling app.exec().
          • In this example, where is app.exec() called?

          My main problem : I need to display something on the UI, do a lot of processing and update the UI. I cannot call app.exec() before my processing, because it's a blocking function. BUT the UI is only updated once I call app.exec... It's the chiken and the egg...

          Any help?

          1 Reply Last reply
          0
          • G Offline
            G Offline
            Gianluca
            wrote on 5 Jan 2014, 10:12 last edited by
            #5

            I solved your issues completely in QML without anything else.
            That's my solution:

            create a splash.qml file that will be called as the main.qml with the following structure:

            @
            Item {
            // this is the item displaying your splash image
            Item {
            Image {
            ….
            }
            // for animation the stuff you have to use the Animators !!
            SequentialAnimation {
            loops: Animation.Infinite
            running: true
            RotationAnimator {
            …
            }
            }
            } // here close the item displaying the splash screen

            // this is the Loader that's load the your main.qml file
               Loader {
                        id: main
                        anchors.fill: parent
                        asynchronous: true
                        visible: status == Loader.Ready
                }
            
              // this is a fake delay needed to give to QML the necessary time
             // to load and setup the splash item above
               PauseAnimation {
                        id: fakeLoadingDelay
                        duration: 50
                        onRunningChanged: {
                                if ( !running ) {
                                        main.source = "main.qml"
                                }
                        }
                }
            
            // this start the animation and loading of mail.qml when the component is ready
            Component.onCompleted: fakeLoadingDelay.start()
            

            }
            @

            The rationale is the following:

            • the Loader is asynchronous and the source is null
            • so, when the splash is loaded the only thing that are created and started are the first Item with your splash image and the animator (this has to be a very fast item to load)
            • after completed on the onCompleted a PauseAnimation is started; this because when the onCompleted is executed there is nothing on the screen yet, you need to wait some milliseconds to allow Qt to draw stuff (50ms is enough)
            • after this pause, the source of the Loader is stetted to "mail.qml" that do the heavy loading stuff
            • the result is that the first Item with the Animator will be appear very fast (less than 1 sec) and it will display an animation until your "main.qml" has finished to load itself and will stop the animation.
            1 Reply Last reply
            0
            • J Offline
              J Offline
              JF002
              wrote on 5 Jan 2014, 16:51 last edited by
              #6

              Gianluca, thanks a lot for your example and explanations! That's exactly what I needed!
              Your example is working well for my use case. I just added one think: I call the Init() function from my C++ objet juste before "main.source = "main.qml" " so that all the C++ initialization is done before the file is loaded.

              Thanks a lot for your help!

              1 Reply Last reply
              0

              1/6

              3 Jan 2014, 16:38

              • Login

              • Login or register to search.
              1 out of 6
              • First post
                1/6
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved