Antkillerfarm Hacking V7.0

GTK学习心得

2014-12-26

GTK

1)安装环境

本人所使用的开发环境是Ubuntu 12.04。默认情况下已经安装了GTK+3开发所需的包。可以使用pkg-config --cflags --libs gtk+-3.0来确认安装的有效性。

阅读示例代码是学习GTK+3的有效途径。可使用sudo apt 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是一个被动事件,无论什么原因,只要改变控件的值,就会触发。

资源

GTK中最关键的GLib,是由Tim Janik设计的。


https://blog.csdn.net/taiyang1987912/article/category/5778511

一个GTK的专栏

2020.7

有4年半时间没有上GTK官网了。这回GTK和Gnome的官网,都改了风格设计,不再是10年前的老样子了。

GTK4已经出了4个预览版,看起来就要正式发布了。从API层面来看,加入了MVVM的设计,CSS应用的也更广了。

12年前,我接触GTK,主要是为了学习Linux GUI编程。

7年前,我研究GTK,开始将工作从Windows转向Linux,那时的目标是写出两个平台都能跑的软件。cygwin/makefile是这时的常客。

5年前,工作全面转入Linux,Windows+Virtual Box。家用双系统。

3年前,工作电脑双系统,几乎不用Windows。

在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包中即可。

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的路径设置好。


2021.12

GTK 3.16+的示例如下:

https://github.com/ebassi/glarea-example

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 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。

Fork me on GitHub