Qt QApplication 類簡介--Qt 類簡介專題(四)

一、詳細描述

QApplication類管理圖形用戶界面應用程序的控制流和主要設置。 可以說QApplication 是Qt的整個後臺管理的命脈

它包含主事件循環,在其中來自窗口系統和其它資源的所有事件被處理和調度。它也處理應用程序的初始化和結束,並且提供對話管理。它也處理絕大多數系統範圍和應用程序範圍的設置。

對於任何一個使用Qt的圖形用戶界面應用程序,都正好存在一個QApplication對象,而不論這個應用程序在同一時間內是不是有0、1、2或更多個窗口。

QApplication對象是可以通過全局變量qApp訪問。它的負責的主要範圍有:

* 它使用用戶的桌面設置,例如palette()、font()和doubleClickInterval()來初始化應用程序。如果用戶改變全局桌面,例如通過一些控制面板,它會對這些屬性保持跟蹤。

 

* 它執行事件處理,也就是說它從低下的窗口系統接收事件並且把它們分派給相關的窗口部件。通過使用sendEvent()和postEvent(),你可以發送你自己的事件到窗口部件。

* 它分析命令行參數並且根據它們設置內部狀態。關於這點的詳細情況請參考下面的構造函數文檔。

* 它定義了由QStyle對象封裝的應用程序的觀感。在運行狀態下,可以通過setStyle()來改變。

* 它指定了應用程序如何分配顏色。詳細情況請參考setColorSpec()。

* 它定義了默認文本編碼(請參考setDefaultCodec())並且提供了通過translate()用戶可見的本地化字符串。

* 它提供了一些像desktop()和clipboard()這樣的魔術般的對象。

* 它知道應用程序的窗口。你可以使用widgetAt()來詢問在一個確定點上存在哪個窗口部件,得到一個topLevelWidgets()(頂級窗口部件)的列表和通過closeAllWindows()來關閉所有窗口,等等。

* 它管理應用程序的鼠標光標處理,請參考setOverrideCursor()和setGlobalMouseTracking()。

* 在X窗口系統上,它提供刷新和同步通訊流的函數,請參考flushX()和syncX()。

* 它提供複雜的對話管理支持。這使得當用戶註銷時,它可以讓應用程序很好地結束,如果無法終止,撤消關閉進程並且甚至爲未來的對話保留整個應用程序的狀態。詳細情況請參考isSessionRestored()、sessionId()、commitData()和saveState()。

應用程序排演實例包含了一個QApplication通常用法的典型完整的main()。

因爲QApplication對象做了如此多的初始化,它必須在所有與用戶界面相關的其它類被創建之前被創建。

因爲它也處理命令行參數,在應用程序中對argv解釋和修改之前創建它通常是一個好主意。(注意,也對於X11,setMainWidget()可以根據-geometry選項來改變主窗口部件。爲了保持這個功能,你必須在setMainWidget()和它的任何重載之前設置你的默認。)

二、QApplication兩類構造的講解

QApplication::QApplication ( int & argc, char ** argv )

初始化窗口系統並且使用在argv中的argc個命令行參數構造一個應用程序對象。
全局指針qApp指向這個應用程序對象。應該只有一個應用程序對象被創建。
這個應用程序對象必須在任何繪製設備(包括窗口部件、像素映射、位圖等等)之前被構造。
注意argc和argv也可以被改變。Qt會移除它能夠識別的命令行參數。原來的argc和argv稍後可以通過qApp->argc()和qApp->argv()來訪問。argv()的文檔中包含如何處理命令行參數的詳細描述。
Qt調試選項(如果Qt被使用被定義的QT_NO_DEBUG標記進行編譯,這些選項就是不可用的):

* -nograb,告訴Qt永遠不要捕獲鼠標或者鍵盤。
* -dograb (只有在X11下),在調試器下運行可能導致和-nograb衝突,使用-dograb來覆蓋。
* -sync (只有在X11下),爲了調試切換爲同步模式。

更詳細的解釋請參考調試技術。

所有的Qt程序自動支持下面這些命令行選項:

* -style= style,設置應用程序圖形用戶界面風格。可能的值有motif、windows和platinum。如果你使用其它風格編譯Qt或者有作爲插件編譯了其它風格,那麼它們都可以被用作-style命令行選項。
* -style style,這個和上面的一樣。
* -session= session,從以前的對話中重新載入應用程序。
* -session session,這個和上面的一樣。

X11版本的Qt也支持傳統的X11命令行選項:

* -display display,設置X顯示(默認爲$DISPLAY)。
* -geometry geometry,設置主窗口部件的客戶端位置和大小。
* -fn或者-font font,定義應用程序的字體。這個字體必須使用X邏輯字體描述來北指定。
* -bg或者-background color,設置默認背景色和應用程序調色板(亮的和暗的陰影將被計算出來)。
* -fg或者-foreground color,設置默認前景色。
* -btn或者-button color,設置默認按鈕顏色。
* -name name,設置應用程序名稱。
* -title title,設置應用程序標題。
* -visual TrueColor,強制應用程序在8位顯示上使用真彩圖像。
* -ncols count,如果應用程序使用QApplication::ManyColor顏色規格,在8位顯示中限制顏色立方體重分配的顏色。如果count爲216,那麼一個6x6x6的顏色立方體將被使用(也就是說6級紅色,6級綠色和6級藍色),對於其它值,與2x3x1立方體成比例的立方體將被使用。
* -cmap,導致應用程序在8位顯示上安裝一個私有的顏色映射。

QApplication::QApplication ( int & argc, char ** argv, bool GUIenabled )

構造一個使用argvargc個命令行參數的應用程序對象。如果GUIenabled爲真,圖形用戶界面應用程序被構造,否則非圖形用戶界面(命令行)應用程序被創建。

對於沒有圖形用戶界面的程序,設置GUIenabled爲假可以在沒有窗口系統的情況下運行。

在X11下,如果GUIenabled爲真,窗口系統被初始化。如果GUIenabled爲假,應用程序不連接X服務器。在Windows和Macintosh,現在窗口系統總是被初始化,而不管GUIenabled的值。在Qt未來的版本這也許會改變。

對於線程配置(也就是說當Qt已經被作爲線程庫建立),應用程序全局互斥量在構造函數中將被鎖定並且當使用exec()進入事件循環中時解鎖。如果你不調用exec(),你必須明顯地對這個互斥量解鎖,否則你將會在應用程序退出時得到警告。

下面這個例子顯示如何創建在可能情況下使用圖形界面的應用程序。

  int main( int argcchar **argv )
  {
#ifdef Q_WS_X11
    bool useGUI = getenv( "DISPLAY" ) != 0;
#else
    bool useGUI = TRUE;
#endif
    QApplication app(argcargv, useGUI);

    if ( useGUI ) {
       //開始圖形用戶界面版本
       ...
    } else {
       //開始非圖形用戶界面版本
       ...
    }
    return app.exec();
  }

三、窗口管理

窗口管理方面,對於獨立的1個進程,qApplication 提供窗口管理的成員函數有(多進程的窗口管理,這裏暫不介紹):

QDesktopWidget * QApplication::desktop () [靜態]

返回桌面窗口部件(也調用根窗口)。

 

桌面窗口部件對於獲得屏幕大小很有用。在桌面上繪製也是可能的。我們建議不要假設可以在桌面上繪製,因爲它不能在所有的操作系統上工作。

    QDesktopWidget *= QApplication::desktop();
    int w = d->width();     // 返回桌面寬度
    int h = d->height();    // 返回桌面高度

QWidgetList * QApplication::allWidgets () [靜態]

返回應用程序中所有窗口部件的列表。

 

這個列表必須使用new來被創建並且必須被調用者刪除。

如果沒有窗口部件,這個列表爲空(QPtrList::isEmpty())。

注意一些窗口部件也許被隱藏。

更新所有窗口部件的實例:

    QWidgetList  *list = QApplication::allWidgets();
    QWidgetListIt it( *list );         // 遍歷窗口部件
    QWidget * w;
    while ( (w=it.current()) != 0 ) {  // 對於每一個窗口部件……
        ++it;
        w->update();
    }
    delete list;                      // 刪除這個列表,不是這個窗口部件

 

QWidgetList * QApplication::topLevelWidgets () [靜態]

返回應用程序中頂級窗口部件的列表。

 

這個列表是使用new創建的並且必須由調用者刪除。

如果沒有頂級窗口部件,這個列表是空的(QPtrList::isEmpty())。

注意一些頂級窗口部件也許被隱藏了,例如如果當前沒有工具提示被顯示的工具提示。

實例:

    // 顯示所有隱藏的頂級窗口部件。
    QWidgetList  *list = QApplication::topLevelWidgets();
    QWidgetListIt it( *list );  // 遍歷窗口部件
    QWidget * w;
    while ( (w=it.current()) != 0 ) {   // 對每一個頂級窗口部件
        ++it;
        if ( !w->isVisible() )
            w->show();
    }
    delete list;                // 刪除這個列表,而不是窗口部件

QWidget * QApplication::topLevelAt ( int x, int y ) [static]

返回最上層x,y點的widget, 可以用來定位最上層窗口

QWidget * QApplication::widgetAt ( int x, int y ) [static]

返回當前層x,y點的widget, 可以用來定位當前窗口,和topLevelAt不同的是 widgetAt是以global screen position 來判斷的,而topLevelAt是以顯示區域爲座標區域的。

void QApplication::closeAllWindows () [static slot]

關閉所有頂級窗口。

 

     exitAct = new QAction(tr("E&xit")this);
     exitAct->setShortcuts(QKeySequence::Quit);
     exitAct->setStatusTip(tr("Exit the application"));
     connect(exitAct, SIGNAL(triggered())qApp, SLOT(closeAllWindows()));

四、關於事件循環

qApplication 的事件循環,就是MainLoop的事件循環,當然它的原理和QEventLoop的原理是一樣的。

void QCoreApplication::processEvents ( QEventLoop::ProcessEventsFlags flags =QEventLoop::AllEvents ) [static]

Processes all pending events for the calling thread according to the specified flags until there are no more events to process.
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
In event you are running a local loop which calls this function continuously, without an event loop, the DeferredDelete events will not be processed. This can affect the behaviour of widgets, e.g. QToolTip, that rely on DeferredDelete events to function properly. An alternative would be to call sendPostedEvents() from within that local loop.
Calling this function processes events only for the calling thread.
大體意思就是預先調用處於隊列狀態的事件,直到全部處理完畢。這個函數大多用於系統繁忙時,導致一些事件被延後了(如繪製事件等),用此函數可保證全部事件處理完畢後在繼續執行。常見於show(),update()之後調用。
Note: 這個函數線程安全

五、事件的發送

關於事件的發送有兩種方式:

1、bool QApplication::sendEvent ( QObject * receiver, QEvent * event ) [靜態]

使用notify()函數直接發送事件event給接受者receiver。返回由事件處理器返回的值。

 

這個事件在它被髮送時,不能被刪除。通常的訪問方式是在棧中創建這個事件,例如:

QMouseEvent me( QEvent::MouseButtonPress, pos, 0, 0 );
QApplication::sendEvent( mainWindow, &me );

如果你在堆中創建這個事件,你就必須刪除它。

void QApplication::postEvent ( QObject * receiver, QEvent * event ) [靜態]

把事件event添加爲對象receiver的接收對象,把它添加到事件隊列中並且立即返回。

 

這個時間必須在堆中被分配,因爲遞送事件隊列將會得到事件的所有權並且一旦它被遞送就刪除它。

當控制返回主事件循環,存儲在隊列中的所有事件將被使用notify()函數發送。

基本上Qt大部分的地方都是用到sendEvent, 而少部分地方會用到postEvent, 研究線程安全的童鞋可以多看看這方面的資料

發佈了1 篇原創文章 · 獲贊 31 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章