- 論壇徽章:
- 1
|
用Gtk+開發(fā)unix上的GUI應(yīng)用軟件
一般一個(gè)容器構(gòu)件只能容納一個(gè)構(gòu)件,如果要在一個(gè)容器構(gòu)件中安排多個(gè)子構(gòu)件,可先將多個(gè)子構(gòu)件放入一個(gè)組合框或組合表構(gòu)件內(nèi),再將這個(gè)組合框或組合表構(gòu)件放入該容器構(gòu)件。
一、如何建立Gtk+應(yīng)用
1.基本概念
在unix上開發(fā)GUI應(yīng)用軟件,我們通常利用Gtk+庫。為了深入了解Gtk+的應(yīng)用,我們首先要明確幾個(gè)概念。
(1) 構(gòu)件(widget)的概念
在Gtk+庫里的窗口、選單和按鈕等應(yīng)用實(shí)體,我們稱之為構(gòu)件(widget)。構(gòu)件具有面向?qū)ο蟮奶卣鳎渚唧w結(jié)構(gòu)由Gtk+庫定義,它對運(yùn)用構(gòu)件的程序員來說是透明的,除非你想創(chuàng)建自己的構(gòu)件。在對構(gòu)件進(jìn)行安排時(shí),我們只需要關(guān)心構(gòu)件的處理函數(shù),這樣做的目的就是要對應(yīng)用程序員屏蔽構(gòu)件的細(xì)節(jié),使程序員將更多的精力集中在應(yīng)用功能上。
(2) 容器(container)的概念
構(gòu)件主要分為兩大類,即容器類(container)和雜類(miscellaneous)。大多數(shù)構(gòu)件屬容器類,它們可以像容器一樣容納其它的構(gòu)件。在安排構(gòu)件時(shí)常常要遵循一個(gè)規(guī)則:除了組合框(box)和組合表(table)這兩種構(gòu)件外,其它的容器類構(gòu)件都只能容納一個(gè)構(gòu)件。雜類構(gòu)件比容器類構(gòu)件簡單,但它不能容納其它構(gòu)件。
(3) 消息及回呼函數(shù)的概念
程序必須能對用戶的操作作出反應(yīng),在基于GUI的程序設(shè)計(jì)中,“消息”或“信號”是必要的。用戶點(diǎn)擊選單、各種按鈕、輸入用戶數(shù)據(jù)、查詢運(yùn)行結(jié)果和拖放,都會產(chǎn)生消息或信號。信號可能需要由軟件來加以處理,這時(shí)程序員就需要編寫消息回呼函數(shù)。消息或信號的概念類似于Windows中的事件。在Gtk+中經(jīng)常產(chǎn)生各種信號,用戶產(chǎn)生的大多數(shù)信號被忽略,只有程序關(guān)心的信號,程序中才有相應(yīng)的處理函數(shù)被調(diào)用。程序員要登記信號與處理函數(shù)之間的關(guān)系,告訴Gtk+哪些信號或事件是程序所關(guān)心的。
2. 構(gòu)件(widget)的運(yùn)用
在調(diào)用Gtk+的構(gòu)件時(shí),一般進(jìn)行如下操作步驟:
。1) 包含所調(diào)用構(gòu)件的頭文件
頭文件通常存放在/usr/include/gtk/目錄下,該文件里有對構(gòu)件的定義及對構(gòu)件的操作函數(shù),在我們使用構(gòu)件時(shí),可以經(jīng)常在這個(gè)目錄下查閱構(gòu)件函數(shù)的調(diào)用格式或參數(shù)。我們不必讓所有構(gòu)件包含頭文件,因?yàn)闃?gòu)件的頭文件已包含在該目錄下一個(gè)名為gtk.h的文件里,包含這個(gè)文件就包含了所有構(gòu)件的頭文件。一般系統(tǒng)將編譯的包含目錄指定為/usr/include,所以我們只需寫明 include 即可。
。2) 聲明構(gòu)件
聲明構(gòu)件的過程是為了符合C語言中先聲明后使用的原則。一般在程序開始要聲明構(gòu)件結(jié)構(gòu)的指針,這就為構(gòu)件分配了地址。
。3) 構(gòu)件指針的初始化
調(diào)用構(gòu)件的創(chuàng)建函數(shù),對構(gòu)件的屬性進(jìn)行調(diào)整(大小、位置和狀態(tài)等),接著顯示構(gòu)件,這一點(diǎn)不能忽略,如果只創(chuàng)建了構(gòu)件卻忘了顯示(gtk_widget_show),在應(yīng)用時(shí),用戶就不能看到構(gòu)件,也就無法對構(gòu)件進(jìn)行操作了。
(4) 安排構(gòu)件的位置與層次關(guān)系
構(gòu)件之間往往是容納與被容納的關(guān)系,也就是說容器內(nèi)還有容器,層層嵌套。要記住一般一個(gè)容器構(gòu)件只能容納一個(gè)構(gòu)件,如果要在一個(gè)容器構(gòu)件中安排多個(gè)子構(gòu)件,可先將多個(gè)子構(gòu)件放入一個(gè)組合框或組合表構(gòu)件內(nèi),再將這個(gè)組合框或組合表構(gòu)件放入該容器構(gòu)件。注意父容器構(gòu)件要先于子容器構(gòu)件創(chuàng)建,父容器構(gòu)件的顯示要在子容器構(gòu)件的顯示之后。
。5) 編寫事件處理函數(shù)
構(gòu)件的頭文件中定義了構(gòu)件能響應(yīng)的事件(消息),但并非所有的消息在應(yīng)用中都是程序所關(guān)心的,對于程序應(yīng)當(dāng)響應(yīng)的事件,程序員要寫出事件處理函數(shù)。
二、應(yīng)用舉例
為了對Gtk+庫的應(yīng)用有一個(gè)具體的認(rèn)識,讓我們來看一個(gè)簡單的應(yīng)用實(shí)例。
1. 初始化Gtk+
寫Gtk+程序需要調(diào)用gtk_init函數(shù)對Gtk+庫進(jìn)行初始化。我們首先將應(yīng)用程序的變量argc和argv傳遞給gtk_init函數(shù),并檢查主要用于調(diào)試的Gtk+選項(xiàng)。如果在變量列表中出現(xiàn)任何這樣的Gtk+參數(shù),就將它移去。在運(yùn)行g(shù)tk_init函數(shù)后,它們不應(yīng)該出現(xiàn)在應(yīng)用程序中。初始化Gtk+的代碼如下:
gtk_init(&&argc,&&argv);
2. 建立構(gòu)件
首先要建立的構(gòu)件是窗口,它是應(yīng)用程序的頂層構(gòu)件,其它構(gòu)件一般安排在頂層窗口中。窗口是GUI程序的基本框架,在窗口里我們可以為用戶安排各種方便的應(yīng)用。一個(gè)應(yīng)用可以有若干個(gè)窗口,這些窗口之間既相互獨(dú)立,又有層次的關(guān)系。窗口有相對固定的風(fēng)格,前景色、背景色、字體和字號等,我們應(yīng)當(dāng)保持定制的風(fēng)格,確保不使應(yīng)用軟件雜亂。
按照上面提出的構(gòu)件運(yùn)用步驟,我們創(chuàng)建一個(gè)程序主窗口:
/?聲明構(gòu)件指針?/
GtkWidget ?window;
/?創(chuàng)建窗口,初始化窗口指針,建立一個(gè)頂層窗口?/
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
/?顯示構(gòu)件?/
gtk_widget_show(window);
/?登記消息與消息處理函數(shù)的關(guān)系?/
gtk_signal_connect(GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(close_window),NULL);
3. 構(gòu)件類型的轉(zhuǎn)換
由于建立的構(gòu)件是通用構(gòu)件,需要將它轉(zhuǎn)換為具體的類型以適合調(diào)用更為專用的函數(shù)。比如建立按鈕構(gòu)件函數(shù)會返回GtkWidget 指針,但是專用的按鈕子程序要求返回GtkButton指針,所以在調(diào)用專用的按鈕函數(shù)以前,需要使用GTK_BUTTON宏將通用的GtkWidget指針轉(zhuǎn)換為GtkButton指針。通常,構(gòu)件是由其它構(gòu)件派生的,窗口構(gòu)件(GtkWindow)是由容器構(gòu)件GtkContainer派生的,而容器構(gòu)件是由通用構(gòu)件派生的。在Gtk+中可以將構(gòu)件指針轉(zhuǎn)換為其父類、祖先類構(gòu)件的任意類型,然后再調(diào)用父類或祖先類構(gòu)件的函數(shù)。
4. Gtk+的事件循環(huán)
對Gtk+進(jìn)行初始化并將窗口等構(gòu)件安排在屏幕上之后,應(yīng)用軟件需要使用Gtk+開始執(zhí)行事件的循環(huán)函數(shù)gtk_main(),沒有這個(gè)函數(shù),應(yīng)用程序運(yùn)行時(shí)就會一閃即逝。但是在調(diào)用gtk_main_quit()函數(shù)之前對gtk_main()函數(shù)的調(diào)用并不返回,也就是說只有g(shù)tk_main_quit()函數(shù)才能停止Gtk+的執(zhí)行,從而最終退出應(yīng)用程序。我們把gtk_main_quit()函數(shù)放在消息處理函數(shù)close_window()之中,這樣,當(dāng)用戶點(diǎn)擊了窗口的關(guān)閉按鈕,Gtk+收到“delelte_event”消息,然后調(diào)用close_window(),執(zhí)行g(shù)tk_main_quit()函數(shù),整個(gè)程序即可退出。
5. 實(shí)例源代碼
現(xiàn)在創(chuàng)建一個(gè)顯示“hello”字樣的簡單窗口程序。整個(gè)程序?qū)崿F(xiàn)代碼如下:
- //hello.c
- include
- /?關(guān)閉主窗口中的消息處理函數(shù)?/
- close_window(GtkWidget ?window,gpointer data)
- {
- /?中止gtk事件循環(huán)?/
- gtk_main_quit();
- }
- /?主函數(shù)?/
- main(int argc,char ?argv)
- {/?聲明窗口和標(biāo)簽兩個(gè)構(gòu)件?/
- GtkWidget ?window;
- GtkWidget ?label;
- /?初始化Gtk+庫?/
- gtk_init(&&argc,&&argv);
- /?初始化window構(gòu)件?/
- window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
- /?初始化label構(gòu)件?/
- label=gtk_label_new("hello!");
- /?將標(biāo)簽放入窗口內(nèi),函數(shù)內(nèi)用GTK_CONTAINER宏將窗口構(gòu)?/
- /?件的指針類型轉(zhuǎn)換為其父類容器構(gòu)件的指針類型?/
- gtk_container_add(GTK_CONTAINER(window),label);
- /?顯示label構(gòu)件?/
- gtk_widget_show(label);
- /?顯示window構(gòu)件?/
- gtk_widget_show(window);
- /?當(dāng)窗口獲得'delete_event'消息時(shí)調(diào)用close_windw函數(shù)?/
- gtk_signal_connect(GTK_OBJECT(window),"delete_event",
- GTK_SIGNAL_FUNC(close_window),NULL);
- /?gtk事件循環(huán)?/
- gtk_main();
- }
復(fù)制代碼 6. 編譯源代碼及運(yùn)行程序
最后談一下Gtk+在程序編譯和運(yùn)行時(shí)有哪些特別之處。在unix系統(tǒng)下的C編譯器,如gcc,要求編譯時(shí)在編譯命令后加上各種參數(shù),如果參數(shù)太復(fù)雜,最好把命令寫入makefile文件。
前面我們講過在應(yīng)用程序文件中用到Gtk+函數(shù)或定義的每一部分必須包含gtk/gtk.h文件,它是Gtk+的主要包含文件。此外,還必須連接若干庫。Gtk+的開發(fā)人員為我們提供了方便。使用gtk-config程序可以簡化這些工作。編譯hello.c源文件成為可執(zhí)行文件hello的命令如下:
gcc hello.c -o hello `gtk-config -cflags``gtk-config -libs`
注意,程序中一定是反引號(在鍵盤上位于字符1的左邊)。`gtk-config`實(shí)際運(yùn)行了gtk-config程序;參數(shù)-cflags輸出編譯標(biāo)志,并將它們插入命令行;參數(shù)-libs輸出連接標(biāo)志并插入命令行。在Gtk+ 1.2以上版本中包含gtk-config程序。在unix的命令行提示符后敲入`gtk-config -cflags`和`gtk-config -libs`表示給gcc 傳遞參數(shù)的正確方法。
用shell命令“chmod -777 hello”將文件hello設(shè)定為所有用戶都可執(zhí)行的文件,再用shell命令“./hello”執(zhí)行這個(gè)文件。
三、小結(jié)
本文僅提供了對Gtk+庫應(yīng)用的基本思路,對于想利用Gtk+開發(fā)unix應(yīng)用的C程序員來說是入門的一課,深入的應(yīng)用和開發(fā)技巧需要讀者在今后不斷的實(shí)踐中獲得。 |
|