Search code examples
c++qtqpainterqmainwindow

unable to make an intro before showing anything in the window and after the window is polished


I am working on Unix 19.02 and Qt 5.13.0 .

I am trying to make an introduction for my application before anything is shown up in the window. So, what I thought is to make the QPainter change the background color in a while-loop. I tried it too many times and I had a problem in the timing : "When is the moment or the event that I should make the qpainter start the introduction?". I searched and found out the best thing is to reimplement this function :

void showEvent(QShowEvent* event) {...}  

inside that function, I call "repaint()", and it will do all the introduction. I tried all of these ways :

  1. Making the while-loop inside the "paintEvent" function.
  2. Making the while-loop outside the "paintEvent" function, and every time we change the color of the background I call "repaint()". Surely I made a small timeout for the computer to slow it down a bit. -Note: using these two ways above, the window shows up, but it's background-color is black and nothing shows up neither the color doesn't change until the introduction is finished!
  3. Lastely, a while-loop that does not use "QPainter", it uses stylesheet instead and after we change the "background-color" property. We call : ui->centeralWidget->style->polish(ui->centeralWidget);

The last way, forces the window not to show up until the introduction is finished completely (it takes 5 seconds to execute the introduction, the while-loop). this is the code :

QString ss; // for opacity
QString ss_prefix = "background-color: rgba(255, 255, 255, ";
QString ss_suffix = ");";
while(i<=50) {
    i++;
    Opacity += 5;
    qDebug() << "Changing opacity : " << ss_prefix+std::to_string(Opacity).c_str()+ss_suffix;
    ui->centralWidget->setStyleSheet(
                ss_prefix+std::to_string(Opacity).c_str()+ss_suffix);
    ui->centralWidget->style()->polish(ui->centralWidget);
    QThread::currentThread()->msleep(100); // 100 * 50 = 5000/1000 = 5 seconds to execute!
}

Nevertheless, there are other ways to make an introduction, but I really would want to know what is happening and fix this problem!

The last equation is meant to calculate the time to execute :

100(sleep) * 50(The code will get executed 50 times) = 5000 / 1000 (it is in milli, so divide by 1000) = 5 seconds Wish you understood my situation.


Solution

  • You're not providing complete code, so I am partially guessing here.

    You need to wait for the main app event loop to get started before starting your animation. If you call that animation routine (with the msleep() at the end) from the QMainWindow (or whatever your top-level QWidget is) constructor, the main window is never given a chance to show itself (until the animation is done).

    If I'm right, you could consider starting your animation from the first QWidget::showEvent() by using a bool flag to know when the first show happens. Another way would be to start a QTimer::singleShot(0, this, &MainWindow::animate) in the constructor (the timer will trigger once the main event loop starts). There are other ways, but the main point is that you need to let the QApplication event loop to be running and the window to have already been initialized.

    Having said all that, I'd probably take a different approach, maybe with a QSplashScreen or a custom QWidget to show the animation before, or while, loading the main window in the background.

    Also, look into QString template/replacement system, specifically the arg() methods and how they can be used to simplify string construction.