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