QMainWindow - wait until 'show' function is done

主宰稳场 提交于 2019-12-03 21:27:47

问题


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


回答1:


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.




回答2:


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.




回答3:


Problem can decide without subclassing, just installing event filter like this:

class CWidgetIsPainting_EF : public QObject
{
    bool m_bIsPainted = false;
public:
    CWidgetIsPainting_EF( QObject * parent = 0 ) : QObject (parent) { }

    inline bool IsPainted() const { return m_bIsPainted; }
    inline void setIsPainted( bool bIsPainted ) { m_bIsPainted = bIsPainted; }

protected:
    bool eventFilter( QObject * obj, QEvent *event )
    {
        if (event->type() == QEvent::Paint)
        {
            m_bIsPainted = true;
            return true;
        };
        return QObject::eventFilter(obj, event);
    }
};

... ...

CWidgetIsPainting_EF * pPaintingEF = new CWidgetIsPainting_EF( m_pWidget );
m_pWidget->installEventFilter( pPaintingEF );

... ...

while ( !pPaintingEF->IsPainted() )
    QApplication::processEvents();



回答4:


Override bool event(QEvent *event) and catch the Paint event. Works for me at least on Windows.

// MainWindow.h
class MainWindow : public QMainWindow
{
    ...
    bool event(QEvent *event) override;
    void functionAfterShown();
    ...
    bool functionAfterShownCalled = false;
    ...
}

// MainWindow.cpp
bool MainWindow::event(QEvent *event)
{
    const bool ret_val = QMainWindow::event(event);
    if(!functionAfterShownCalled && event->type() == QEvent::Paint)
    {
        functionAfterShown();
        functionAfterShownCalled = true;
    }
    return ret_val;
}


来源:https://stackoverflow.com/questions/15884199/qmainwindow-wait-until-show-function-is-done

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!