新手必學(xué) Qt 類簡介之 Qt QApplication 類
一、詳細(xì)描述
QApplication 類管理圖形用戶界面應(yīng)用程序的控制流和主要設(shè)置。 可以說 QApplication 是Qt的整個(gè)后臺(tái)管理的命脈
它包含主事件循環(huán),在其中來自窗口系統(tǒng)和其它資源的所有事件被處理和調(diào)度。它也處理應(yīng)用程序的初始化和結(jié)束,并且提供對話管理。它也處理絕大多數(shù)系統(tǒng)范圍和應(yīng)用程序范圍的設(shè)置。
對于任何一個(gè)使用Qt的圖形用戶界面應(yīng)用程序,都正好存在一個(gè)QApplication對象,而不論這個(gè)應(yīng)用程序在同一時(shí)間內(nèi)是不是有0、1、2或更多個(gè)窗口。
QApplication 對象是可以通過全局變量qApp訪問。它的負(fù)責(zé)的主要范圍有:
它使用用戶的桌面設(shè)置,例如palette()、font()和doubleClickInterval()來初始化應(yīng)用程序。如果用戶改變?nèi)肿烂妫缤ㄟ^一些控制面板,它會(huì)對這些屬性保持跟蹤。
它執(zhí)行事件處理,也就是說它從低下的窗口系統(tǒng)接收事件并且把它們分派給相關(guān)的窗口部件。通過使用sendEvent()和postEvent(),你可以發(fā)送你自己的事件到窗口部件。
它分析命令行參數(shù)并且根據(jù)它們設(shè)置內(nèi)部狀態(tài)。關(guān)于這點(diǎn)的詳細(xì)情況請參考下面的構(gòu)造函數(shù)文檔。
它定義了由QStyle對象封裝的應(yīng)用程序的觀感。在運(yùn)行狀態(tài)下,可以通過setStyle()來改變。
它指定了應(yīng)用程序如何分配顏色。詳細(xì)情況請參考setColorSpec()。
它定義了默認(rèn)文本編碼(請參考setDefaultCodec())并且提供了通過translate()用戶可見的本地化字符串。
它提供了一些像desktop()和clipboard()這樣的魔術(shù)般的對象。
它知道應(yīng)用程序的窗口。你可以使用widgetAt()來詢問在一個(gè)確定點(diǎn)上存在哪個(gè)窗口部件,得到一個(gè)topLevelWidgets()(***窗口部件)的列表和通過closeAllWindows()來關(guān)閉所有窗口,等等。
它管理應(yīng)用程序的鼠標(biāo)光標(biāo)處理,請參考setOverrideCursor()和setGlobalMouseTracking()。
在X窗口系統(tǒng)上,它提供刷新和同步通訊流的函數(shù),請參考flushX()和syncX()。
它提供復(fù)雜的對話管理支持。這使得當(dāng)用戶注銷時(shí),它可以讓應(yīng)用程序很好地結(jié)束,如果無法終止,撤消關(guān)閉進(jìn)程并且甚至為未來的對話保留整個(gè)應(yīng)用程序的狀態(tài)。詳細(xì)情況請參考isSessionRestored()、sessionId()、commitData()和saveState()。
應(yīng)用程序排演實(shí)例包含了一個(gè)QApplication通常用法的典型完整的main()。
因?yàn)镼Application對象做了如此多的初始化,它必須在所有與用戶界面相關(guān)的其它類被創(chuàng)建之前被創(chuàng)建。
因?yàn)樗蔡幚砻钚袇?shù),在應(yīng)用程序中對argv解釋和修改之前創(chuàng)建它通常是一個(gè)好主意。(注意,也對于X11,setMainWidget()可以根據(jù)-geometry選項(xiàng)來改變主窗口部件。為了保持這個(gè)功能,你必須在setMainWidget()和它的任何重載之前設(shè)置你的默認(rèn)。)
#p#
二、QApplication兩類構(gòu)造的講解
QApplication::QApplication ( int & argc, char ** argv )
初始化窗口系統(tǒng)并且使用在argv中的argc個(gè)命令行參數(shù)構(gòu)造一個(gè)應(yīng)用程序?qū)ο蟆?/p>
全局指針qApp指向這個(gè)應(yīng)用程序?qū)ο?。?yīng)該只有一個(gè)應(yīng)用程序?qū)ο蟊粍?chuàng)建。
這個(gè)應(yīng)用程序?qū)ο蟊仨氃谌魏卫L制設(shè)備(包括窗口部件、像素映射、位圖等等)之前被構(gòu)造。
注意argc和argv也可以被改變。Qt會(huì)移除它能夠識(shí)別的命令行參數(shù)。原來的argc和argv稍后可以通過qApp->argc()和qApp->argv()來訪問。argv()的文檔中包含如何處理命令行參數(shù)的詳細(xì)描述。
Qt調(diào)試選項(xiàng)(如果Qt被使用被定義的QT_NO_DEBUG標(biāo)記進(jìn)行編譯,這些選項(xiàng)就是不可用的):
-nograb,告訴Qt永遠(yuǎn)不要捕獲鼠標(biāo)或者鍵盤。
-dograb (只有在X11下),在調(diào)試器下運(yùn)行可能導(dǎo)致和-nograb沖突,使用-dograb來覆蓋。
-sync (只有在X11下),為了調(diào)試切換為同步模式。
更詳細(xì)的解釋請參考調(diào)試技術(shù)。
#p#
所有的Qt程序自動(dòng)支持下面這些命令行選項(xiàng):
-style= style,設(shè)置應(yīng)用程序圖形用戶界面風(fēng)格??赡艿闹涤衜otif、windows和platinum。如果你使用其它風(fēng)格編譯Qt或者有作為插件編譯了其它風(fēng)格,那么它們都可以被用作-style命令行選項(xiàng)。
-style style,這個(gè)和上面的一樣。
-session= session,從以前的對話中重新載入應(yīng)用程序。
-session session,這個(gè)和上面的一樣。
X11版本的Qt也支持傳統(tǒng)的X11命令行選項(xiàng):
-display display,設(shè)置X顯示(默認(rèn)為$DISPLAY)。
-geometry geometry,設(shè)置主窗口部件的客戶端位置和大小。
-fn或者-font font,定義應(yīng)用程序的字體。這個(gè)字體必須使用X邏輯字體描述來北指定。
-bg或者-background color,設(shè)置默認(rèn)背景色和應(yīng)用程序調(diào)色板(亮的和暗的陰影將被計(jì)算出來)。
-fg或者-foreground color,設(shè)置默認(rèn)前景色。
-btn或者-button color,設(shè)置默認(rèn)按鈕顏色。
-name name,設(shè)置應(yīng)用程序名稱。
-title title,設(shè)置應(yīng)用程序標(biāo)題。
-visual TrueColor,強(qiáng)制應(yīng)用程序在8位顯示上使用真彩圖像。
-ncols count,如果應(yīng)用程序使用QApplication::ManyColor顏色規(guī)格,在8位顯示中限制顏色立方體重分配的顏色。如果count為216,那么一個(gè)6x6x6的顏色立方體將被使用(也就是說6級紅色,6級綠色和6級藍(lán)色),對于其它值,與2x3x1立方體成比例的立方體將被使用。
-cmap,導(dǎo)致應(yīng)用程序在8位顯示上安裝一個(gè)私有的顏色映射。
QApplication::QApplication ( int & argc, char ** argv, bool GUIenabled )
構(gòu)造一個(gè)使用argv中argc個(gè)命令行參數(shù)的應(yīng)用程序?qū)ο?。如果GUIenabled為真,圖形用戶界面應(yīng)用程序被構(gòu)造,否則非圖形用戶界面(命令行)應(yīng)用程序被創(chuàng)建。
對于沒有圖形用戶界面的程序,設(shè)置GUIenabled為假可以在沒有窗口系統(tǒng)的情況下運(yùn)行。
在X11下,如果GUIenabled為真,窗口系統(tǒng)被初始化。如果GUIenabled為假,應(yīng)用程序不連接X服務(wù)器。在Windows和Macintosh,現(xiàn)在窗口系統(tǒng)總是被初始化,而不管GUIenabled的值。在Qt未來的版本這也許會(huì)改變。
對于線程配置(也就是說當(dāng)Qt已經(jīng)被作為線程庫建立),應(yīng)用程序全局互斥量在構(gòu)造函數(shù)中將被鎖定并且當(dāng)使用exec()進(jìn)入事件循環(huán)中時(shí)解鎖。如果你不調(diào)用exec(),你必須明顯地對這個(gè)互斥量解鎖,否則你將會(huì)在應(yīng)用程序退出時(shí)得到警告。
下面這個(gè)例子顯示如何創(chuàng)建在可能情況下使用圖形界面的應(yīng)用程序。
- int main( int argc, char **argv )
- {
- #ifdef Q_WS_X11
- bool useGUI = getenv( "DISPLAY" ) != 0;
- #else
- bool useGUI = TRUE;
- #endif
- QApplication app(argc, argv, useGUI);
- if ( useGUI ) {
- //開始圖形用戶界面版本
- ...
- } else {
- //開始非圖形用戶界面版本
- ...
- }
- return app.exec();
- }
#p#
三、窗口管理
在窗口管理方面,對于獨(dú)立的1個(gè)進(jìn)程,qApplication 提供窗口管理的成員函數(shù)有(多進(jìn)程的窗口管理,這里暫不介紹):
- QDesktopWidget * QApplication::desktop () [靜態(tài)]
返回桌面窗口部件(也調(diào)用根窗口)。
桌面窗口部件對于獲得屏幕大小很有用。在桌面上繪制也是可能的。我們建議不要假設(shè)可以在桌面上繪制,因?yàn)樗荒茉谒械牟僮飨到y(tǒng)上工作。
- QDesktopWidget *d = QApplication::desktop();
- int w = d->width(); // 返回桌面寬度
- int h = d->height(); // 返回桌面高度
- QWidgetList * QApplication::allWidgets () [靜態(tài)]
返回應(yīng)用程序中所有窗口部件的列表。
這個(gè)列表必須使用new來被創(chuàng)建并且必須被調(diào)用者刪除。
如果沒有窗口部件,這個(gè)列表為空(QPtrList::isEmpty())。
注意一些窗口部件也許被隱藏。
更新所有窗口部件的實(shí)例:
- QWidgetList *list = QApplication::allWidgets();
- QWidgetListIt it( *list ); // 遍歷窗口部件
- QWidget * w;
- while ( (w=it.current()) != 0 ) { // 對于每一個(gè)窗口部件……
- ++it;
- w->update();
- }
- delete list; // 刪除這個(gè)列表,不是這個(gè)窗口部件
- QWidgetList * QApplication::topLevelWidgets () [靜態(tài)]
返回應(yīng)用程序中***窗口部件的列表。
這個(gè)列表是使用new創(chuàng)建的并且必須由調(diào)用者刪除。
如果沒有***窗口部件,這個(gè)列表是空的(QPtrList::isEmpty())。
注意一些***窗口部件也許被隱藏了,例如如果當(dāng)前沒有工具提示被顯示的工具提示。
實(shí)例:
- // 顯示所有隱藏的***窗口部件。
- QWidgetList *list = QApplication::topLevelWidgets();
- QWidgetListIt it( *list ); // 遍歷窗口部件
- QWidget * w;
- while ( (w=it.current()) != 0 ) { // 對每一個(gè)***窗口部件
- ++it;
- if ( !w->isVisible() )
- w->show();
- }
- delete list; // 刪除這個(gè)列表,而不是窗口部件
- QWidget * QApplication::topLevelAt ( int x, int y ) [static]
返回最上層x,y點(diǎn)的widget, 可以用來定位最上層窗口
返回當(dāng)前層x,y點(diǎn)的widget, 可以用來定位當(dāng)前窗口,和topLevelAt不同的是 widgetAt是以global
- QWidget * QApplication::widgetAt ( int x, int y ) [static]
screen position 來判斷的,而topLevelAt是以顯示區(qū)域?yàn)樽鴺?biāo)區(qū)域的。
- void QApplication::closeAllWindows () [static slot]
關(guān)閉所有***窗口。
- exitAct = new QAction(tr("E&xit"), this);
- exitAct->setShortcuts(QKeySequence::Quit);
- exitAct->setStatusTip(tr("Exit the application"));
- connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
#p#
四、關(guān)于事件循環(huán)
qApplication 的事件循環(huán),就是MainLoop的事件循環(huán),當(dāng)然它的原理和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.
大體意思就是預(yù)先調(diào)用處于隊(duì)列狀態(tài)的事件,直到全部處理完畢。這個(gè)函數(shù)大多用于系統(tǒng)繁忙時(shí),導(dǎo)致一些事件被延后了(如繪制事件等),用此函數(shù)可保證全部事件處理完畢后在繼續(xù)執(zhí)行。常見于show(),update()之后調(diào)用。
Note: 這個(gè)函數(shù)線程安全
五、事件的發(fā)送
關(guān)于事件的發(fā)送有兩種方式:
- bool QApplication::sendEvent ( QObject * receiver, QEvent * event ) [靜態(tài)]
使用notify()函數(shù)直接發(fā)送事件event給接受者receiver。返回由事件處理器返回的值。
這個(gè)事件在它被發(fā)送時(shí),不能被刪除。通常的訪問方式是在棧中創(chuàng)建這個(gè)事件,例如:
- QMouseEvent me( QEvent::MouseButtonPress, pos, 0, 0 );
- QApplication::sendEvent( mainWindow, &me );
如果你在堆中創(chuàng)建這個(gè)事件,你就必須刪除它。
- void QApplication::postEvent ( QObject * receiver, QEvent * event ) [靜態(tài)]
把事件event添加為對象receiver的接收對象,把它添加到事件隊(duì)列中并且立即返回。
這個(gè)時(shí)間必須在堆中被分配,因?yàn)檫f送事件隊(duì)列將會(huì)得到事件的所有權(quán)并且一旦它被遞送就刪除它。
當(dāng)控制返回主事件循環(huán),存儲(chǔ)在隊(duì)列中的所有事件將被使用notify()函數(shù)發(fā)送。
基本上Qt大部分的地方都是用到sendEvent, 而少部分地方會(huì)用到postEvent, 研究線程安全的童鞋可以多看看這方面的資料
小結(jié):QApplication 包含主事件循環(huán),在其中來自窗口系統(tǒng)和其它資源的所有事件被處理和調(diào)度。它也處理應(yīng)用程序的初始化和結(jié)束,并且提供對話管理。它也處理絕大多數(shù)系統(tǒng)范圍和應(yīng)用程序范圍的設(shè)置。對于任何一個(gè)使用Qt的圖形用戶界面應(yīng)用程序,都正好存在一個(gè) QApplication 對象,而不論這個(gè)應(yīng)用程序在同一時(shí)間內(nèi)是不是有0、1、2或更多個(gè)窗口。