GTK学习心得
http://antkillerfarm.github.io/
GTK
1)安裝環(huán)境
本人所使用的開發(fā)環(huán)境是Ubuntu 12.04。默認(rèn)情況下已經(jīng)安裝了GTK+3開發(fā)所需的包??梢允褂胮kg-config –cflags –libs gtk+-3.0來確認(rèn)安裝的有效性。
閱讀示例代碼是學(xué)習(xí)GTK+3的有效途徑??墒褂胹udo apt-get install gtk-3-examples安裝相關(guān)的示例代碼。
2)Glade
Glade仍然是GTK+3默認(rèn)的UI設(shè)計(jì)工具。與GTK+3配合的Glade版本是Glade 3。但是與Glade 2不同的是,Glade 3不再生成相關(guān)的C代碼,取而代之的是一個描述UI的XML文件。因此,多年前積累的使用經(jīng)驗(yàn)已經(jīng)不起作用了。需要從頭學(xué)起。
在GTK官網(wǎng)的GTK+ 3 Reference Manual中的Getting Started with GTK+一節(jié),提供了如何使用Glade布局文件的例子。但實(shí)際上Glade除了布局之外,也支持消息映射的定義。例如,我們完全可以在Glade中定義某個按鈕的點(diǎn)擊事件的回調(diào)函數(shù),而無需再使用g_signal_connect函數(shù)去鏈接消息和回調(diào)函數(shù)。
不過,如果在Glade中使用了該特性的話,相關(guān)的編譯選項(xiàng)亦需要調(diào)整。
由
pkg-config --cflags --libs gtk+-3.0
改為
pkg-config --cflags --libs gtk+-3.0 gmodule-export-2.0
這樣修改之后,程序即可自動鏈接相應(yīng)的回調(diào)函數(shù)。另外還要注意,用戶定義的回調(diào)函數(shù)的定義需與文檔中消息回調(diào)函數(shù)的原型一致。一些細(xì)微的差異會導(dǎo)致g_signal_connect函數(shù)顯式指定的回調(diào)函數(shù)可以正常工作,但glade文件隱式指定的卻不行。
此外,如果是在Windows平臺下使用GTK+,還需要在回調(diào)函數(shù)之前加上G_MODULE_EXPORT宏。
3)事件回調(diào)函數(shù)
事件回調(diào)函數(shù)一般包括兩個參數(shù),第一個是產(chǎn)生事件的Widget的指針,第二個是用戶自定義的數(shù)據(jù)的指針??梢詫⑿枰獋鬟f的數(shù)據(jù)用這個指針傳遞。如示例(http://code.google.com/p/antkillfarm-source-pool/source/browse/tags/first_demo.7z)中的do_cmd_itouch函數(shù)所示。
4)如何獲得某個控件的指針
事件回調(diào)函數(shù)只能返回一個用戶數(shù)據(jù)指針,有的時候某個按鍵動作會同時對幾個控件進(jìn)行操作。這個時候就需要通過某種方式來獲得各個控件的指針。
如示例(http://code.google.com/p/antkillfarm-source-pool/source/browse/tags/first_demo.7z)中的do_cmd_ipod函數(shù)所示:
1–首先在Glade中,將main_box的指針設(shè)為用戶數(shù)據(jù)指針。
2–使用gtk_container_get_children函數(shù)獲得各個子控件的指針鏈表。
3–GTK中使用GList類型來表示雙向鏈表數(shù)據(jù)結(jié)構(gòu)??墒褂胓_list_first獲得鏈表的頭結(jié)點(diǎn)。但是需要注意
g_list_next函數(shù)的參數(shù)是當(dāng)前節(jié)點(diǎn)main_box_child,而不是鏈表的指針main_box_children_list。這個類型的相關(guān)函數(shù)中并不存在一個類似枚舉器的概念。
4–gtk_widget_get_name函數(shù)返回的是控件的類型名,例如GtkLabel。gtk_buildable_get_name函數(shù)返回的才是控件的id,例如label_hello。顯然只有根據(jù)Glade文件生成的控件才有id。
5)多窗體開發(fā)
單窗口GTK+程序的編程,很快就掌握了。下一步開始實(shí)踐點(diǎn)擊一個按鈕,生成一個新窗口的功能。網(wǎng)上的例程多數(shù)都是基于GTK+ 2的。由于GTK+和Glade的版本升級,這樣的方式雖然仍然可用,但卻不再是最簡便的方式了。
首先還是使用Glade編輯ui文件。一個ui文件可以包含若干個窗口定義。調(diào)用gtk_builder_add_from_file生成這些窗口的數(shù)據(jù) 結(jié)構(gòu)。可以將生成的窗口結(jié)構(gòu)通過user_data的方式傳遞給按鈕的回調(diào)函數(shù)。但是需要注意的是,傳遞給回調(diào)函數(shù)的窗口結(jié)構(gòu)必須是有效的。
例如,在ui文件中,將B窗口結(jié)構(gòu)傳給A窗口中的C按鈕的回調(diào)函數(shù)。程序運(yùn)行時,首先點(diǎn)擊C按鈕,彈出B窗口,然后關(guān)閉B窗口,并再次點(diǎn)擊C按鈕,結(jié)果什么反應(yīng)也沒有,B窗口并未如預(yù)期般彈出。
經(jīng)分析方知,關(guān)閉B窗口的時候,B窗口的數(shù)據(jù)結(jié)構(gòu)被銷毀,從而不再有效。因此如果想要再次彈出B窗口的話,就只有兩種辦法:
1)重新創(chuàng)建B窗口的數(shù)據(jù)結(jié)構(gòu)。
2)重載B窗口的關(guān)閉消息,讓它只是隱藏而不是銷毀窗口。
對于第2種方案,網(wǎng)上的例子很少,有也基本都是重載窗口的destroy信號。但實(shí)際上delete-event才是關(guān)閉事件的信號,只有做完了 delete-event才會執(zhí)行destroy。這一點(diǎn)在GTK的用戶手冊上有詳細(xì)的說明。同時,手冊還推薦使用 gtk_widget_hide_on_delete函數(shù)來實(shí)現(xiàn)第2種方案。
6)change-value和value-changed
GtkScale有兩個容易混淆的事件:change-value和value-changed。
兩者的區(qū)別是,change-value是一個主動事件,只有用戶通過GUI操作控件才會觸發(fā);而value-changed是一個被動事件,無論什么原因,只要改變控件的值,就會觸發(fā)。
在Windows下使用GTK+3
2013.9
1)安裝MinGW
我比較偷懶,之前安裝Qt SDK的時候,已經(jīng)有了個MinGW環(huán)境,直接拿來用就可以了。
2)下載GTK+3 for Windows
到http://www.tarnyko.net/下載GTK+3的包。該網(wǎng)站是個法國佬辦的。在www.gtk.org官方的維護(hù)GTK+ for Windows的人員閃人之后,這是少數(shù)幾個移植GTK+3到Windows,且成功的版本。
該網(wǎng)站還有一篇GTK+3 Installation Tutorial for Windows的文章,介紹如何安裝他制作的GTK包。里面還附帶有一個Hello World程序代碼,對于初始的學(xué)習(xí)很有幫助。
3)優(yōu)化自己的開發(fā)環(huán)境
在mingw文件夾下新建MinGW.bat文件,內(nèi)容如下:
set PATH=D:\QtSDK\mingw\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;D:\gtk+-bundle_3.6.4-20130513_win32\bin
cmd
除了幾個Windows的系統(tǒng)路徑之外,把MinGW和GTK的路徑加進(jìn)去就可以了。
把mingw32-make.exe復(fù)制一份,并改名make.exe,就可以如同在Linux環(huán)境下一樣,使用makefile文件控制編譯過程了。
4)如何去掉執(zhí)行文件時的命令行窗口?
編譯時添加-mwindows選項(xiàng),就可以只啟動gtk窗口,不啟動命令行窗口。
5)找不到-lintl該怎么辦?
到opensuse的官網(wǎng)下載mingw32-libintl的rpm包。用7-zip解壓安裝到gtk包中即可。
2015.11
稍早的時候,我在安裝pygtk的環(huán)境時,發(fā)現(xiàn)pygi-aio安裝程序提供的GTK版本已經(jīng)到了3.14。但GTK官方這時仍然沒有進(jìn)展,版本停留在3.6.4。于是我又打算使用pygtk提供的更新來進(jìn)行編程,但pygtk只提供了.dll文件,而沒有.h和.lib文件,實(shí)際上并不好用,因此只得放棄之。
最近再上官網(wǎng),發(fā)現(xiàn)其已經(jīng)提供了更好的解決辦法——MSYS2。MSYS2是Martell Malone維護(hù)的一個開源項(xiàng)目,旨在提供一個方便易安裝的MSYS開發(fā)環(huán)境,其中也包括為各種開發(fā)包提供更新維護(hù),GTK就是其中之一。(當(dāng)前的版本為Gtk 3.18.3)
現(xiàn)將安裝步驟羅列如下:
1.在https://msys2.github.io/,下載安裝程序,并按照網(wǎng)頁提示,更新pacman。
2.使用pacman下載必要的開發(fā)包。
pacman -S autoconf autogen automake-wrapper pkg-config make gcc gdb
pacman -Ss <name>: 查詢相關(guān)的軟件包是否存在。
pacman -Syu: 更新已安裝的軟件包。
MSYS2提供的環(huán)境除了安裝友好,便于更新之外,對bash的支持也優(yōu)于之前的版本?,F(xiàn)在已經(jīng)不需要單獨(dú)為Windows平臺提供特殊的makefile文件了。
GTK & OpenGL
眾所周知,OpenGL只是一個圖形渲染庫,沒有對于窗口系統(tǒng)的支持,而glut等也只是提供了最基本的窗口操作,使用起來并不方便。因此最好的做法是在一個成熟的GUI庫的基礎(chǔ)上添加OpenGL的支持。
GTK 2下使用OpenGL,可以考慮使用GtkGLExt。但該軟件并不支持GTK 3。
按照GTK 3官方的說法,他們計(jì)劃在2015年4月發(fā)布的GTK 3.16中集成對于OpenGL的支持,但實(shí)際上相關(guān)的支持代碼已經(jīng)于2014年12月17日,由Chun-wei Fan提交到版本庫中。
搜了一下,Chun-wei Fan是一位臺灣同學(xué),因?yàn)樗泥]箱是臺灣Yahoo的。但估計(jì)不是linkedin中的哥們,那個人雖然也是搞IT的,但偏重Java和網(wǎng)頁方面的開發(fā)。
從git log來看,這個Chun-wei Fan是GTK的骨灰級提交者,提交次數(shù)240+,從2010年11月就開始提交,提交內(nèi)容多集中在GTK的Windows移植上,尤其是如何使用VS來編譯GTK。
但是編譯GTK工作量較大,對于我這樣臨時抱佛腳的人來說,起不了什么作用。
于是我打算用最簡單的方法,解決在Windows平臺下,GTK 3對于OpenGL的支持。
我主要參考了以下文章:
http://garfileo.is-programmer.com/posts/25812
這篇文章講述了如何使用GLX,向GTK 3中添加OpenGL支持。考慮到在Windows下,MS提供了WGL作為GLX的等價物。因此我們只要將該文章中與GLX相關(guān)的內(nèi)容用WGL替換掉,理論上就可以在Windows平臺上,提供對GTK 3的OpenGL支持。
參考文獻(xiàn)還包括:
1.http://msdn.microsoft.com/en-us/library/windows/desktop/dd374204(v=vs.85).aspx
這篇文章講述GLX和WGL函數(shù)之間的對應(yīng)關(guān)系。
2.http://msdn.microsoft.com/en-us/library/dd318258(v=vs.85).aspx
這篇文章提供了一個最簡單的GLX的例子,并給出了在WGL下的等價代碼。
移植成功的代碼放在:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtkglx
用戶需要根據(jù)自己的實(shí)際情況,修改Makifile.w32中的相關(guān)路徑,把GTK和MINGW的路徑設(shè)置好。
GTK與系統(tǒng)圖標(biāo)
在GTK 2.x時代,用戶可以通過一系列的stock API來調(diào)用GTK自帶的圖標(biāo),比如gtk_tool_button_new_from_stock函數(shù)。
到了GTK 3.x時代,GTK使用Icon Theme取代了之前的stock。不光函數(shù)名發(fā)生了變化,就連參數(shù)中名稱的字符串也發(fā)生了變化。stock時代,將相關(guān)字符串定義為C語言的宏。而Icon Theme時代,需要在/usr/share/icons目錄下,查找所需要的圖標(biāo),然后把圖標(biāo)的后綴名去掉,即可得到相關(guān)字符串。
Icon Theme系統(tǒng)的關(guān)鍵是各個目錄下的index.theme文件。
GTK嵌入網(wǎng)頁
GTK嵌入網(wǎng)頁的方案,主要有兩種:GtkMozEmbed和WebkitGtk。
GtkMozEmbed調(diào)用Mozilla的Gecko內(nèi)核渲染網(wǎng)頁,這個方案在2008年以前比較流行。但近些年來,由于Webkit的流行,該方案已經(jīng)日趨式微,最新版本仍然停留在2008年。
WebkitGtk調(diào)用Webkit內(nèi)核渲染網(wǎng)頁。它的安裝方法:
sudo apt-get install libwebkitgtk-3.0-dev
注意這里需要根據(jù)你的gtk環(huán)境和Webkit API的版本選擇不同的包。比如Gtk 2.x選擇libwebkitgtk-dev,Gtk 3.x+Webkit 2選擇libwebkit2gtk-3.0-dev。
例子參見:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtk_browser
這里有兩個例子,一個是helloworld型的,用于確定開發(fā)環(huán)境。另一個是從http://imtx.me/archives/1124.html中摘錄的,原始的版本基于Gtk 2.x,現(xiàn)在改用Gtk 3.x。
GIO網(wǎng)絡(luò)應(yīng)用開發(fā)
GIO提供了以GSocket為首的低級API,和以GSocketClient、GSocketConnection為首的高級API。
高級API的使用示例如下:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/helloworld/glib/network
總結(jié)
- 上一篇: Android研究
- 下一篇: CC2530, 各种智能家居通信技术比较