Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Splash screen on embedded device



  • When starting my app, I have a splash screen displayed while the rest of the app loads. It should disappear when my app shows up.
    This is part of my main() function :
    @int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    #ifdef ON_TARGETBOARD
    // This will hide the cursor when app runs on target board
    a.setOverrideCursor( QCursor( Qt::BlankCursor ) );

    // this will show a splash screen while loading the rest of the app
    QPixmap pixmap ("/images/splash.bmp");
    QSplashScreen *splash = new QSplashScreen(pixmap);
    QFont font("FreeSans", 48, QFont::Bold);
    splash->setFont(font);
    splash->showNormal();
    splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
    

    #endif

    MyWindow w;
    w.show();
    

    #ifdef ON_TARGETBOARD
    splash->finish(&w);
    #endif

    return a.exec();
    

    }@

    I notice however that the splash screen disappears before the app screen is visible. Between the end of the splash screen and the beginning of the app screen, there's a small gap (maybe 1 sec) displaying a uniform screen (in my case a blue screen).
    How can I prevent/solve this ?
    I taught, the splash's finish function was intended to do a smooth transition from splash to app. Shouldn't it wait to stop till the app's window shows up...?

    Filip



  • in facts, the w.Show() method ends only when the window is closed if i remember.
    And splash->finish(&w) doesn't make the splash finish immediately, it just tell it that it will have to wait the complete "w" loading to hide.
    So use this code and you must be alright :

    @

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MyWindow * w = new MyWindow();

    #ifdef ON_TARGETBOARD
    // This will hide the cursor when app runs on target board
    a.setOverrideCursor( QCursor( Qt::BlankCursor ) );
    // this will show a splash screen while loading the rest of the app
    QPixmap pixmap ("/images/splash.bmp");
    QSplashScreen *splash = new QSplashScreen(pixmap);
    QFont font("FreeSans", 48, QFont::Bold);
    splash->setFont(font);
    splash->showNormal();
    splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
    splash->finish(w);
    #endif

    w->show();
    return a.exec();
    

    }
    @



  • I changed it like this :

    @int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    #ifdef ON_TARGETBOARD
    // This will hide the cursor when app runs on target board
    a.setOverrideCursor( QCursor( Qt::BlankCursor ) );
    // this will show a splash screen while loading the rest of the app
    QPixmap pixmap ("/images/splash.bmp");
    QSplashScreen *splash = new QSplashScreen(pixmap);
    QFont font("FreeSans", 48, QFont::Bold);
    splash->setFont(font);
    splash->showNormal();
    splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
    #endif

    MyWindow *w = new MyWindow();
    

    #ifdef ON_TARGETBOARD
    splash->finish(w);
    #endif

    w->show();
    return a.exec();
    

    }@

    I have to display my splash screen before I create MyWindow because most of the start-up delay occurs when creating the mainwindow (from within mainwindow, a lot of other things are initialised and started).
    But it still doesn't work like it should. The gap between the end of the splash screen and the start of the app screen is now even bigger (some seconds).



  • [quote author="TheBootroo" date="1307625177"]in facts, the w.Show() method ends only when the window is closed if i remember.
    [/quote]

    Thats method exec() on dialogs.

    show() always returns after the widget is made visible (or at least the request is queued up internally).



  • finish() seems to work on X11 only:

    @

    void QSplashScreen::finish(QWidget *mainWin)
    {
    if (mainWin) {
    #if defined(Q_WS_X11)
    extern void qt_x11_wait_for_window_manager(QWidget *mainWin);
    qt_x11_wait_for_window_manager(mainWin);
    #endif
    }
    close();
    }
    @

    On other window systems, the method does nothing and calls close() immediately.



  • What if you completey remove the QSplashScreen - do you still have a blue screen when showing the main window? Is it possible that the blue screen just means "no window shown" as the splash screen is already hidden and the windows isn't shown yet?

    What if you show a simple widget like a QLabel instead of MyWindow - do you still have a blue screen?

    Is there a special reason you use showNormal() instead of using show()?

    [quote author="filip" date="1307624698"]I taught, the splash's finish function was intended to do a smooth transition from splash to app. Shouldn't it wait to stop till the app's window shows up...?[/quote]

    Yes it should. However the "correct" order is splash->show(), w->show(), splash->finish(&w).

    [quote author="TheBootroo" date="1307625177"]in facts, the w.Show() method ends only when the window is closed if i remember.[/quote]

    No. It shows the widget and returns immediately.



  • I would have done this way :

    main.cpp
    @
    #include "MyWindow.h"
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MyWindow w;
    w.show();
    return a.exec();
    }
    @

    mywindow.h :
    @
    #ifndef MYWINDOW_H
    #define MYWINDOW_H
    #include <QApplication>
    #include <QMainWindow>
    #ifdef ON_TARGETBOARD
    #include <QSplashScreen>
    #include <QTimer>
    #endif
    namespace Ui { class MainWindow; }
    class MainWindow : public QMainWindow
    {
    Q_OBJECT
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    private:
    Ui::MainWindow *ui;
    #ifdef ON_TARGETBOARD
    QSplashScreen *splash;
    #endif
    };
    #endif // MYWINDOW_H
    @

    and finally mainwindow.cpp :
    @
    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent), ui(new Ui::MainWindow)
    {
    #ifdef ON_TARGETBOARD
    qApp->setOverrideCursor(QCursor(Qt::BlankCursor));
    splash = new QSplashScreen(this, QPixmap("/images/splash.bmp"));
    splash->setFont(QFont("FreeSans", 48, QFont::Bold));
    splash->showMessage(tr("Loading..."), Qt::AlignTop|Qt::AlignHCenter);
    splash->showFullScreen();
    #endif
    ui->setupUi(this);
    /****************************************/
    /
    PUT YOUR HEAVY AND SLOW INIT STUFF HERE
    /
    /******************************************/
    #ifdef ON_TARGETBOARD
    // Keep the splash on until the Window is entirely shown and drawn
    QTimer::singleShot(1500, splash, SLOT(close()));
    #endif
    }
    MainWindow::~MainWindow() { delete ui; }
    @

    The trick is not using finish() but directely kill the splash a short moment after window is shown.

    I have tested on my Work Computer (Win7) and my phone (Nokia N900)



  • You can put the timer in the main function. A timeout of 0 is ok, it only fires once the event loop runs and it is started with app.exec().



  • Tried the method with the timer and seems to work fine !
    Thanks !!



  • your welcome ;-)



  • [quote author="Volker" date="1307628728"]finish() seems to work on X11 only:
    On other window systems, the method does nothing and calls close() immediately.[/quote]

    This is something you cannot read in the documentation :-|



  • [quote author="Lukas Geyer" date="1307630918"][quote author="Volker" date="1307628728"]finish() seems to work on X11 only:
    On other window systems, the method does nothing and calls close() immediately.[/quote]

    This is something you cannot read in the documentation :-|[/quote]

    Indeed, unfortunately that's right.
    But being open source, one can always have a quick look in the source code - that's what I do regularly, if I wonder why something does not work.


Log in to reply