GTK+学习:概述 、搭建环境(Windows,Linux)、开发

GTK+学习:概述


    相对于Swing之于Java,C/C++环境下的GUI构建就显得复杂得多。首先就是C/C++语言并没有一个官方的GUI库。于是,第三方类库就如雨后春笋般成长起来。由于C/C++没有Java类似的跨平台性,所以其类库大多也是限定平台的,比如微软的MFC。当然也会有很多能够跨平台的 GUI库,比如Qt,比如wxWidget,比如我们这里所要讲解的GTK+。
 
    相对于MFC、Qt和wxWidget,GTK+使用面向对象框架的纯C语言编写。这是一个小巧但是功能丝毫没有逊色的GUI类库。Linux 下的GNOME环境就是使用GTK+编写的,还有类似于Photoshop的GIMP,更与GTK+有着密不可分的联系。下面先来简单介绍一下GTK+。
 
    说起GTK+,首先要先说GIMP。在很多推荐使用自由软件代替商业软件的文章中,大多会提到,使用开源的GIMP代替Photoshop。GIMP是GNU Image Manipulation Program的缩写,最初是类Unix操作系统上的图像处理程序,现在也被移植到了Windows平台。为了简化GIMP的开发,GIMP ToolKit诞生了,这就是GTK。在增加了面向对象的特性之后,它的名字后面添加了一个加号,于是就成为GTK+。
 
GTK+是一个创建图形化用户界面的库,能够运行于类Unix平台、Windows平台和其他设备上。GTK+依赖于下面所列出的几个库:

    * GLib - 一个通用的工具库,并不仅仅用于创建图形用户界面。GLib定义了很多数据类型、宏、文件工具等;
    * Pango - 国际化文字绑定;
    * ATK - 提供图形用户界面交互访问技术的通用接口;
    * GdkPixbuf - 允许从图像数据或者图像文件创建像素缓冲;
    * GDK - 为不同的窗口系统提供的抽象层,提供本地图形接口和GTK+间的一个抽象,是平台相关的。如果需要向其他平台上移植GTK+,只需要重新编写GDK;
    * GTK - GTK+库,提供了各种控件。

我们对GTK+的学习仅仅为了使用GTK+,不会过多的纠缠这些库的使用。


GTK+学习:搭建环境


了解过GTK+之后,下面要进行的是环境搭建工作,以便进行GTK+的学习。环境的搭建需要分为Windows和Linux两个平台:
 
Windows平台:
在[url]http://www.gtk.org/download.html[/url]可以找到Windows(32-bit)和64-bit的版本下载,按照自己的系统是32位还是64位选择相应的版本,页面中的GTK+ individual packages是GTK+运行所必须的库,Third Party Dependencies是第三方依赖库。这样我们就能够根据需要下载相应的库文件,能够使GTK+库最小化。如果想要简单的话,页面上也提供了一个 bundle包,这是将所有库打包在一起的,可以下载这个使用。注意,bundle包并没有单列出来,而是在页面正文中给出的链接,可能需要小心找找。
 
这里我们下载bundle包,解压缩之后,可以将里面的bin文件夹添加到环境变量path里面,以便我们编译出的exe文件运行时可以找到那些dll。否则的话需要将这些dll复制到和exe同一目录下。还可以将bin里面的这些dll全部复制到C:/WINDOWS/system32文件夹下,因为即使将这些添加到系统环境变量,在IDE里面运行也是找不到dll的,复制到system32文件夹下就可以了。
 
下面使用VC6来配置编译环境。
 
首先在VC6的Tools-Options下面的Directories选择Include files,添加GTK+目录下的include文件夹以及里面的所有一级子目录,然后添加lib文件夹下的子目录中的include文件夹,这样的话一共是添加10个目录:
 
然后在Library files里面添加GTK+目录下的lib文件夹:
 
这样之后VC6就已经配置好了,VS2008之类的也类似配置。下面新建一个控制台工程(VC6)或者是空工程(VS2008),打开工程的 settings,在link选项卡下清空里面原有的Object/library modules,然后添加glib-2.0.lib gtk-win32-2.0.lib gdk-win32-2.0.lib gobject-2.0.lib gdk_pixbuf-2.0.lib gthread-2.0.lib gmodule-2.0.lib pango-1.0.lib intl.lib 几个,确定即可。这里使用的是VC6,VS2008里面也有类似的设置。
 
这样设置之后可以新建一个main.c文件,然后输入:
 
#include <gtk/gtk.h>
 
int main(int argc, char** argv)
{
        GtkWidget* window;
        gtk_init(&argc, &argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
        gtk_widget_show(window);
        gtk_main();
        return 0;
}
 
编译、链接、运行,有窗口出现,说明环境配置成功:
 
Linux平台:
首先声明,我是用的Linux版本是Ubuntu,桌面环境是gnome。前面也说过gnome就是使用GTK+编写,所以运行环境不需要另外配置了,要做的是安装开发所需要的环境。
 
刚刚安装好的Ubuntu已经默认安装了gcc,但是并没有安装所需要的头文件,我们需要手动添加:
sudo apt-get install build-essential
 
然后再安装gnome开发包:
sudo apt-get install gnome-core-devel
 
系统会自动找到所依赖的库,并一起下载下来。
 
这样安装过后使用下面的命令编译上面的代码:
gcc main.c -o main `pkg-config --cflags --libs gtk+-2.0
 
注意,这里的`是键盘上1左面的反引号,不是单引号。
 
这里不清楚KDE桌面怎样配置GTK+,可能步骤也类似,但是需要先安装GTK+的运行环境吧?
 
上面是Windows和Linux平台下GTK+的环境配置。这些步骤在我的机器上已经测试通过了。在配置好环境后,下面我们就开始新的学习了。


GTK+学习:不仅仅是Hello world

一般在学习一项新技术的时候,我最希望看到的不是那一本本厚厚的理论书籍或者编程技巧,即便没有什么技巧,我希望的是能够看到我的成果,即便只是一个小小的什么都不能做的窗口,也能满足一下我的好奇心。所以,现在我们先来写一个小程序,看看GTK+程序是怎样编写的。
 
由于上次我们已经配置好了编译环境,所以,直接打开你所喜爱的IDE或者记事本,敲下如下的代码。这里我是在Windows平台下使用VS2005编译的,有些术语在其他平台下可能会有出入,但整体是类似的。
 
#include <gtk/gtk.h>

int main(int argc, char** argv)
{
  GtkWidget* window;
  gtk_init(&argc, &argv);
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_show(window);
  gtk_main();
  return 0;
}
 
然后进行编译连接,运行之后,如果没有错误的话,将会出现一个小窗口。嗯,这就是我们用GTK+编写的界面了。
 
下面来看看这段程序。首先第一行,是引用的头文件,一般来说只要引用这个gtk.h就可以了。按照前面所述的方法引入include文件的话,就是在gtk目录下的gtk.h了。
 
然后是main函数定义,和C语言一模一样。
 
main函数中,第一句声明一个GtkWidget的指针。前面说过,GTK+是按照面向对象思想设计的,不妨把这个GtkWidget当作类吧,虽然C编译器并不这么认为。然后是gtk_init调用,这是初始化GTK+环境。写过OpenGL程序的朋友应该比较清楚,OpenGL里面也有一个类似的init函数。然后对前面声明的指针赋值。看看这个函数名字:gtk_window_new,很清楚是新建一个window指针。按照面向对象的写法就是:
        GtkWidget* window = new GtkWindow(GTK_WINDOW_TOPLEVEL);
 
怎么样?清楚很多了吧?其实这里就已经暗示出了,GtkWindow继承了GtkWidget类。这些在后面就会看出,GtkWidget其实是所有控件的父类。传递的参数是GTK_WINDOW_TOPLEVEL,指明是一个顶层的窗口。然后使用gtk_widget_show设置显示,同样把它想象成面向对象的语法就是:
        window -> show();
 
最后一句gtk_main,将我们的程序带入GTK+的事件监听循环。
 
这样,我们的程序就介绍完了。但是也许就会发现一个问题:怎么后面还有一个黑黑的控制台窗口啊?这是因为默认运行方式是Debug,换成Release看看?那个丑丑的窗口没有了吧?而且生成的二进制文件也比那个小了很多。
 
嗯,当我们按下关闭按钮时,窗口是不见了,但是程序并没有退出啊?对哦,因为我们没有添加事件监听啊,所以当关闭窗口的时候,GTK+也不知道该怎么做。所以,我们继续修改代码如下:
 
#include <gtk/gtk.h>

int main(int argc, char** argv)
{
  GtkWidget* window;
  gtk_init(&argc, &argv);
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show(window);
  gtk_main();
  return 0;
}
 
注意,我们添加了一个事件监听函数:
g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
它的意思是,对于对象window,当"destroy"时间发生时,调用gtk_main_quit函数,传给这个函数的参数是NULL。如果我们使用Java语言的事件监听写法,就是这样子的:
window.addDestroyListener(new CallbackFunc(){
    gtk_main_quit();
});
 
不过这段代码应该也是比较容易读懂的。其实这就是GTK+中添加事件监听的写法,每个控件的每个事件监听都是这样编写代码,很统一。修改完成后运行一下,点下关闭按钮:哈,程序退出了!
 
那么,我们再来修改一下程序吧:
 
#include <gtk/gtk.h>

int main(int argc, char** argv)
{
  GtkWidget* window;
  gtk_init(&argc, &argv);
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Hello world!");
  g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show(window);
  gtk_main();
  return 0;
}
 
运行一下看看?窗口标题已经换成了经典的Hello world!了。
 
读一下代码,我们添加了这么一句:
gtk_window_set_title(GTK_WINDOW(window), "Hello world!");
 
如果你能想到它的面向对象语法,就达到目的了啊:
((GtkWindow*)window) -> setTitle("Hello world!");
 
注意,因为C编译器是不理解面向对象的多态机制的,所以,GTK+使用了很多宏来进行类型转换,比如这里的GTK_WINDOW。还记得我们声明的是GtkWidget指针,需要转换成GtkWindow指针才能使用set_title函数的。同时,这个宏也有类型检测的功能,如果不能转换,是会抛出异常的。
 
好了,现在经过一步步的代码添加,我们已经了解了GTK+程序的编写过程,并且能够创建一个窗体,添加事件监听和修改控件属性——GUI编程的主体不就是这些吗?剩下的就是一些细节,和对于庞大的控件库的学习了。

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页