Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QMainWindow - wait until 'show' function is done

Tags:

qt

qmainwindow

Is there a signal that tells when 'show' function finishes?

I have a problem in my code: If I write:

QMainWinObj.show();
QMainWinObj.someGuiFunc();

the code doesn't work. But, if I write:

QMainWinObj.show();
sleep(3000);
QMainWinObj.someGuiFunc();

It does.

So I think the problem is that 'show' dosn't finish its jub before I call 'someGuiFunc'. That's why I want to have some kind of a sign that 'show' is finished..

like image 355
kakush Avatar asked Jan 14 '23 17:01

kakush


2 Answers

This may be a bit dated but since nobody else answered it except the one: Since there is no "Show" signal I suggest overriding the show event like this:

In your mainwindow.cpp file:

void MainWindow::show()
{
   QMainWindow::show();
   QApplication::processEvents();
   emit windowShown();
}

In your mainwindow.h file, somewhere in MainWindow's declaration:

...
class MainWindow: public QMainWindow
{
   ...
   signals:
       void windowShown();

   ...
}
...

Then, when you go to the designer, right click on the main window (very top of the object tree), and select "Change signals/slots". In the "Signals" frame, click the "+" button, and you will need to add "windowShown()" and then press enter, and then the OK button (note that the elipses "..." denote other code that is already in your header).

That's it -- you can now use the signals/slots editor to link slots up to the 'windowShown' signal whenever you want. Now if you want something more like Microsoft's "Loaded" event which I think is used in .NET you will need to create some instance variable and flag it so that every time the window is shown, it isnt emitted, for example:

void MainWindow::show()
{
   QMainWindow::show();
   QApplication::processEvents();
   emit windowShown();
   if (firstTimeShown == true)
   {
      emit windowLoaded();
      firstTimeShown = false;
   }
}

Also, don't forget to initialize the variable to 'true' in your constructor:

MainWindow::MainWindow(QObject* parent)
 ...
{
   firstTimeShown = true; // put this somewhere before ui->setupUi()
}

If you decide to put it in the initializer list however, make sure it is in proper order. The compiler will complain if the variables are not instantiated in a top-to-bottom fashion as declared in the class' header.

Now, make sure when you define firstTimeShown in your header, that you make it private. And lets not forget the added signals:

class MainWindow : public QMainWindow
{
    ...
    signals:
      void windowLoaded();
      void windowShown();

    private:
      bool firstTimeShown;
    ...

That's about it. With the flexibility of signals and slots, its pretty easy to mimic any event that you might find from windows forms or from MFC. It just takes a little effort on the programmer's part. Once you get the hang of it however it it'll be like second nature.

note: there probably are optimizations or better and more precise ways of making the "Loaded" and "Shown" signals perform but I have left things like this out for simplicity's sake. And to come back to the question at hand, calling QApplication::processEvents() is most likely what you want to do instead of waiting a fixed amount of time because who knows how long it will take if the user is running 100 other things on top of it, etc, etc. Hope that helped, the extra explanation was included hoping that it might give you a better way to do the things that you want to do instead of waiting for something to be done, 'knowing' it is done is a much better alternative.

like image 88
osirisgothra Avatar answered Jan 16 '23 07:01

osirisgothra


There is no such signal, but having QMainWindow subclassed you can override showEvent event.

void MainWindow::showEvent(QShowEvent *){
    //your code
}

More info here: http://qt-project.org/doc/qt-4.8/qwidget.html#showEvent

Be aware it's called every time your window is about to be displayed.

like image 36
Gricha Avatar answered Jan 16 '23 05:01

Gricha