Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

It feels like this question has been asked about a hundred times before (e.g. here) but I haven't found a working solution yet..

I have a Qt5 program (Linux) which takes some time (about 2sec) for initialization. I don't want to spawn a thread (for several reasons) and before initialization is done the program is not usable anyway.

Currently the program starts and it shows a black window, until initialization is done.

I'd like to have the window content be drawn as soon as possible and queue a method which does the rest which gets executed right after the main window has been drawn.

This is what I tried:

class my_window : public QMainWindow {
    Q_OBJECT
    explicit my_window(QWidget *parent = 0) : QMainWindow(parent) {

        initializeUI();

        /// UI is ready and should be drawn. initializeRest() should 
        /// be queued 

        /// tried to repaint() or update() the MainWindow and to 'force'
        /// processing outstanding events - with no effect
        update();
        repaint();
        QApplication::processEvents();

        /// don't call - just queue 
        QMetaObject::invokeMethod(this, "initializeRest", Qt::QueuedConnection);
    }

    void initializeRest() {
        // do stuff which takes a while
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

But the main window stayes black until initializeRest() has been executed.

How can I tell Qt to execute initializeRest() right after the window has been constructed?

I can think of starting a timer (bad, introduces extra latency) or an event handler which reacts on some kind of "WindowDrawn" event (bad, complicated).

What's the Qt-way to do this?

Update:

I've also tried to put the initializeRest() method into the main() function like suggested by Murphy:

my_window::my_window(QWidget *parent = 0) : QMainWindow(parent) {
    initializeUI();
}

int main(int a_argsc, char *a_argsv[]) {
    QApplication l_application(a_argsc, a_argsv);
    my_window mainWindow;
    mainWindow.show();
    QApplication::processEvents();
    mainWindow.initializeRest();
    return l_application.exec();
}

With same results: Waiting for a couple of seconds inside initializeRest() makes show up the initially black main window and be drawn right after initializeRest() returned (which seems to be logical to me because the event loop has not been started yet..)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
168 views
Welcome To Ask or Share your Answers For Others

1 Answer

Note: This suggestion doesn't solve the issue; it's left here for completeness.

You can split the startup into smaller steps in main():

  1. Create the QApplication instance.
  2. Instantiate the main window (I'll call the variable mainWindow here). You can safely remove all that repaint-workaround stuff after initializeUI(); from the constructor of your code example.
  3. Call mainWindow.show() to enforce showing the main window, followed by a call to QApplication::processEvents() to enforce the paint events being handled.
  4. Do all the other initialization stuff of your application.
  5. Start the event loop as usual by calling QApplication::exec().

Be aware that with complex applications/main window implementations it can get quite hairy to do everything in the right order; a QSplashScreen would surely be the less tedious solution.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...