基于GTK+和X-window的GUI在嵌入式Linux中的應(yīng)用
在大多數(shù)開(kāi)發(fā)人員的印象里,X 系統(tǒng)很龐大,但實(shí)際上,你聽(tīng)到的,是那些對(duì) X 不夠了解的人的一種誤解。在經(jīng)過(guò)裁剪后的情況下,GTK+/X 要比 GTK+/FB 與 Qt/E 還要來(lái)得有效,且 XLIB 對(duì)一般的應(yīng)用程序有著更好的支持作用,應(yīng)用程序的開(kāi)發(fā)會(huì)變得更高效。
如何裁剪 GTK+
我們可以從標(biāo)準(zhǔn)的 GTK+ 發(fā)行版本來(lái)裁剪,裁剪掉其中的不需要的,修改已經(jīng)有的代碼,并加入新的特性所需要的代碼。裁剪的范圍包括小的改動(dòng),也包括一些大的結(jié)構(gòu)性的、核心的改變。
一、 去除 Widgets 窗口
最開(kāi)始,我們把不需要的 Widgets 去除掉,比如:GtkGamma、GtkHRuler、過(guò)時(shí)了的 GtkList(被 GtkCList所替代了)、和我們不需要的 GtkFrame 邊框。
二、 Widgets 窗口尺寸與繪制
接著,修改Widgets的大小與繪制方法,GTK+提供了一個(gè)主題引擎機(jī)制,來(lái)控制窗口的外觀與效果。它允許在運(yùn)行中設(shè)置字體,設(shè)置行間隔,設(shè)置繪制特性。這樣的機(jī)制很不錯(cuò),但不夠靈活,代碼中很多設(shè)置的地方都是使用硬編碼的方式;另外,一種主題,就是一堆額外的代碼段和參數(shù),這樣會(huì)增加整體的尺寸。
需要找出影響到窗口系統(tǒng)整體尺寸的內(nèi)容,再來(lái)修改它。比如,一個(gè)按鈕的大小與繪制,包括這樣的參數(shù):邊框的寬度,x/y的位置(主題引擎需要的參數(shù)),缺省的間隔(常量),缺省的左上角的位置(常量),獲得焦點(diǎn)。這些在嵌入系統(tǒng)中并不需要那么完整,我們可以根據(jù)實(shí)際的需求來(lái)簡(jiǎn)化代碼,來(lái)避免 GTK+的復(fù)雜性。
另外,使用面向?qū)ο蟮姆椒ǎ瑏?lái)繼承窗口Widgets的特性,作為子類也是一個(gè)有效的方法。
三、GtkWindow
GTK+總是假定一個(gè)窗口里面包含了另一個(gè)窗口,它們就是嵌套關(guān)系。但對(duì)于我們經(jīng)常會(huì)碰到的有軟鍵盤的應(yīng)用時(shí),就不完全正確了。軟鍵盤雖然是屬于一個(gè)窗口的,但卻會(huì)超出那個(gè)窗口。所以為了突破這個(gè)假定,需要對(duì)GtkWindow增加一些特性,將軟鍵盤處理成一種特殊的子窗口。
軟鍵盤所在的窗口,需要處理軟鍵盤的按鍵事件,并將按鍵轉(zhuǎn)發(fā)給軟鍵盤工具條。當(dāng)軟鍵盤按下,軟鍵盤的回調(diào)函數(shù)就被注冊(cè)到原始窗口上,這樣軟鍵盤就會(huì)響應(yīng)按鍵事件。在GtkWindow上增加接口,可以創(chuàng)建,響應(yīng)按鍵。
在小屏幕的嵌入系統(tǒng)中,可以將滾動(dòng)條做得更簡(jiǎn)化些,去掉邊框,使用單個(gè)滾動(dòng)條。這些都更適合嵌入系統(tǒng)。
字體管理系統(tǒng)
在字體管理方面,要找到一個(gè)輕型的機(jī)制來(lái)在嵌入式系統(tǒng)顯示各種字體,并不是那么簡(jiǎn)單,困難在于GTK+ 的大型的 Widget 風(fēng)格與 X 系統(tǒng)的老式的字體管理機(jī)制的結(jié)合所引起的問(wèn)題。
前面提到的,主題引擎方式的GTK+ 是用來(lái)控制窗口的樣式與外觀的。在一個(gè)窗口顯示之前,它會(huì)得到一個(gè)式樣對(duì)象,GtkStyle,它可以是一個(gè)指向父窗口的式樣對(duì)象指針,或者是一個(gè)新的類型,這些式樣對(duì)象將被應(yīng)用到這個(gè)窗口及它的子窗口。這個(gè)式樣由缺省值、rc 文本文件、應(yīng)用來(lái)確定。
要改變一個(gè)窗口的字體,你必須克隆窗口的式樣,并使用X字體加載一個(gè)新的字體,類似adobe-helvetica-bold-r-normal--12-*-*-*-p-*-iso8859-1。
但實(shí)際中會(huì)有些問(wèn)題,GtkStyle是一個(gè)大的對(duì)象。如果一個(gè)屏幕上有很多種不同字體大小的多個(gè)窗口,每個(gè)都有一個(gè)唯一的GtkStyle對(duì)象,我們就會(huì)浪費(fèi)大量的內(nèi)存。到最后,X系統(tǒng)就不能支持類似字體的各種變化了。你甚至不能使X完成讓某個(gè)字體變粗的操作,因?yàn)閄系統(tǒng)是將不同外型的字體作為不同的字體的。X系統(tǒng)是假定你會(huì)硬編碼一個(gè)希望的字體或者分析出一個(gè)字體名,改變字體及驗(yàn)證結(jié)果都將在字體服務(wù)器上。
還可以使用一個(gè)更好的方法來(lái)完善字體管理系統(tǒng),即包裝GtkStyle,這樣開(kāi)發(fā)者就可以通過(guò)屬性來(lái)獲得一個(gè)窗口的字體,這比直接使用 X 系統(tǒng)字體的名字要更靈活。比如要顯示一個(gè)比基本字體要大一號(hào),并且是黑體字就可以調(diào)用:
gtk_widget_set_font_bold (widget, TRUE);
gtk_widget_set_font_enlarge (widget, 1);
這是通過(guò)在 GtkWidget 結(jié)構(gòu)中加入一個(gè) GdkFont * font 來(lái)實(shí)現(xiàn)的,GtkWidget 是所有窗口類的父類。如果設(shè)置widget->font 那么就使用它,否則就使用widget->style->font。
窗口管理
在嵌入系統(tǒng)GUI中,還需要建立一個(gè)窗口管理器。我們可以選擇一個(gè)開(kāi)放代碼的,輕量級(jí)的X管理器,Aewm。在嵌入系統(tǒng)中,我們會(huì)將最上層的窗口設(shè)置為獲得焦點(diǎn),并且只有對(duì)話框能移動(dòng),能顯示其標(biāo)題欄。
窗口管理器是一個(gè)交互端,它可以管理內(nèi)部與外部的應(yīng)用程序的窗口。每一個(gè)應(yīng)用程序的窗口,都會(huì)建立一個(gè) socket 連接,并取一個(gè)名字。一個(gè)應(yīng)用可以把請(qǐng)求將自己放在窗口堆棧的最下面,或者將一個(gè)命名的應(yīng)用往上移。如果一個(gè)對(duì)話框要在最上層的窗口上打開(kāi),那么窗口管理器就將告訴這個(gè)最上層的窗口它將不再獲得焦點(diǎn),而新對(duì)話框?qū)@得焦點(diǎn)。
評(píng)論