• 正文
    • 12.2  Qt/Embedded開發(fā)入門
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Qt圖形編程基礎(chǔ)之:Qt/Embedded開發(fā)入門

2013/09/13
1
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

?

12.2??Qt/Embedded開發(fā)入門

12.2.1??Qt/Embedded介紹

1.架構(gòu)

Qt/Embedded以原始Qt為基礎(chǔ),并做了許多出色的調(diào)整以適用于嵌入式環(huán)境。Qt/Embedded通過Qt?APILinux?I/O設(shè)施直接交互,成為嵌入式Linux端口。同Qt/X11相比,Qt/Embedded很省內(nèi)存,因?yàn)樗恍枰粋€(gè)X服務(wù)器或是Xlib庫(kù),它在底層拋棄了X?lib,采用framebuffer(幀緩沖)作為底層圖形接口。同時(shí),將外部輸入設(shè)備抽象為keyboard和mouse輸入事件。Qt/Embedde的應(yīng)用程序可以直接寫內(nèi)核緩沖幀,這避免開發(fā)者使用繁瑣的Xlib/Server系統(tǒng)。圖12.1所示比較了Qt/Embedded與Qt/X11的架構(gòu)區(qū)別。

使用單一的API進(jìn)行跨平臺(tái)的編程可以有很多好處。提供嵌入式設(shè)備和桌面計(jì)算機(jī)環(huán)境下應(yīng)用的公司可以培訓(xùn)開發(fā)人員使用同一套工具開發(fā)包,這有利于開發(fā)人員之間共享開發(fā)經(jīng)驗(yàn)與知識(shí),也使得管理人員在分配開發(fā)人員到項(xiàng)目中的時(shí)候增加靈活性。更進(jìn)一步來說,針對(duì)某個(gè)平臺(tái)而開發(fā)的應(yīng)用和組件也可以銷售到Qt支持的其他平臺(tái)上,從而以低廉的成本擴(kuò)大產(chǎn)品的市場(chǎng)。

(1)窗口系統(tǒng)。

一個(gè)Qt/Embedded窗口系統(tǒng)包含了一個(gè)或多個(gè)進(jìn)程,其中的一個(gè)進(jìn)程可作為服務(wù)器。該服務(wù)進(jìn)程會(huì)分配客戶顯示區(qū)域,以及產(chǎn)生鼠標(biāo)和鍵盤事件。該服務(wù)進(jìn)程還能夠提供輸入方法和一個(gè)用戶接口給運(yùn)行起來的客戶應(yīng)用程序。該服務(wù)進(jìn)程其實(shí)就是一個(gè)有某些額外權(quán)限的客戶進(jìn)程。任何程序都可以在命令行上加上“-qws”的選項(xiàng)來把它作為一個(gè)服務(wù)器運(yùn)行。

客戶與服務(wù)器之間的通信使用共享內(nèi)存的方法實(shí)現(xiàn),通信量應(yīng)該保持最小,例如客戶進(jìn)程直接訪問幀緩沖來完成全部的繪制操作,而不會(huì)通過服務(wù)器,客戶程序需要負(fù)責(zé)繪制它們自己的標(biāo)題欄和其他式樣。這就是Qt/Embedded庫(kù)內(nèi)部層次分明的處理過程。客戶可以使用QCOP通道交換消息。服務(wù)進(jìn)程簡(jiǎn)單的廣播QCOP消息給所有監(jiān)聽指定通道的應(yīng)用進(jìn)程,接著應(yīng)用進(jìn)程可以把一個(gè)插槽連接到一個(gè)負(fù)責(zé)接收的信號(hào)上,從而對(duì)消息做出響應(yīng)。消息的傳遞通常伴隨著二進(jìn)制數(shù)據(jù)的傳輸,這是通過一個(gè)QDataStream類的序列化過程來實(shí)現(xiàn)的,有關(guān)這個(gè)類的描述,請(qǐng)讀者參考相關(guān)資料。

QProcess類提供了另外一種異步的進(jìn)程間通信機(jī)制。它用于啟動(dòng)一個(gè)外部的程序并且通過寫一個(gè)標(biāo)準(zhǔn)的輸入和讀取外部程序的標(biāo)準(zhǔn)輸出和錯(cuò)誤碼來和它們通信。

(2)字體

Qt/Embedded支持4種不同的字體格式:True?Type字體(TTF),Postscript?Type1字體,位圖發(fā)布字體(BDF)和Qt的預(yù)呈現(xiàn)(Pre-rendered)字體(QPF)。Qt還可以通過增加Qfont-
Factory的子類來支持其他字體,也可以支持以插件方式出現(xiàn)的反別名字體。

每個(gè)TTF或者TYPE1類型的字體首次在圖形或者文本方式的環(huán)境下被使用時(shí),這些字體的字形都會(huì)以指定的大小被預(yù)先呈現(xiàn)出來,呈現(xiàn)的結(jié)果會(huì)被緩沖。根據(jù)給定的字體尺寸(例如10或12點(diǎn)陣)預(yù)先呈現(xiàn)TTF或者TYPE1類型的字體文件并把結(jié)果以QPF的格式保存起來,這樣可以節(jié)省內(nèi)存和CPU的處理時(shí)間。QPF文件包含了一些必要的字體,這些字體可以通過makeqpf工具取得,或者通過運(yùn)行程序時(shí)加上“-savefonts”選項(xiàng)獲取。如果應(yīng)用程序中使用到的字體都是QPF格式,那么Qt/Embedded將被重新配置,并排除對(duì)TTF和TYPE1類型的字體的編譯,這樣就可以減少Q(mào)t/Embedded的庫(kù)的大小和存儲(chǔ)字體的空間。例如一個(gè)10點(diǎn)陣大小的包含所有ASCII字符的QPF字體文件的大小為1300字節(jié),這個(gè)文件可以直接從物理存儲(chǔ)格式映射成為內(nèi)存存儲(chǔ)格式。

Qt/Embedded的字體通常包括Unicode字體的一部分子集,ASCII和Latin-1。一個(gè)完整的16點(diǎn)陣的Unicode字體的存儲(chǔ)空間通常超過1MB,我們應(yīng)盡可能存儲(chǔ)一個(gè)字體的子集,而不是存儲(chǔ)所有的字,例如在一個(gè)應(yīng)用中,僅僅需要以Cappuccino字體、粗體的方式顯示產(chǎn)品的名稱,但是卻有一個(gè)包含了全部字形的字體文件。

(3)輸入設(shè)備及輸入法。

Qt/Embedded?3.0支持幾種鼠標(biāo)協(xié)議:BusMouse、IntelliMouse,Microsoft和MouseMan.Qt/
Embedded還支持NECVr41XX和iPAQ的觸摸屏。通過從QWSMouseHandler或者Qcalibra-
tedMouseHandler派生子類,開發(fā)人員可以讓Qt/Embedded支持更多的客戶指示設(shè)備。

Qt/Embedded支持標(biāo)準(zhǔn)的101鍵盤和Vr41XX按鍵,通過子類化QWSKeyboardHandler可以讓Qt/Embedded支持更多的客戶鍵盤和其他的非指示設(shè)備。

對(duì)于非拉丁語(yǔ)系字符(例如阿拉伯、中文、希伯來和日語(yǔ))的輸入法,需要把它寫成過濾器的方式,并改變鍵盤的輸入。輸入法的作者應(yīng)該對(duì)全部的Qt?API的使用有完整的認(rèn)識(shí)。在一個(gè)無鍵盤的設(shè)備上,輸入法成了惟一的輸入字符的手段。Qtopia提供了4種輸入方法:筆跡識(shí)別器、圖形化的標(biāo)準(zhǔn)鍵盤、Unicode鍵盤和基于字典方式提取的鍵盤。

(4)屏幕加速

通過子類化QScreen和QgfxRaster可以實(shí)現(xiàn)硬件加速,從而為屏幕操作帶來好處。Troll-
tech提供了Mach64和Voodoo3視頻卡的硬件加速的驅(qū)動(dòng)例子,同時(shí)可以按照協(xié)議編寫其他的驅(qū)動(dòng)程序。

?

2.Qt的開發(fā)環(huán)境

Qt/Embedded的開發(fā)環(huán)境可以取代那些我們熟知的UNIX和Windows開發(fā)工具。它提供了幾個(gè)跨平臺(tái)的工具使得開發(fā)變得迅速和方便,尤其是它的圖形設(shè)計(jì)器。UNIX下的開發(fā)者可以在PC機(jī)或者工作站使用虛擬緩沖幀,從而可以模仿一個(gè)和嵌入式設(shè)備的顯示終端大小,像素相同的顯示環(huán)境。

嵌入式設(shè)備的應(yīng)用可以在安裝了一個(gè)跨平臺(tái)開發(fā)工具鏈的不同的平臺(tái)上編譯。最通常的做法是在一個(gè)UNIX系統(tǒng)上安裝跨平臺(tái)的帶有l(wèi)ibc庫(kù)的GNU?C++編譯器和二進(jìn)制工具。在開發(fā)的許多階段,一個(gè)可替代的做法是使用Qt的桌面版本,例如通過Qt/X11或是Qt/Windows來進(jìn)行開發(fā)。這樣開發(fā)人員就可以使用他們熟悉的開發(fā)環(huán)境,例如微軟公司的Visual?C++或者Borland?C++。在UNIX操作系統(tǒng)下,許多環(huán)境也是可用的,例如Kdevelop,它也支持交互式開發(fā)。

如果Qt/Embedded的應(yīng)用是在UNIX平臺(tái)下開發(fā)的話,那么它就可以在開發(fā)的機(jī)器上以一個(gè)獨(dú)立的控制臺(tái)或者虛擬緩沖幀的方式來運(yùn)行,對(duì)于后者來說,其實(shí)是有一個(gè)X11的應(yīng)用程序虛擬了一個(gè)緩沖幀。通過指定顯示設(shè)備的寬度、高度和顏色深度,虛擬出來的緩沖幀將和物理的顯示設(shè)備在每個(gè)像素上保持一致。這樣每次調(diào)試應(yīng)用時(shí)開發(fā)人員就不用總是刷新嵌入式設(shè)備的Flash存儲(chǔ)空間,從而加速了應(yīng)用的編譯、鏈接和運(yùn)行周期。運(yùn)行Qt的虛擬緩沖幀工具的方法是在Linux的圖形模式下運(yùn)行以下命令:

qvfb?(回車)

當(dāng)Qt嵌入式的應(yīng)用程序要把顯示結(jié)果輸出到虛擬緩沖幀時(shí),我們?cè)诿钚羞\(yùn)行這個(gè)程序,并在程序名后加上-qws的選項(xiàng)。例如:$>?hello–qws。

3.Qt的支撐工具

Qt包含了許多支持嵌入式系統(tǒng)開發(fā)的工具,有兩個(gè)最實(shí)用的工具是qmake和Qt?designer(圖形設(shè)計(jì)器)。

n qmake是一個(gè)為編譯Qt/Embedded庫(kù)和應(yīng)用而提供的Makefile生成器。它能夠根據(jù)一個(gè)工程文件(.pro)產(chǎn)生不同平臺(tái)下的Makefile文件。qmake支持跨平臺(tái)開發(fā)和影子生成,影子生成是指當(dāng)工程的源代碼共享給網(wǎng)絡(luò)上的多臺(tái)機(jī)器時(shí),每臺(tái)機(jī)器編譯鏈接這個(gè)工程的代碼將在不同的子路徑下完成,這樣就不會(huì)覆蓋別人的編譯鏈接生成的文件。qmake還易于在不同的配置之間切換。

n Qt圖形設(shè)計(jì)器可以使開發(fā)者可視化地設(shè)計(jì)對(duì)話框而不需編寫代碼。使用Qt圖形設(shè)計(jì)器的布局管理可以生成能平滑改變尺寸的對(duì)話框。

qmake和Qt圖形設(shè)計(jì)器是完全集成在一起的。

12.2.2??Qt/Embedded信號(hào)和插槽機(jī)制

1.機(jī)制概述

信號(hào)和插槽機(jī)制是Qt的核心機(jī)制,要精通Qt編程就必須對(duì)信號(hào)和插槽有所了解。信號(hào)和插槽是一種高級(jí)接口,應(yīng)用于對(duì)象之間的通信,它是Qt的核心特性,也是Qt區(qū)別于其他工具包的重要地方。信號(hào)和插槽是Qt自行定義的一種通信機(jī)制,它獨(dú)立于標(biāo)準(zhǔn)的C/C++語(yǔ)言,因此要正確地處理信號(hào)和插槽,必須借助一個(gè)稱為moc(Meta?Object?Compiler)的Qt工具,該工具是一個(gè)C++預(yù)處理程序,它為高層次的事件處理自動(dòng)生成所需要的附加代碼。

所謂圖形用戶接口的應(yīng)用就是要對(duì)用戶的動(dòng)作做出響應(yīng)。例如,當(dāng)用戶單擊了一個(gè)菜單項(xiàng)或是工具欄的按鈕時(shí),應(yīng)用程序會(huì)執(zhí)行某些代碼。大部分情況下,是希望不同類型的對(duì)象之間能夠進(jìn)行通信。程序員必須把事件和相關(guān)代碼聯(lián)系起來,這樣才能對(duì)事件做出響應(yīng)。以前的工具開發(fā)包使用的事件響應(yīng)機(jī)制是易崩潰的,不夠健壯的,同時(shí)也不是面向?qū)ο蟮摹?/p>

以前,當(dāng)使用回調(diào)函數(shù)機(jī)制把某段響應(yīng)代碼和一個(gè)按鈕的動(dòng)作相關(guān)聯(lián)時(shí),通常把那段響應(yīng)代碼寫成一個(gè)函數(shù),然后把這個(gè)函數(shù)的地址指針傳給按鈕,當(dāng)那個(gè)按鈕被單擊時(shí),這個(gè)函數(shù)就會(huì)被執(zhí)行。對(duì)于這種方式,以前的開發(fā)包不能夠確?;卣{(diào)函數(shù)被執(zhí)行時(shí)所傳遞進(jìn)來的函數(shù)參數(shù)就是正確的類型,因此容易造成進(jìn)程崩潰。另外一個(gè)問題是,回調(diào)這種方式緊緊地綁定了圖形用戶接口的功能元素,因而很難進(jìn)行獨(dú)立的開發(fā)。

信號(hào)與插槽機(jī)制是不同的。它是一種強(qiáng)有力的對(duì)象間通信機(jī)制,完全可以取代原始的回調(diào)和消息映射機(jī)制。在Qt中信號(hào)和插槽取代了上述這些凌亂的函數(shù)指針,使得用戶編寫這些通信程序更為簡(jiǎn)潔明了。信號(hào)和插槽能攜帶任意數(shù)量和任意類型的參數(shù),它們是類型完全安全的,因此不會(huì)像回調(diào)函數(shù)那樣產(chǎn)生core?dumps。

圖12.2??對(duì)象間信號(hào)與插槽的關(guān)系

所有從QObject或其子類(例如Qwidget)派生的類都能夠包含信號(hào)和插槽。當(dāng)對(duì)象改變狀態(tài)時(shí),信號(hào)就由該對(duì)象發(fā)射(emit)出去了,這就是對(duì)象所要做的全部工作,它不知道另一端是誰(shuí)在接收這個(gè)信號(hào)。這就是真正的信息封裝,它確保對(duì)象被當(dāng)作一個(gè)真正的軟件組件來使用。插槽用于接收信號(hào),但它們是普通的對(duì)象成員函數(shù)。一個(gè)插槽并不知道是否有任何信號(hào)與自己相連接。而且,對(duì)象并不了解具體的通信機(jī)制。

用戶可以將很多信號(hào)與單個(gè)插槽進(jìn)行連接,也可以將單個(gè)信號(hào)與很多插槽進(jìn)行連接,甚至將一個(gè)信號(hào)與另外一個(gè)信號(hào)相連接也是可能的,這時(shí)無論第一個(gè)信號(hào)什么時(shí)候發(fā)射,系統(tǒng)都將立刻發(fā)射第二個(gè)信號(hào)??傊?,信號(hào)與插槽構(gòu)造了一個(gè)強(qiáng)大的部件編程機(jī)制。

?

2.信號(hào)與插槽實(shí)現(xiàn)實(shí)例

(1)信號(hào)。

當(dāng)某個(gè)信號(hào)對(duì)其客戶或所有者內(nèi)部狀態(tài)發(fā)生改變時(shí),信號(hào)就被一個(gè)對(duì)象發(fā)射。只有定義了這個(gè)信號(hào)的類及其派生類才能夠發(fā)射這個(gè)信號(hào)。當(dāng)一個(gè)信號(hào)被發(fā)射時(shí),與其相關(guān)聯(lián)的插槽將被立刻執(zhí)行,就像一個(gè)正常的函數(shù)調(diào)用一樣。信號(hào)-插槽機(jī)制完全獨(dú)立于任何GUI事件循環(huán)。只有當(dāng)所有的槽返回以后發(fā)射函數(shù)(emit)才返回。如果存在多個(gè)槽與某個(gè)信號(hào)相關(guān)聯(lián),那么,當(dāng)這個(gè)信號(hào)被發(fā)射時(shí),這些槽將會(huì)一個(gè)接一個(gè)地執(zhí)行,但是它們執(zhí)行的順序?qū)?huì)是隨機(jī)的、不確定的,用戶不能人為地指定哪個(gè)先執(zhí)行、哪個(gè)后執(zhí)行。

Qt的signals關(guān)鍵字指出進(jìn)入了信號(hào)聲明區(qū),隨后即可聲明自己的信號(hào)。例如,下面定義了3個(gè)信號(hào):

signals:

void?mySignal();

void?mySignal(int?x);

void?mySignalParam(int?x,int?y);

在上面的定義中,signals是Qt的關(guān)鍵字,而非C/C++的。接下來的一行void?mySignal()定義了信號(hào)mySignal,這個(gè)信號(hào)沒有攜帶參數(shù);接下來的一行void?mySignal(int?x)定義了重名信號(hào)mySignal,但是它攜帶一個(gè)整形參數(shù),這有點(diǎn)類似于C++中的虛函數(shù)。從形式上講信號(hào)的聲明與普通的C++函數(shù)是一樣的,但是信號(hào)卻沒有函數(shù)體定義。另外,信號(hào)的返回類型都是void。信號(hào)由moc自動(dòng)產(chǎn)生,它們不應(yīng)該在.cpp文件中實(shí)現(xiàn)。

(2)插槽。

插槽是普通的C++成員函數(shù),可以被正常調(diào)用,它們惟一的特殊性就是很多信號(hào)可以與其相關(guān)聯(lián)。當(dāng)與其關(guān)聯(lián)的信號(hào)被發(fā)射時(shí),這個(gè)插槽就會(huì)被調(diào)用。插槽可以有參數(shù),但插槽的參數(shù)不能有缺省值。

插槽是普通的成員函數(shù),因此與其他的函數(shù)一樣,它們也有存取權(quán)限。插槽的存取權(quán)限決定了誰(shuí)能夠與其相關(guān)聯(lián)。同普通的C++成員函數(shù)一樣,插槽函數(shù)也分為3種類型,即public?slots、private?slots和protected?slots。

n public?slots:在這個(gè)區(qū)內(nèi)聲明的槽意味著任何對(duì)象都可將信號(hào)與之相連接。這對(duì)于組件編程非常有用,用戶可以創(chuàng)建彼此互不了解的對(duì)象,將它們的信號(hào)與槽進(jìn)行連接以便信息能夠正確地傳遞。

n protected?slots:在這個(gè)區(qū)內(nèi)聲明的槽意味著當(dāng)前類及其子類可以將信號(hào)與之相連接。這適用于那些槽,它們是類實(shí)現(xiàn)的一部分,但是其界面接口卻面向外部。

n private?slots:在這個(gè)區(qū)內(nèi)聲明的槽意味著只有類自己可以將信號(hào)與之相連接。這適用于聯(lián)系非常緊密的類。

插槽也能夠被聲明為虛函數(shù),這也是非常有用的。插槽的聲明也是在頭文件中進(jìn)行的。例如,下面聲明了3個(gè)插槽:

public?slots:

void?mySlot();

void?mySlot(int?x);

void?mySignalParam(int?x,int?y);

(3)信號(hào)與插槽關(guān)聯(lián)。

通過調(diào)用QObject對(duì)象的connect()函數(shù)可以將某個(gè)對(duì)象的信號(hào)與另外一個(gè)對(duì)象的插槽函數(shù)或信號(hào)相關(guān)聯(lián),當(dāng)發(fā)射者發(fā)射信號(hào)時(shí),接收者的槽函數(shù)或信號(hào)將被調(diào)用。

該函數(shù)的定義如下所示:

bool?QObject::connect?(const?QObject?*?sender,?const?char?*?signal,const?QObject?*?receiver,?const?char?*?member)?[static]

這個(gè)函數(shù)的作用就是將發(fā)射者sender對(duì)象中的信號(hào)signal與接收者receiver中的member插槽函數(shù)聯(lián)系起來。當(dāng)指定信號(hào)signal時(shí)必須使用Qt的宏SIGNAL(),當(dāng)指定插槽函數(shù)時(shí)必須使用宏SLOT()。如果發(fā)射者與接收者屬于同一個(gè)對(duì)象的話,那么在connect()調(diào)用中接收者參數(shù)可以省略。

n 信號(hào)與插槽相關(guān)聯(lián)。

下例定義了兩個(gè)對(duì)象:標(biāo)簽對(duì)象label和滾動(dòng)條對(duì)象scroll,并將valueChanged()信號(hào)與標(biāo)簽對(duì)象的setNum()插槽函數(shù)相關(guān)聯(lián),另外信號(hào)還攜帶了一個(gè)整型參數(shù),這樣標(biāo)簽總是顯示滾動(dòng)條所處位置的值。

QLabel?*label?=?new?QLabel;

QScrollBar?*scroll?=?new?QScrollBar;

QObject::connect(scroll,?SIGNAL(valueChanged(int)),label,?SLOT(setNum(int)));

n 信號(hào)與信號(hào)相關(guān)聯(lián)。

在下面的構(gòu)造函數(shù)中,MyWidget創(chuàng)建了一個(gè)私有的按鈕aButton,按鈕的單擊事件產(chǎn)生的信號(hào)clicked()與另外一個(gè)信號(hào)aSignal()進(jìn)行關(guān)聯(lián)。這樣,當(dāng)信號(hào)clicked()被發(fā)射時(shí),信號(hào)aSignal()也接著被發(fā)射。如下所示:

class?MyWidget?:?public?QWidget

{

public:

MyWidget();

...

signals:

void?aSignal();

...

private:

...

QPushButton?*aButton;

};

MyWidget::MyWidget()

{

????aButton?=?new?QPushButton(this);

????connect(aButton,?SIGNAL(clicked()),?SIGNAL(aSignal()));

}

(4)解除信號(hào)與插槽關(guān)聯(lián)。

當(dāng)信號(hào)與槽沒有必要繼續(xù)保持關(guān)聯(lián)時(shí),用戶可以使用disconnect()函數(shù)來斷開連接。其定義如下所示:

bool?QObject::disconnect?(const?QObject?*?sender,?const?char?*?signal,const?Object?*?receiver,?const?char?*?member)?[static]

這個(gè)函數(shù)斷開發(fā)射者中的信號(hào)與接收者中的槽函數(shù)之間的關(guān)聯(lián)。

有3種情況必須使用disconnect()函數(shù)。

n 斷開與某個(gè)對(duì)象相關(guān)聯(lián)的任何對(duì)象。

當(dāng)用戶在某個(gè)對(duì)象中定義了一個(gè)或者多個(gè)信號(hào),這些信號(hào)與另外若干個(gè)對(duì)象中的槽相關(guān)聯(lián),如果想要切斷這些關(guān)聯(lián)的話,就可以利用這個(gè)方法,非常簡(jiǎn)潔。如下所示:

disconnect(myObject,?0,?0,?0)

或者

myObject->disconnect()

n 斷開與某個(gè)特定信號(hào)的任何關(guān)聯(lián)。

這種情況是非常常見的,其典型用法如下所示:

disconnect(myObject,?SIGNAL(mySignal()),?0,?0)

或者

myObject->disconnect(SIGNAL(mySignal()))

n 斷開兩個(gè)對(duì)象之間的關(guān)聯(lián)。

這也是非常常用的情況,如下所示:

disconnect(myObject,?0,?myReceiver,?0)

或者

myObject->disconnect(myReceiver)

注意

在disconnect()函數(shù)中0可以用作一個(gè)通配符,分別表示任何信號(hào)、任何接收對(duì)象、接收對(duì)象中的任何槽函數(shù)。但是發(fā)射者sender不能為0,其他3個(gè)參數(shù)的值可以等于0。

?

12.2.3??搭建Qt/Embedded開發(fā)環(huán)境

一般來說,用Qt/Embedded開發(fā)的應(yīng)用程序最終會(huì)發(fā)布到安裝有嵌入式Linux操作系統(tǒng)的小型設(shè)備上,所以使用裝有Linux操作系統(tǒng)的PC機(jī)或者工作站來完成Qt/Embedded開發(fā)當(dāng)然是最理想的環(huán)境,此外Qt/Embedded也可以安裝在UNIX或Windows系統(tǒng)上。這里就以在Linux操作系統(tǒng)中安裝為例進(jìn)行介紹。

這里需要有3個(gè)軟件安裝包:tmake工具安裝包、Qt/Embedded安裝包和Qt的X11版的安裝包。

n tmake1.11或更高版本:生成Qt/Embedded應(yīng)用工程的Makefile文件。

n Qt/Embedded:Qt/Embedded安裝包。

n Qt?2.3.2?for?X11:Qt的X11版的安裝包,產(chǎn)生X11開發(fā)環(huán)境所需要的兩個(gè)工具。

注意

這些軟件安裝包都有許多不同的版本,由于版本的不同會(huì)導(dǎo)致這些軟件在使用時(shí)可能引起的沖突,為此必須依照一定的安裝原則,Qt/Embedded安裝包的版本必須比Qt?for?X11的安裝包的版本新,這是因?yàn)镼t?for?X11的安裝包中的兩個(gè)工具uic和designer產(chǎn)生的源文件會(huì)和Qt/Embedded的庫(kù)一起被編譯鏈接,因此要本著“向前兼容”的原則,Qt?for?X11?的版本應(yīng)比Qt/Embedded的版本舊。

1.安裝tmake

用戶使用普通的解壓縮即可,注意要將路徑添加到全局變量中去,如下所示:

tar?zxvf?tmake-1.11.tar.gz

export?TMAKEDIR=$PWD/tmake-1.11

export?TMAKEPATH=$TMAKEDIR/lib/qws/linux-x86-g++

export?PATH=$TMAKEDIR/bin:$PATH

2.安裝Qt/Embedded?2.3.7

這里使用常見的解壓命令及安裝命令即可,要注意這里的路徑與不同的系統(tǒng)有關(guān),讀者要根據(jù)實(shí)際情況進(jìn)行修改。另外,這里的configure命令帶有參數(shù)“-qconfig?–qvfb?–depths?4816,32”分別為指定Qt嵌入式開發(fā)包生成虛擬緩沖幀工具qvfb,并支持4、8、16、32?位的顯示顏色深度。另外讀者也可以在configure的參數(shù)中添加“-system”、“-jpeg”或“gif”命令,使Qt/Embedded平臺(tái)能支持jpeg、gif格式的圖形。

Qt/Embedded開發(fā)包有5種編譯范圍的選項(xiàng),使用這些選項(xiàng)可控制Qt生成的庫(kù)文件的大小。如命令make?sub-src指定按精簡(jiǎn)方式編譯開發(fā)包,也就是說有些Qt類未被編譯。其他編譯選項(xiàng)的具體用法可通過“./configure–help”命令查看。精簡(jiǎn)方式的安裝步驟如下所示:

tar?zxvf?qt-embedded-2.3.7.tar.gz

cd?qt-2.3.7

export?QTDIR=$PWD

export?QTEDIR=$QTDIR

export?PATH=$QTDIR/bin:$PATH

export?LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH

./configure?-qconfig?local-qvfb?-depths?4,8,16,32

make?sub-src

3.安裝Qt/X11?2.3.2

與上一步類似,用戶也可以在configure后添加一定的參數(shù),如“-no-opengl”或“-no-xfs”,可以鍵入命令“./configure?–help”來獲得一些幫助信息。

tar?xfz?qt-x11-2.3.2.tar.gz

cd?qt-2.3.2

export?QTDIR=$PWD

export?PATH=$QTDIR/bin:$PATH

export?LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH

./configure?-no-opengl

make

make?-C?tools/qvfb

mv?tools/qvfb/qvfb?bin

cp?bin/uic?$QTEDIR/bin

12.2.4??Qt/Embedded窗口部件

Qt提供了一整套的窗口部件。它們組合起來可用于創(chuàng)建用戶界面的可視元素。按鈕、菜單、滾動(dòng)條、消息框和應(yīng)用程序窗口都是窗口部件的實(shí)例。因?yàn)樗械拇翱诓考仁强丶质侨萜?,因此Qt的窗口部件不能任意地分為控件和容器。通過子類化已存在的Qt部件或少數(shù)時(shí)候必要的全新創(chuàng)建,自定義的窗口部件能很容易地創(chuàng)建出來。

窗口部件是QWidget或其子類的實(shí)例,用戶自定義的窗口通過子類化得到,如圖12.3所示。

圖12.3??源自QWidget的類層次結(jié)構(gòu)

一個(gè)窗口部件可包含任意數(shù)量的子部件。子部件在父部件的區(qū)域內(nèi)顯示。沒有父部件的部件是頂級(jí)部件(比如一個(gè)窗口),通常在桌面的任務(wù)欄上有它們的入口。Qt不在窗口部件上施加任何限制。任何部件都可以是頂級(jí)部件,任何部件都可以是其他部件的子部件。通過自動(dòng)或手動(dòng)(如果你喜歡)使用布局管理器可以設(shè)定子部件在父部件區(qū)域中的位置。如果父部件被停用、隱藏或刪除,則同樣的動(dòng)作會(huì)應(yīng)用于它的所有子部件。

1.Hello窗口實(shí)例

下面是一個(gè)顯示“Hello?Qt/Embedded!”的程序的完整代碼:

#include?<qapplication.h>

#include?<qlabel.h>

int?main(int?argc,?char?**argv)

{

?????QApplication?app(argc,?argv);

?????QLabel?*hello=new?QLabel?

("<font?color=blue>Hello""<i>Qt?Embedded!</i></font>",0);

?????app.setMainWidget(hello);

?????hello->show();

?????return?app.exec();

}

2.常見通用窗口組合

Qt中還有一些常見的通用窗口,它們使用了Windows風(fēng)格顯示,圖12.5、12.6、12.7、12.8分別描述了常見的一些通用窗口的組合使用。圖12.4是該Hello窗口的運(yùn)行效果圖:

????????????????

圖12.4 Hello窗口運(yùn)行效果圖    ???????? 圖12.5 使用QHBox排列一個(gè)標(biāo)簽和一個(gè)按鈕

???    ????????????     

圖12.6 使用了QButtonGroup的兩個(gè)單選框和兩個(gè)復(fù)選框????? 圖12.7 QGroupBox組合圖示

?

圖12.8使用了QGroupBox進(jìn)行排列的日期類QDateTimeEdit、一個(gè)行編輯框類QLine-
Edit、一個(gè)文本編輯類QTextEdit和一個(gè)組合框類QComboBox。

圖12.9是以QGrid排列的一個(gè)QDial、一個(gè)QProgressBar、一個(gè)QSpinBox、一個(gè)QScrollBar、一個(gè)QLCDNumber和一個(gè)QSlider。

圖12.10是以QGrid排列的一個(gè)QIconView、一個(gè)QListView、一個(gè)QListBox和一個(gè)QTable。

     

???圖12.8 QGrid組合圖示1    ???????圖12.9 QGrid組合圖示2 ???????圖12.10??鐘表部件圖示

?

3.自定義窗口

開發(fā)者可以通過子類化QWidget或它的一個(gè)子類創(chuàng)建他們自己的部件或?qū)υ捒?。為了舉例說明子類化,下面提供了數(shù)字鐘部件的完整代碼。

鐘表部件是一個(gè)能顯示當(dāng)前時(shí)間并自動(dòng)更新的LCD。一個(gè)冒號(hào)分隔符隨秒數(shù)的流逝而閃爍,如圖12.10所示。

Clock從QLCDNumber部件繼承了LCD功能。它有一個(gè)典型部件類所擁有的典型構(gòu)造函數(shù),帶有可選的parent和name參數(shù)(如果設(shè)置了name參數(shù),測(cè)試和調(diào)試會(huì)更容易)。系統(tǒng)有規(guī)律地調(diào)用從QObject繼承的timerEvent()函數(shù)。

它在clock.h中定義如下所示:

#include?<qlcdnumber.h>

class?Clock:public?QLCDNumber

{

public:

?????Clock(QWidget?*parent=0,const?char?*name=0);

protected:

?????void?timerEvent(QTimerEvent?*event);

private:

?????void?showTime();

?????bool?showingColon;

};

構(gòu)造函數(shù)showTime()是用當(dāng)前時(shí)間初始化鐘表,并且告訴系統(tǒng)每1000ms調(diào)用一次timerEvent()來刷新LCD的顯示。在showTime()中,通過調(diào)用QLCDNumber::display()來顯示當(dāng)前時(shí)間。每次調(diào)用showTime()來讓冒號(hào)閃爍時(shí),冒號(hào)就被空白代替。

clock.cpp的源碼如下所示:

#include?<qdatetime.h>

#include?"clock.h"

Clock::Clock(QWidget?*parent,const?char?*name)

:QLCDNumber(parent,name),showingColon(true)

{

?????showTime();

?????startTimer(1000);

}

void?Clock::timerEvent(QTimerEvent?*)

{

?????showTime();

}

void?Clock::showTime()

{

?????QString?timer=QTime::currentTime().toString().left(5);

?????if?(!showingColon)

?????{

?????time[2]='?';

?????}

?????display(time);

?????showingColon=!showingColon;

}

文件clock.h和clock.cpp完整地聲明并實(shí)現(xiàn)了Clock部件。

#include?<qapplication.h>

#include?"clock.h"

int?main(int?argc,char?**argv)

{

????QApplication?app(argc,argv);

????Clock?*clock=new?Clock;

????app.setMainWidget(clock);

????clock->show();

????return?app.exec();

}

?

12.2.5??Qt/Embedded圖形界面編程

Qt提供了所有可能的類和函數(shù)來創(chuàng)建GUI程序。Qt既可用來創(chuàng)建“主窗口”式的程序,即一個(gè)有菜單欄,工具欄和狀態(tài)欄作為環(huán)繞的中心區(qū)域;也可以用來創(chuàng)建“對(duì)話框”式的程序,使用按鈕和必要的選項(xiàng)卡來呈現(xiàn)選項(xiàng)與信息。Qt支持SDI(單文檔界面)和MDI(多文檔界面)。Qt還支持拖動(dòng)、放下和剪貼板。工具欄可以在工具欄區(qū)域內(nèi)移動(dòng),拖拽到其他區(qū)域或者作為工具托盤浮動(dòng)起來。這個(gè)功能是內(nèi)建的,不需要額外的代碼,但程序員在需要時(shí)可以約束工具欄的行為。

使用Qt可以大大簡(jiǎn)化編程。例如,如果一個(gè)菜單項(xiàng)、一個(gè)工具欄按鈕和一個(gè)快捷鍵都完成同樣的動(dòng)作,那么這個(gè)動(dòng)作只需要一份代碼。

Qt還提供消息框和一系列標(biāo)準(zhǔn)對(duì)話框,使得程序向用戶提問和讓用戶選擇文件、文件夾、字體以及顏色變得更加簡(jiǎn)單。為了呈現(xiàn)一個(gè)消息框或一個(gè)標(biāo)準(zhǔn)對(duì)話框,只需要用一個(gè)使用方便的Qt靜態(tài)函數(shù)的一行的語(yǔ)句。

1.主窗口類

QMainWindow類提供了一個(gè)典型應(yīng)用程序的主窗口框架。

一個(gè)主窗口包含了一組標(biāo)準(zhǔn)窗體的集合。主窗口的頂部包含一個(gè)菜單欄,它的下方放置著一個(gè)工具欄,工具欄可以移動(dòng)到其他的停靠區(qū)域。主窗口允許停靠的位置有頂部、左邊、右邊和底部。工具欄可以被拖放到一個(gè)停靠的位置,從而形成一個(gè)浮動(dòng)的工具面板。主窗口的下方,也就是在底部的??课恢孟路接幸粋€(gè)狀態(tài)欄。主窗口的中間區(qū)域可以包含其他的窗體。提示工具和“這是什么”幫助按鈕以旁述的方式闡述了用戶接口的使用方法。

對(duì)于小屏幕的設(shè)備,使用Qt圖形設(shè)計(jì)器定義的標(biāo)準(zhǔn)的QWidget模板比使用主窗口類更好一些。典型的模板包含有菜單欄、工具欄,可能沒有狀態(tài)欄(在必要的情況下,可以用任務(wù)欄,標(biāo)題欄來顯示狀態(tài))。

例如,一個(gè)文本編輯器可以把QTextEdit作為中心部件:

QTextEdit?*editor?=?new?QTextEdit(mainWindow);

mainWindow->setCentralWidget(editor);

2.菜單類

彈出式菜單QPopupMenu類以垂直列表的方式顯示菜單項(xiàng),它可以是單個(gè)的(例如上下文相關(guān)菜單),可以以菜單欄的方式出現(xiàn),或者是別的彈出式菜單的子菜單出現(xiàn)。

每個(gè)菜單項(xiàng)可以有一個(gè)圖標(biāo)、一個(gè)復(fù)選框和一個(gè)加速器(快捷鍵),菜單項(xiàng)通常對(duì)應(yīng)一個(gè)動(dòng)作(例如存盤),分隔器通常顯示成一條豎線,它用于把一組相關(guān)聯(lián)的動(dòng)作菜單分離成組。

下面是一個(gè)建立包含有New、Open和Exit菜單項(xiàng)的文件菜單的例子。

QPopupMenu?*fileMenu?=?new?QPopupMenu(this);

fileMenu->insertItem("&New",?this,?SLOT(newFile()),?CTRL+Key_N);

fileMenu->insertItem("&Open...",?this,?SLOT(open()),?CTRL+Key_O);

fileMenu->insertSeparator();

fileMenu->insertItem("&Exit",?qApp,?SLOT(quit()),?CTRL+Key_Q);

當(dāng)一個(gè)菜單項(xiàng)被選中,和它相關(guān)的插槽將被執(zhí)行。加速器(快捷鍵)很少在一個(gè)沒有鍵盤輸入的設(shè)備上使用,Qt/Embedded的典型配置并未包含對(duì)加速器的支持。上面出現(xiàn)的代碼“&New”意思是在桌面機(jī)器上以“New”的方式顯示出來,但是在嵌入式設(shè)備中,它只會(huì)顯示為“New”。

QMenuBar類實(shí)現(xiàn)了一個(gè)菜單欄,它會(huì)自動(dòng)地設(shè)置幾何尺寸并在它的父窗體的頂部顯示出來,如果父窗體的寬度不夠?qū)捯灾敛荒茱@示一個(gè)完整的菜單欄,那么菜單欄將會(huì)分為多行顯示出來。Qt內(nèi)置的布局管理能夠自動(dòng)調(diào)整菜單欄。

Qt的菜單系統(tǒng)是非常靈活的,菜單項(xiàng)可以被動(dòng)態(tài)使能、失效、添加或者刪除。通過子類化QCustomMenuItem,用戶可以建立客戶化外觀和功能的菜單項(xiàng)。

3.工具欄

工具欄可以被移動(dòng)到中心區(qū)域的頂部、底部、左邊或右邊。任何工具欄都可以拖拽到工具欄區(qū)域的外邊,作為獨(dú)立的浮動(dòng)工具托盤。

QToolButton類實(shí)現(xiàn)了具有一個(gè)圖標(biāo),一個(gè)3D框架和一個(gè)可選標(biāo)簽的工具欄。切換型工具欄按鈕具有可以打開或關(guān)閉某些特征的功能。其他的則會(huì)執(zhí)行一個(gè)命令??梢詾榛顒?dòng)、關(guān)閉、開啟等模式,打開或關(guān)閉等狀態(tài)提供不同的圖標(biāo)。如果只提供一個(gè)圖標(biāo),Qt能根據(jù)可視化線索自動(dòng)地辨別狀態(tài),例如將禁用的按鈕變灰,工具欄按鈕也能觸發(fā)彈出式菜單。

QToolButton通常在QToolBar內(nèi)并排出現(xiàn)。一個(gè)程序可含有任意數(shù)量的工具欄并且用戶可以自由地移動(dòng)它們。工具欄可以包括幾乎所有部件,例如QComboBox和QSpinBox。

?

4.旁述

現(xiàn)在的應(yīng)用主要使用旁述的方式去解釋用戶接口的用法。Qt提供了兩種旁述的方式,即“提示欄”和“這是什么”幫助按鈕。

n “提示欄”是小的,通常是黃色的矩形,當(dāng)光標(biāo)在窗體的某些位置游動(dòng)時(shí),它就會(huì)自動(dòng)地出現(xiàn)。它主要用于解釋工具欄按鈕,特別是那些缺少文字標(biāo)簽說明的工具欄按鈕的用途。下面就是如何設(shè)置一個(gè)“存盤”按鈕的提示代碼。

QToolTip::add(saveButton,"Save");

當(dāng)提示字符出現(xiàn)之后,還可以在狀態(tài)欄顯示更詳細(xì)的文字說明。

對(duì)于一些沒有鼠標(biāo)的設(shè)備(例如那些使用觸點(diǎn)輸入的設(shè)備),就不會(huì)出現(xiàn)鼠標(biāo)的光標(biāo)在窗體上進(jìn)行游動(dòng),這樣就不能激活提示欄。對(duì)于這些設(shè)備也許就需要使用“這是什么”幫助按鈕,或者使用一種狀態(tài)來表示輸入設(shè)備正在進(jìn)行游動(dòng),例如用按下或者握住的狀態(tài)來表示現(xiàn)在正在進(jìn)行游動(dòng)。

n “這是什么”幫助按鈕和提示欄有些相似,只不過前者是要用戶單擊它才會(huì)顯示旁述。在小屏幕設(shè)備上,要想單擊“這是什么”幫助按鈕,具體的方法是,在靠近應(yīng)用的X窗口的關(guān)閉按鈕“x”附近你會(huì)看到一個(gè)“?”符號(hào)的小按鈕,這個(gè)按鈕就是“這是什么”的幫助按鈕。一般來說,“這是什么”幫助按鈕按下后要顯示的提示信息應(yīng)該比提示欄要多一些。下面是設(shè)置一個(gè)存盤按鈕的“這是什么”文本提示信息的方法:

QWhatsThis::add(saveButton,?"Save?the?current?file.");

QToolTip和QWhatsThis類提供了可以通過重新實(shí)現(xiàn)來獲取更多特殊化行為的虛函數(shù),比如根據(jù)鼠標(biāo)在部件的位置來顯示不同的文本。

5.動(dòng)作

應(yīng)用程序通常提供幾種不同的方式來執(zhí)行特定的動(dòng)作。比如,許多應(yīng)用程序通過菜單(Flie->Save)、工具欄(像一個(gè)軟盤的按鈕)和快捷鍵(Ctrl+S)來提供“Save”動(dòng)作。QAction類封裝了“動(dòng)作”這個(gè)概念。它允許程序員在某個(gè)地方定義一個(gè)動(dòng)作。

下面的代碼實(shí)現(xiàn)了一個(gè)“Save”菜單項(xiàng)、一個(gè)“Save”工具欄按鈕和一個(gè)“Save”快捷鍵,并且均有旁述幫助:

QAction?*saveAct?=?new?QAction("Save",?saveIcon,?"&Save",CTRL+Key_S,?this);

connect(saveAct,SIGNAL(activated()),?this,?SLOT(save()));

saveAct->setWhatsThis("Saves?the?current?file.");

saveAct->addTo(fileMenu);

saveAct->addTo(toolbar);

為了避免重復(fù),使用QAction可保證菜單項(xiàng)的狀態(tài)與工具欄保持同步,而工具提示能在需要的時(shí)候顯示。禁用一個(gè)動(dòng)作會(huì)禁用相應(yīng)的菜單項(xiàng)和工具欄按鈕。類似地,當(dāng)用戶單擊切換型按鈕時(shí),相應(yīng)的菜單項(xiàng)會(huì)因此被選中或不選。

12.2.6??Qt/Embedded對(duì)話框設(shè)計(jì)

Qt/Embedded對(duì)話框的設(shè)計(jì)比較復(fù)雜,要使用布局管理自動(dòng)地設(shè)置窗體與別的窗體之間相對(duì)的尺寸和位置,這樣可以確保對(duì)話框能夠最好地利用屏幕上的可用空間,接著還要使用Qt圖形設(shè)計(jì)器可視化設(shè)計(jì)工具建立對(duì)話框。下面就詳細(xì)講解具體的步驟。

1.布局

Qt的布局管理用于組織管理一個(gè)父窗體區(qū)域內(nèi)的子窗體。它的特點(diǎn)是可以自動(dòng)設(shè)置子窗體的位置和大小,并可確定出一個(gè)頂級(jí)窗體的最小和缺省的尺寸,當(dāng)窗體的字體或內(nèi)容變化后,它可以重置一個(gè)窗體的布局。

使用布局管理,開發(fā)者可以編寫?yīng)毩⒂谄聊淮笮『头较蛑獾某绦颍瑥亩恍枰速M(fèi)代碼空間和重復(fù)編寫代碼。對(duì)于一些國(guó)際化的應(yīng)用程序,使用布局管理,可以確保按鈕和標(biāo)簽在不同的語(yǔ)言環(huán)境下有足夠的空間顯示文本,不會(huì)造成部分文字被剪掉。

布局管理提供部分用戶接口組件,例如輸入法和任務(wù)欄變得更容易。我們可以通過一個(gè)例子說明這一點(diǎn),當(dāng)Qtopia的用戶輸入文字時(shí),輸入法會(huì)占用一定的文字空間,應(yīng)用程序這時(shí)也會(huì)根據(jù)可用屏幕尺寸的變化調(diào)整自己。

Qtopia的布局管理示例如圖12.11所示。

?

(1)內(nèi)建布局管理器

Qt提供了3種用于布局管理的類:QHBoxLayout、QVBox-
Layout和QGridLayout。

n QHBoxLayout?布局管理把窗體按照水平方向從左至右排成一行。

n QVBoxLayout布局管理把窗體按照垂直方向從上至下排成一列。

n QGridLayout布局管理以網(wǎng)格的方式來排列窗體,一個(gè)窗體可以占據(jù)多個(gè)網(wǎng)格。

它們的示例如圖12.12所示。

在多數(shù)情況下,Qt的布局管理器為其管理的部件挑選一個(gè)最適合的尺寸以便窗口能夠平滑地縮放。如果其缺省值不合適,開發(fā)者可以使用以下機(jī)制微調(diào)布局:

n 設(shè)置一個(gè)最小尺寸、一個(gè)最大尺寸,或者為一些子部件設(shè)置固定的大小。

圖12.12??3種布局管理類示意圖

n 設(shè)置一些延伸項(xiàng)目或間隔項(xiàng)目,延伸或間隔項(xiàng)目會(huì)填充空余的布局空間。

n 改變子部件的尺寸策略。通過調(diào)用QWidget::setSizePolicy(),程序員可以仔細(xì)調(diào)整子部件的縮放行為。子部件可以設(shè)置為擴(kuò)展、收縮、保持原大小等狀態(tài)。

n 改變子部件的建議大小。QWidget::sizeHint()和QWidget::minimumSizeHint()會(huì)根據(jù)內(nèi)容返回部件的首選尺寸和最小首選尺寸。內(nèi)建部件提供了合適的重新實(shí)現(xiàn)。

n 設(shè)置延伸因子。延伸因子規(guī)定了子部件的相應(yīng)增量,比如,2/3的可用空間分配給部件A而1/3分配給B。

(2)布局嵌套。

布局可以嵌套任意層。圖12.13顯示了一個(gè)對(duì)話框的兩種大小。

?????

圖12.13??一個(gè)對(duì)話框的兩種大小

這個(gè)對(duì)話框使用了3種布局:一個(gè)QVBoxLayout組合了按鈕,一個(gè)QHBoxLayout組合了國(guó)家列表和那組按鈕,一個(gè)QVBoxLayout組合了“Select?a?country”標(biāo)簽和剩下的部件。一個(gè)延伸項(xiàng)目用來維護(hù)Cancel和Help按鈕間的距離。

下面的代碼創(chuàng)建了對(duì)話框部件和布局:

QVBoxLayout?*buttonBox?=?new?QVBoxLayout(6);

buttonBox->addWidget(new?QPushButton("OK",?this));

buttonBox->addWidget(new?QPushButton("Cancel",?this));

buttonBox->addStretch(1);

buttonBox->addWidget(new?QPushButton("Help",?this));

QListBox?*countryList?=?new?QListBox(this);

countryList->insertItem("Canada");

/*...*/

countryList->insertItem("United?States?of?America");

QHBoxLayout?*middleBox?=?new?QHBoxLayout(11);

middleBox->addWidget(countyList);

middleBox->addLayout(buttonBox);

QVBoxLayout?*topLevelBox?=?new?QVBoxLayout(this,6,11);

topLevelBox->addWidget(new?QLabel("Select?a?country",?this));

topLevelBox->addLayout(middleBox);

可以看到,Qt讓布局變得非常容易。

(3)自定義布局。

通過子類化QLayout,開發(fā)者可以定義自己的布局管理器。和Qt一起提供的customlayout樣例展示了3個(gè)自定義布局管理器:BorderLayout、CardLayout和SimpleFlow,程序員可以使用并修改它們。

Qt還包括QSplitter,是一個(gè)最終用戶可以操縱的分離器。某些情況下,QSplitter可能比布局管理器更為可取。

為了完全控制,重新實(shí)現(xiàn)每個(gè)子部件的QWidget::resizeEvent()并調(diào)用QWidget::setGeometry(),就可以在一個(gè)部件中手動(dòng)地實(shí)現(xiàn)布局。

2.Qt/Embedded圖形設(shè)計(jì)器

Qt圖形設(shè)計(jì)器是一個(gè)具有可視化用戶接口的設(shè)計(jì)工具。Qt的應(yīng)用程序可以完全用源代碼來編寫,或者使用Qt圖形設(shè)計(jì)器來加速開發(fā)工作。啟動(dòng)Qt圖形設(shè)計(jì)器的方法是:

cd?qt-2.3.2/bin

./designer

這樣就可以啟動(dòng)一個(gè)圖形化的設(shè)計(jì)界面,如圖12.14所示。

圖12.14??Qt圖形設(shè)計(jì)器界面

?

開發(fā)者單擊工具欄上的代表不同功能的子窗體/組件的按鈕,然后把它拖放到一個(gè)表單(Form)上,這樣就可以把一個(gè)子窗體/組件放到表單上了。開發(fā)者可以使用屬性對(duì)話框來設(shè)置子窗體的屬性,精確地設(shè)置子窗體的位置和尺寸大小是沒必要的。開發(fā)者可以選擇一組窗體,然后對(duì)它們進(jìn)行排列。例如,我們選定了一些按鈕窗體,然后使用“水平排列(lay?out?horizontally)”選項(xiàng)對(duì)它們進(jìn)行一個(gè)接一個(gè)地水平排列。這樣做不僅使得設(shè)計(jì)工作變得更快,而且完成后的窗體將能夠按照屬性設(shè)置的比例填充窗口的可用范圍。

使用Qt圖形設(shè)計(jì)器進(jìn)行圖形用戶接口的設(shè)計(jì)可以消除應(yīng)用的編譯、鏈接和運(yùn)行時(shí)間,同時(shí)使修改圖形用戶接口的設(shè)計(jì)變得更容易。Qt圖形設(shè)計(jì)器的預(yù)覽功能使開發(fā)者能夠在開發(fā)階段看到各種樣式的圖形用戶界面,也包括客戶樣式的用戶界面。通過Qt集成功能強(qiáng)大的數(shù)據(jù)庫(kù)類,Qt圖形設(shè)計(jì)器還可提供生動(dòng)的數(shù)據(jù)庫(kù)數(shù)據(jù)瀏覽和編輯操作。

開發(fā)者可以建立同時(shí)包含有對(duì)話框和主窗口的應(yīng)用,其中主窗口可以放置菜單、工具欄、旁述幫助等子窗口部件。Qt圖形設(shè)計(jì)器提供了幾種表單模板,如果窗體會(huì)被多個(gè)不同的應(yīng)用反復(fù)使用,那么開發(fā)者也可建立自己的表單模板以確保窗體的一致性。

Qt圖形設(shè)計(jì)器使用向?qū)韼椭藗兏臁⒏奖愕亟泄ぞ邫?、菜單和?shù)據(jù)庫(kù)等方面的應(yīng)用。程序員可以建立自己的客戶窗體,并把它集成到Qt圖形設(shè)計(jì)器中。

Qt圖形設(shè)計(jì)器設(shè)計(jì)的圖形界面以擴(kuò)展名為“ui”的文件進(jìn)行保存,這個(gè)文件有良好的可讀性,這個(gè)文件可被uic(Qt提供的用戶接口編譯工具)編譯成為C++的頭文件和源文件。qmake工具在它為工程生成的Makefile文件中自動(dòng)包含了uic生成頭文件和源文件的規(guī)則。

另一種可選的做法是在應(yīng)用程序運(yùn)行期間載入ui文件,然后把它轉(zhuǎn)變?yōu)榫邆湓热抗δ艿谋韱巍_@樣開發(fā)者就可以在程序運(yùn)行期間動(dòng)態(tài)地修改應(yīng)用的界面,而不需重新編譯應(yīng)用,另一方面,也使得應(yīng)用的文件尺寸減小了。

3.建立對(duì)話框

Qt為許多通用的任務(wù)提供了現(xiàn)成的包含了實(shí)用的靜態(tài)函數(shù)的對(duì)話框類,主要有以下幾種。

n QMessageBox類:是一個(gè)用于向用戶提供信息或是讓用戶進(jìn)行一些簡(jiǎn)單選擇(例如“yes”或“no”)的對(duì)話框類,如圖12.15所示。

n QProgressDialog類:包含了一個(gè)進(jìn)度欄和一個(gè)“Cancel”按鈕,如圖12.16所示。

n QWizard類:提供了一個(gè)向?qū)?duì)話框的框架,如圖12.17所示。

??????????? ?????

圖12.15??QMessageBox類對(duì)話框???圖12.16??QProgressDialog類對(duì)話框????圖12.17??QWizard類對(duì)話框

另外,Qt提供的對(duì)話框還包括QColorDialog、QFileDialog、QFontDialog和QPrintDialog。這些類通常適用于桌面應(yīng)用,一般不會(huì)在Qt/Embedded中編譯使用它們。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

華清遠(yuǎn)見(www.farsight.com.cn)是國(guó)內(nèi)領(lǐng)先嵌入師培訓(xùn)機(jī)構(gòu),2004年注冊(cè)于中國(guó)北京海淀高科技園區(qū),除北京總部外,上海、深圳、成都、南京、武漢、西安、廣州均有直營(yíng)分公司。華清遠(yuǎn)見除提供嵌入式相關(guān)的長(zhǎng)期就業(yè)培訓(xùn)、短期高端培訓(xùn)、師資培訓(xùn)及企業(yè)員工內(nèi)訓(xùn)等業(yè)務(wù)外,其下屬研發(fā)中心還負(fù)責(zé)嵌入式、Android及物聯(lián)網(wǎng)方向的教學(xué)實(shí)驗(yàn)平臺(tái)的研發(fā)及培訓(xùn)教材的出版,截止目前為止已公開出版70余本嵌入式/移動(dòng)開發(fā)/物聯(lián)網(wǎng)相關(guān)圖書。企業(yè)理念:專業(yè)始于專注 卓識(shí)源于遠(yuǎn)見。企業(yè)價(jià)值觀:做良心教育、做專業(yè)教育,更要做受人尊敬的職業(yè)教育。