June 9, 2011

filip filip
Lab Rat
65 posts

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 :

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.  
  5. #ifdef ON_TARGETBOARD
  6.     // This will hide the cursor when app runs on target board
  7.     a.setOverrideCursor( QCursor( Qt::BlankCursor ) );
  8.  
  9.     // this will show a splash screen while loading the rest of the app
  10.     QPixmap pixmap ("/images/splash.bmp");
  11.     QSplashScreen *splash = new QSplashScreen(pixmap);
  12.     QFont font("FreeSans", 48, QFont::Bold);
  13.     splash->setFont(font);
  14.     splash->showNormal();
  15.     splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
  16. #endif
  17.  
  18.     MyWindow w;
  19.     w.show();
  20.  
  21. #ifdef ON_TARGETBOARD
  22.     splash->finish(&w);
  23. #endif
  24.  
  25.     return a.exec();
  26. }

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

11 replies

June 9, 2011

TheBootroo TheBootroo
Lab Rat
9 posts

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 :

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     MyWindow * w = new MyWindow();
  5.  
  6. #ifdef ON_TARGETBOARD
  7.     // This will hide the cursor when app runs on target board
  8.     a.setOverrideCursor( QCursor( Qt::BlankCursor ) );
  9.     // this will show a splash screen while loading the rest of the app
  10.     QPixmap pixmap ("/images/splash.bmp");
  11.     QSplashScreen *splash = new QSplashScreen(pixmap);
  12.     QFont font("FreeSans", 48, QFont::Bold);
  13.     splash->setFont(font);
  14.     splash->showNormal();
  15.     splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
  16.     splash->finish(w);
  17. #endif
  18.  
  19.     w->show();
  20.     return a.exec();
  21. }

June 9, 2011

filip filip
Lab Rat
65 posts

I changed it like this :

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.  
  5. #ifdef ON_TARGETBOARD
  6.     // This will hide the cursor when app runs on target board
  7.     a.setOverrideCursor( QCursor( Qt::BlankCursor ) );
  8.     // this will show a splash screen while loading the rest of the app
  9.     QPixmap pixmap ("/images/splash.bmp");
  10.     QSplashScreen *splash = new QSplashScreen(pixmap);
  11.     QFont font("FreeSans", 48, QFont::Bold);
  12.     splash->setFont(font);
  13.     splash->showNormal();
  14.     splash->showMessage(QObject::tr("Loading..."), Qt::AlignTop | Qt::AlignHCenter);
  15. #endif
  16.  
  17.     MyWindow *w = new MyWindow();
  18.  
  19. #ifdef ON_TARGETBOARD
  20.     splash->finish(w);
  21. #endif
  22.  
  23.     w->show();
  24.     return a.exec();
  25. }

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).

June 9, 2011

Volker Volker
Ant Farmer
5428 posts
TheBootroo wrote:
in facts, the w.Show() method ends only when the window is closed if i remember.

Thats method exec() on dialogs.

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

June 9, 2011

Volker Volker
Ant Farmer
5428 posts

finish() seems to work on X11 only:

  1. void QSplashScreen::finish(QWidget *mainWin)
  2. {
  3.     if (mainWin) {
  4. #if defined(Q_WS_X11)
  5.         extern void qt_x11_wait_for_window_manager(QWidget *mainWin);
  6.         qt_x11_wait_for_window_manager(mainWin);
  7. #endif
  8.     }
  9.     close();
  10. }

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

June 9, 2011

Lukas Geyer Lukas Geyer
Lab Rat
2074 posts

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()?

filip wrote:
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…?

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

TheBootroo wrote:
in facts, the w.Show() method ends only when the window is closed if i remember.

No. It shows the widget and returns immediately.

June 9, 2011

TheBootroo TheBootroo
Lab Rat
9 posts

I would have done this way :

main.cpp

  1. #include "MyWindow.h"
  2. int main(int argc, char *argv[])
  3. {
  4.     QApplication a(argc, argv);
  5.     MyWindow w;
  6.     w.show();
  7.     return a.exec();
  8. }

mywindow.h :

  1. #ifndef MYWINDOW_H
  2. #define MYWINDOW_H
  3. #include <QApplication>
  4. #include <QMainWindow>
  5. #ifdef ON_TARGETBOARD
  6. #include <QSplashScreen>
  7. #include <QTimer>
  8. #endif
  9. namespace Ui { class MainWindow; }
  10. class MainWindow : public QMainWindow
  11. {
  12.     Q_OBJECT
  13. public:
  14.     explicit MainWindow(QWidget *parent = 0);
  15.     ~MainWindow();
  16. private:
  17.     Ui::MainWindow *ui;
  18. #ifdef ON_TARGETBOARD
  19.     QSplashScreen  *splash;
  20. #endif
  21. };
  22. #endif // MYWINDOW_H

and finally mainwindow.cpp :

  1. #include "MainWindow.h"
  2. #include "ui_MainWindow.h"
  3. MainWindow::MainWindow(QWidget * parent) :  QMainWindow(parent), ui(new Ui::MainWindow)
  4. {
  5. #ifdef ON_TARGETBOARD
  6.     qApp->setOverrideCursor(QCursor(Qt::BlankCursor));
  7.     splash = new QSplashScreen(this, QPixmap("/images/splash.bmp"));
  8.     splash->setFont(QFont("FreeSans", 48, QFont::Bold));
  9.     splash->showMessage(tr("Loading..."), Qt::AlignTop|Qt::AlignHCenter);
  10.     splash->showFullScreen();
  11. #endif
  12.     ui->setupUi(this);
  13.     /******************************************/
  14.     /* PUT YOUR HEAVY AND SLOW INIT STUFF HERE*/
  15.     /******************************************/
  16. #ifdef ON_TARGETBOARD
  17.     // Keep the splash on until the Window is entirely shown and drawn
  18.     QTimer::singleShot(1500, splash, SLOT(close()));
  19. #endif
  20. }
  21. 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)

June 9, 2011

Volker Volker
Ant Farmer
5428 posts

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().

June 9, 2011

filip filip
Lab Rat
65 posts

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

June 9, 2011

TheBootroo TheBootroo
Lab Rat
9 posts

your welcome ;-)

June 9, 2011

Lukas Geyer Lukas Geyer
Lab Rat
2074 posts
Volker wrote:
finish() seems to work on X11 only: On other window systems, the method does nothing and calls close() immediately.

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

June 9, 2011

Volker Volker
Ant Farmer
5428 posts
Lukas Geyer wrote:
Volker wrote:
finish() seems to work on X11 only: On other window systems, the method does nothing and calls close() immediately.

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

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.

 
  ‹‹ How to build native rss with project      Deleting Device Calender items through a client(application) ››

You must log in to post a reply. Not a member yet? Register here!