2013-04-08 217 views
3

是否有一個信號告訴'show'功能何時結束?QMainWindow - 等到'show'功能完成

我在我的代碼中的問題:如果我寫:

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

代碼不起作用。但是,如果我寫:

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

它的確如此。

所以我認爲問題是'show'dosn't在我調用'someGuiFunc'之前完成它的jub。這就是爲什麼我想有一個'顯示'完成的跡象..

+1

它我知道你在這裏做什麼很重要。你最終的目標是什麼?什麼是''someGuiFunc()''做的? – 2013-04-08 18:52:32

+0

我同意@JanKundrát,爲什麼'someGuiFunc()'依賴'QMainWinObj'是可見的?即使它確實依賴於它被繪製,「someGuiFunc()」只需要等到事件隊列被刷新(有幾個簡單的方法可以做到這一點),但如果是這種情況,第二個例子仍然不會因爲「睡眠」停止當前線程。 – cmannett85 2013-04-08 19:30:33

回答

4

這可能有點過時,但因爲沒有人回答了這個問題,除了一個: 由於沒有「顯示」信號,我建議重寫這樣的演出活動:

在你mainwindow.cpp文件:

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

在你mainwindow.h文件,介於主窗口的聲明:

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

    ... 
} 
... 

然後,當你去到設計中,右鍵單擊日e主窗口(對象樹頂部),然後選擇「更改信號/插槽」。在「信號」框中,單擊「+」按鈕,然後您需要添加「windowShown()」,然後按enter鍵,然後按OK按鈕(請注意,elipses「...」表示其他代碼已經在你的頭文件中)。

就是這樣 - 您現在可以使用信號/插槽編輯器將插槽連接到'windowShown'信號,只要您想要。現在,如果您想要更類似Microsoft的「已加載」事件(我認爲它在.NET中使用),則需要創建一些實例變量並將其標記,以便每次顯示窗口時都不會發射,例如:

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

同時,不要忘了在構造函數初始化變量爲「真」:

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

如果你決定把它的初始化列表但要確保它在正確的順序。如果變量未按照類頭中聲明的從上到下的方式實例化,編譯器會發出抱怨。

現在,請確保在標題中定義firstTimeShown時,將其設爲私人。並且不要忘記添加的信號:

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

    private: 
     bool firstTimeShown; 
    ... 

就是這樣。藉助信號和插槽的靈活性,您可以很容易地模仿您可能從Windows窗體或MFC中找到的任何事件。它只需要程序員的一點努力。一旦你掌握了它,它會像第二天性一樣。

注:有可能優化或更好,使得「裝載」,「中顯示」信號進行更精確的方式,但我已經離開了這樣的事情出來爲簡單起見。回到現在的問題,調用QApplication :: processEvents()很可能是你想要做的,而不是等待一段固定的時間,因爲誰知道如果用戶運行其他100個東西需要多長時間最重要的是,等等等等。希望這會有所幫助,包括額外的解釋,希望它能讓你有更好的方式去做你想做的事情,而不是等待某件事情做完,「知道」它已經完成是一個更好的選擇。

0

重寫bool event(QEvent *event)並捕獲Paint事件。至少在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; 
} 
1

問題可以決定沒有子,只是安裝事件過濾器是這樣的:

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