- 相關(guān)推薦
Linux下的GTK圖形界面編程
【摘要】 本文介紹了Linux平臺下的Xwindow圖形窗口編程工具GTK,并給出了用GTK編程的基本要素和步驟。 【關(guān)鍵詞】GTK,回調(diào)函數(shù),消息處理器,調(diào)節(jié)器GTK(GIMP Toolkit)是一個圖形用戶編程的接口工具。它注冊完全免費,所以用來開發(fā)自由軟件或商業(yè)軟件都不需要花費什么,F(xiàn)在很多Linux集成系統(tǒng)都已經(jīng)將GTK1.2版本打包進去了。包括RedHat Linux 6.0以上版本,還有中文化的Turbo Linux等等。它也越來越被普遍的應(yīng)用于UNIX系統(tǒng)編程。還有一個組件叫Glib,它包含了一些標(biāo)準(zhǔn)應(yīng)用的新擴展用來提高GTK的兼容性。用于Linux系統(tǒng)的某些函數(shù)可能不適合標(biāo)準(zhǔn)的UNIX系統(tǒng),例如g_strerror()函數(shù)等等。某些函數(shù)也擴展了GNUC的一般功能,例如g_malloc函數(shù)就有自己加強的調(diào)試功能。
GTK可以與多種語言綁定,包括C++, Guile, Perl, Python, Ton, Ada95, Objective C, Free Pascal, Eiffel。用標(biāo)準(zhǔn)C開發(fā)的程序,編譯軟件可用GNU并附帶上GTK選項即可。想用除了標(biāo)準(zhǔn)C以外的其它語言來開發(fā)Xwindow圖形用戶程序,則需要先參考一下有關(guān)綁定軟件的內(nèi)容(HTTP:// www.gtk.org)。 如果用C++語言來調(diào)用GTK進行開發(fā),可以用已經(jīng)和C++綁定的軟件叫GTK--軟件,來提供一個比GTK更好的C++編譯環(huán)境。
目前已經(jīng)開發(fā)出來GTK的增強版GTK+。GTK+是將GTK,GDK,GLIB集成在一起的開發(fā)包,可以工作在許多類似于UNIX的系統(tǒng)上,沒有GTK的平臺限制。
1
.GTK的消息處理機制下面我們先看一個基本的例子,該例子產(chǎn)生一個
200×200像素的窗口。它不能自己退出,只能通過shell來殺死進程(調(diào)用kill命令)。/*
例子 base.c */#include <gtk/gtk.h>
int main( int argc,char *argv[ ] ){
GtkWidget *window;
gtk_init (&argc, &argv); /*
初始化顯示環(huán)境 */window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*
創(chuàng)建一個新的窗口*/gtk_widget_show (window); /*
顯示窗口*/gtk_main (); /*
進入睡眠狀態(tài),等待事件激活*/return(0);
}
從上面的程序可以看出,
GTK是一個事件驅(qū)動工具包,當(dāng)它運行到gtk_main()函數(shù)時會自動睡眠,直到有事件發(fā)生,控制權(quán)轉(zhuǎn)讓給相應(yīng)的函數(shù)調(diào)用,在該函數(shù)中可以用標(biāo)準(zhǔn)C寫出相應(yīng)的事物邏輯。這與windows 上的程序處理是一樣的。對窗口對象上發(fā)生的事件(如按下鼠標(biāo),激活鍵盤等),
GTK也有相應(yīng)的消息信號產(chǎn)生。這時就需要程序員創(chuàng)建一個信號處理器來捕獲該信號,并告訴GTK程序事件發(fā)生后調(diào)用哪個回調(diào)函數(shù)。信號處理器的創(chuàng)建函數(shù)定義如下:gint gtk_signal_connect( GtkObject *object, gchar *name,
GtkSignalFunc callback_func, gpointer func_data );
返回值是一個區(qū)分同一對象中的事件與不同回調(diào)函數(shù)的關(guān)聯(lián)標(biāo)簽。這樣可以做到一個對象的一個信號就有任意多個回調(diào)函數(shù),并且每一個都會按照聲明的順序執(zhí)行。函數(shù)調(diào)用的第一個參數(shù)是產(chǎn)生信號的widget組件(即按鈕等窗口構(gòu)件),而name則是希望捕獲的信號或事件的名稱,callback_func則是事件發(fā)生后所調(diào)用的回調(diào)函數(shù)名稱,而第四個參數(shù)func_data則是傳遞給回調(diào)函數(shù)的參數(shù)。
回調(diào)函數(shù)要定義在主程序的前面,它們的一般格式都如下所示:
void callback_func( GtkWidget *widget, gpointer func_data );
調(diào)用下面這個方法將允許你將回調(diào)函數(shù)與事件的關(guān)聯(lián)斷開:
void gtk_signal_disconnect( GtkObject *object, gint id );
該函數(shù)的第二個參數(shù)就是上述gtk_signal_connect()函數(shù)的返回值,即關(guān)聯(lián)標(biāo)簽。第一個參數(shù)指向了去除關(guān)聯(lián)的對象名稱。這樣可以做到斷開事件與回調(diào)函數(shù)的關(guān)聯(lián),使得事件發(fā)生后,不會調(diào)用相關(guān)的回調(diào)函數(shù)。
- 布局格式
2.1打包盒子
對GTK顯示格式的控制是通常通過打包盒子來完成的。widget組件打包可以采用兩種方式,水平盒子和垂直盒子。若將widget組件打包進平行盒子,組件就被依次水平的插入窗口;若是垂直盒子,則組件排列是垂直的。產(chǎn)生新的水平盒子的函數(shù)為
GtkWidget *gtk_hbox_new (gint homogeneous, gint spacing);
參數(shù)homogeneous是用來控制是否盒子中的每個組件都有同樣的大。ɡ缢胶凶又械目丶型瑯拥膶挾龋怪焙凶又械目丶型瑯拥母叨龋。Spacing參數(shù)是組件之間的間隔。
垂直盒子的創(chuàng)建函數(shù)是gtk_vbox_new(),定義與水平盒子一致。
gtk_box_pack_start()和gtk_box_pack_end()函數(shù)是用來將打包對象放入這些盒子中的。
void gtk_box_pack_start( GtkBox *box, GtkWidget *child,
gint expand, gint fill, gint padding );
第一個參數(shù)是你將組件打進去的盒子指針,第二個參數(shù)是你將要打進去的組件指針。Expand參數(shù)是用來控制是否允許組件擴展至分配給盒子空間的大。ㄟxTRUE),還是盒子的大小收縮到組件那么大(選FALSE)。函數(shù)中的fill參數(shù)是用來控制是否將多余的空間分配給組件,即將組件擴展到盒子的大小(選TRUE),或者多余的空間不變,保留作為盒子和打包組件間的間隔。該參數(shù)只有在expand參數(shù)取TRUE時才有效。Padding參數(shù)是指組件四周與盒子的間隔大小。
注意fill取FALSE值,expand取TRUE值時與expand取FALSE值,fill值無效的區(qū)別。前者的盒子仍是原來創(chuàng)建盒子時指定的大小,而后者的盒子已經(jīng)縮小到打包組件的大小了。
gtk_box_pack_end()函數(shù)的參數(shù)與上面描述的一致。只是排列順序分別是從下到上,從右到左。
最后將所有的盒子或組件打包到一個大盒子中,用gtk_container_add()函數(shù)將盒子加入窗口即可。
2.2表格打包
我們可以產(chǎn)生一個表格,將widget組件一一放入。Widget組件將占據(jù)所有分配給它的空間。創(chuàng)建表格是用下面的函數(shù):
GtkWidget *gtk_table_new( gint rows, gint columns,
gint homogeneous );
第一個參數(shù),顯而易見,是表格的行數(shù)。后面的參數(shù)則是表格的列數(shù)。homogeneous參數(shù)則是用來安排表格間隔大小。如果它取TRUE,則表格中每個小格的大小用表格中最大組件的大小來設(shè)置的,所有的小格大小都是一樣的。如果homogeneous參數(shù)取FALSE的,每個小格的大小都用同行中最高組件的高度,同列中最寬組件的寬度。
將一個widget組件放入一個表格,用下面的函數(shù):
void gtk_table_attach( GtkTable *table, GtkWidget *child, gint left_attach,
gint right_attach, gint top_attach, gint bottom_attach,
gint xoptions, gint yoptions, gint xpadding, gint ypadding );
left_attach參數(shù)和right_attach參數(shù)將指出在哪兒放置組件,以及用了多少盒子。如果你想在兩行兩列的表格中的右下小格中加入一個按鈕,并且想讓按鈕充滿那個小格,則參數(shù)可以選擇left_attach = 1, right_attach = 2, top_attach = 1, bottom_attach = 2。其實left_attach也就是組件所在小格的左邊框是表格的第幾條邊數(shù),其它依此類推。
參數(shù)xoptions和yoptions是用來確定打包選項的,可以用OR來選擇多個選項。
- 調(diào)節(jié)器
GTK有很多組件可以用鼠標(biāo)或鍵盤來調(diào)整,例如范圍組件(Range Widget)。還有一些組件在整個數(shù)據(jù)區(qū)域的一部分是可調(diào)整的,例如文本組件(Text Widget)和視口組件(Viewport Widget)。
很明顯,程序是要能夠?qū)烧{(diào)整組件所產(chǎn)生的變化進行處理。一種解決辦法是讓可調(diào)整組件在釋放自己的信號時,將調(diào)整數(shù)據(jù)值傳遞信號處理器;蛘哂昧硗庖环N解決方法將調(diào)整數(shù)據(jù)值放入一個數(shù)據(jù)結(jié)構(gòu),由程序訪問該結(jié)構(gòu)來獲得改變的參數(shù)值。有時候你可能需要將幾個可調(diào)整組件的調(diào)節(jié)相關(guān)聯(lián),調(diào)整一個也會導(dǎo)致另一個的變化。最明顯的例子就是滾動條與文本編輯框組件的處理。如果這些相關(guān)聯(lián)的組件分別有自己處理調(diào)整數(shù)據(jù)的方法,則程序員必須自己寫一個信號處理器,將一個組件的調(diào)整數(shù)據(jù)轉(zhuǎn)換成另一個組件的調(diào)整數(shù)據(jù),并調(diào)用調(diào)整設(shè)置函數(shù)將該值設(shè)置進去。
GTK調(diào)用了調(diào)節(jié)器成功的解決了這個問題。調(diào)節(jié)器不是組件,而是存儲和傳遞調(diào)整數(shù)據(jù)的結(jié)構(gòu)。最典型的調(diào)整器應(yīng)用是存儲配置參數(shù)和范圍組件的值。不同的是調(diào)整器也是從對象(Object)繼承而來的,它有許多不同于數(shù)據(jù)結(jié)構(gòu)的特性。最重要的是,它也會釋放信號,并且這些信號不僅可以被程序捕獲來響應(yīng)用戶的調(diào)整和編輯,還可以在可調(diào)整組件中透明的傳播調(diào)整數(shù)據(jù)。
一般調(diào)節(jié)器會創(chuàng)建組件時自動創(chuàng)建。例如讓文本組件和滾動條組件用同一個調(diào)節(jié)器如下所示:
text = gtk_text_new (NULL, NULL);
/* 將剛創(chuàng)建的調(diào)節(jié)器用于垂直滾動條 */
vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
調(diào)節(jié)器是從對象
Object繼承下來的。所以它與其它的組件對象一樣,能夠產(chǎn)生信號。當(dāng)好幾個組件共享一個調(diào)節(jié)器時,它們都會和一個信號處理器相關(guān)聯(lián)。這個信號處理器是用來處理“value_changed”信號的,跟程序中處理信號是一樣。下面是在GtkAdjustmentClass結(jié)構(gòu)中該信號的定義:void (* value_changed) (GtkAdjustment *adjustment);
不同的可調(diào)整組件都用一個調(diào)節(jié)器時,任何一個組件發(fā)生調(diào)整變化都會產(chǎn)生該信號。有兩種情況會導(dǎo)致這個現(xiàn)象的發(fā)生。第一種情況是用戶在用鼠標(biāo)或鍵盤調(diào)整該組件(例如拉滾動條),或者直接在程序中用
gtk_adjustment_set_value()函數(shù)來改變調(diào)節(jié)器中的value值。當(dāng)調(diào)節(jié)器的
upper參數(shù)和lower參數(shù)被重新配置時,就象用戶需要給一個文本編輯框加入了更多的文本后,調(diào)節(jié)器就會釋放出“changed”信號。它的定義如下:void (* changed) (GtkAdjustment *adjustment);
范圍組件將該信號與一個信號處理器相關(guān)聯(lián),并隨時在面板上反映參數(shù)的變化。舉個例子,滾動條中滑動鍵的大小與調(diào)節(jié)器中
upper,lower值之差正好成反比。一旦前者有任何改變,面板上的顯示也會相應(yīng)產(chǎn)生變化。不需要在程序中將一個信號處理器與該信號相關(guān)聯(lián),一切都是
GTK完成的。如果你直接設(shè)置了調(diào)節(jié)器的這些參數(shù),則需要在程序中調(diào)用下面的語句來釋放信號:gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
- 創(chuàng)建組件小結(jié)
widget組件可以用以下幾個步驟完成:從上面可看出,創(chuàng)建一個
- 創(chuàng)建組件小結(jié)
- gtk_*_new()—調(diào)用一個非常有用的函數(shù)來產(chǎn)生一個新的widget組件。
4.2用gtk_box_pack_start()函數(shù)連接所有的信號和事件,產(chǎn)生相應(yīng)的事件處理器來調(diào)用回調(diào)函數(shù)。
4.3設(shè)置widget組件以及調(diào)節(jié)器的特性。
4.4用合適的函數(shù)將widget組件打包到一個容器(盒子或表格)中,例如gtk_box_container_start()函數(shù)或者gtk_container_add()函數(shù)等。
4.5用gtk_widget_show()函數(shù)來顯示組件。
用上述方法可創(chuàng)建出程序員所需要的任意窗口構(gòu)件,再將容器打入窗口并顯示窗口之后,程序便進入主循環(huán)睡眠狀態(tài),主程序編制也就結(jié)束了。事件的處理邏輯放到回調(diào)函數(shù)中編制。
編譯程序用下面的命令:
gcc my_prog.c –o my_prog.o –lgtk –lgdk ↙
完成后在Xwindow環(huán)境下運行my_prog.o程序即可。
目前X窗口(Xwindow)和GNU編譯系統(tǒng)已成為應(yīng)用linux或unix操作系統(tǒng)的計算機工作站和大型計算機上最主要的圖形用戶界面系統(tǒng),在微機上也有廣泛應(yīng)用。而GTK正是兩者結(jié)合的編程開發(fā)包。它比以往用的Xwindow/Motif編程更為簡單方便,功能也很強大,有著較好的應(yīng)用前景。目前網(wǎng)上已經(jīng)有很多利用該軟件包開發(fā)出來的自由發(fā)布軟件,極大的豐富了Linux平臺的應(yīng)用。
[參考文獻]
1.《GTK Turtoil》 Peter Mattis, Spencer Kimball, Josh MacDonald著 http://www.gtk.org
2.《linux系統(tǒng)管理指南》 M.F.Komarinski,C.Collet著 曉冬 馬丁譯 1999,清華大學(xué)出版社
3.《UNIX網(wǎng)絡(luò)編程》 W.Richard Stevens著 1998,清華大學(xué)出版社
【Linux下的GTK圖形界面編程】相關(guān)文章:
嵌入式Linux系統(tǒng)下Microwindows的應(yīng)用08-06
QNX環(huán)境下多線程編程08-06
Linux系統(tǒng)下USB攝像頭驅(qū)動開發(fā)08-06
嵌入式Linux下基于MiniGUI的信息終端軟件開發(fā)08-06
linux實習(xí)心得03-02
基于PXA255的PDA交通管理系統(tǒng)在Linux環(huán)境下的實現(xiàn)08-06
在Linux下用Qt開發(fā)新一代DTS圖形數(shù)據(jù)系統(tǒng)的分析08-06
Linux對TCP/IP的支持淺析08-06