专注于技术 心无旁骛 - justforfan528

Linux技术| 网络编程coding | 网络安全Cyber Security | study |

 

导航

linux下gtk编程资源(转载)

from: http://blog.csdn.net/zhaoyawei/archive/2006/02/08/594629.aspx

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=kylix&Number=278523&page=0&view=collapsed&sb=5&o=&fpart=

///////////////////////**************************************///////////////////////////

http://developer.gnome.org/doc/API/glib/

//////////////////////*************************************///////////////////////

http://developer.gnome.org/doc/API/zvtterm/book1.html

/////////////////////////////*****************************//////////////////////////////////////

http://bbs.chinaunix.net/viewthread.php?tid=202464&highlight=gtk

????????????>>>>>>>>>>>>>>>>>>>>>>>>??????????

GTK (GIMP Toolkit) 是一套用于创建图形用户界面的工具包。它遵循 LGPL 许可证,所以你可以用它来开发开源软件、自由软件,甚至是封闭源代码的商业软件,而不用花费任何钱来购买许可证和使用权。

GTK 被称为 GIMP 工具包是因为最初写它是用来开发 GIMP (GNU 图像处理程序) 的,但是它现在已经被用于很多软件项目了,包括 GNOME (GNU 网络对象模型环境)。GTK 是在 GDK (GIMP Drawing Kit) 和 gdk-pixbuf 的基础上建立起来的,GDK 基本上是对访问窗口的底层函数 (在 X 窗口系统中是 Xlib) 的一层封装,gdk-pixbuf 是一个用于客户端图像处理的库。

GTK 的创建者是:


Peter Mattis petm@xcf.berkeley.edu

Spencer Kimball spencer@xcf.berkeley.edu

Josh MacDonald jmacd@xcf.berkeley.edu

GTK 的当前维护者是:


Owen Taylor otaylor@redhat.com

Tim Janik timj@gtk.org

GTK 实质上是一个面向对象的应用程序接口 (API)。尽管完全用 C 写成的,但它是基于类和回调函数 (指向函数的指针) 的思想实现的。

还有一个名为 GLib 的第三个组件,包含一些标准函数的替代函数,以及一些处理链表等数据结构的函数等。这些替代函数被用来增强GTK 的可移植性,因为它们所实现的一些函数在其它 Unix 系统上未实现或不符合标准,比如 g_strerror()。一些是对 libc 的对应函数的增强,比如 g_malloc() 具有增强的调试功能。

在 2.0 版中,GLib 又加入这样一些新内容:构成 GTK 类层次基础的类型系统 (type system),在 GTK 中广泛使用的信号系统,对各种不同平台的线程 API 进行抽象而得的一个线程 API,以及一个加载模块的工具。

作为最后一个组件,GTK 使用了 Pango 库来处理国际化文字输出。

本教程讲述 GTK 的 C 接口。还有许多其它语言的 GTK 绑定如 C++、Perl、Python、TOM、Ada95、Objective C、Free Pascal、Eiffel、Java 和 C#。如果你想使用 GTK 其它语言的绑定,请先查看该绑定的文档。有时这些文档会讲一些重要的概念,然后你再来参考本教程。还有一些跨平台的 API (如 wxWindows 和 V),它们把 GTK 作为一个支持的平台。同样,先参考它们的文档。

如果你用 C++ 来开发 GTK 应用程序,有以下几点需要注意。已有一个 GTK 的 C++ 绑定叫做 GTK-- (译者注:现在叫做 gtkmm),提供一个更符合 C++ 规范的接口,你可以先看看这个接口。如果你由于种种原因不喜欢这种方法,还有另外两种使用 GTK 的方法。首先,你可以只使用 C++ 中的 C 子集来调用 GTK,这样就可以使用本教程描述的 C 接口。其次,你可以用下述方法同时使用 GTK 和 C++:把所用的回调函数定义为 C++ 类中的静态成员函数,然后仍然使用 C 接口来调用 GTK。如果你选择后一种方法,你可以把指向要操作的对象的指针 (即所谓的 "this"作为回调函数的 data 参数。选择哪一种方法仅仅是个人的喜好问题,因为不管用哪一种方法,你都会得到 C++ 和 GTK。它们都不需要特殊的预处理程序,因此你可以同时使用标准 C++ 和 GTK

本教程试图尽可能详细地描述 GTK,但是肯定不能面面俱到。本教程假设你能够较好的理解 C 语言,并且了解怎样编写一个 C 程序。有 X 编程经验会很有帮助,但不是必要条件。如果 GTK 是你学习的第一个构件工具包,请告诉我们你怎样找到这个教程,以及学习时有什么困难。还有其它一些语言的绑定,如 C++、Objective C、ADA、Guile 等,但我不了解这些。

本教程仍在不断完善中。请到 http://www.gtk.org/ 查看更新情况。

????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>>>

应用GTK+编程
作者:宋国伟    本文选自:IBM DW中国  2003年04月18日  

  GTK+采用具有OO特色的C语言开发框架,这使它在开发GUI应用程序能和操作系统紧密结合,同时具有很大简洁性,其中的很多代码只要简单的复制和更改即可完成,只用一个C源代码文件就可以创建一个LINUX下的GUI程序。

  用GTK+写的HelloWorld:

  下面的代码是笔者用GTK+编写的一个HelloWorld例程,编译后运行显示一个带按钮的窗口,点击按钮会弹出提示信息对话框。

//hello.c
#include <gtk/gtk.h>;
//主窗口中按钮的回调函数
void        on_button_clicked(GtkWidget* button, gpointer userdata)
{
        GtkWidget *dialog;
//创建带确认按钮的对话框,父控件为空
        dialog = gtk_message_dialog_new(NULL,
                        GTK_DIALOG_MODAL |GTK_DIALOG_DESTROY_WITH_PARENT,
                        GTK_MESSAGE_INFO,
                        GTK_BUTTONS_OK,
                        (gchar*)userdata);
        gtk_dialog_run(GTK_DIALOG(dialog));//显示并运行对话框
        gtk_widget_destroy(dialog);//销毁对话框
}
//主函数
int        main(int argc, char* argv[])
{
        GtkWidget *window, *button;
        //初始化GTK+程序
        gtk_init(&argc, &argv);
        //创建窗口,并为窗口的关闭信号加回调函数以便退出
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(G_OBJECT(window),"delete_event",
                        G_CALLBACK(gtk_main_quit),NULL);
        gtk_window_set_title(GTK_WINDOW(window),"Hello World!";
        gtk_container_set_border_width(GTK_CONTAINER(window),10);
        //创建按钮控件,为单击信号加回调函数,将其放入窗口中
        button=gtk_button_new_with_label("Hello World!";
        g_signal_connect(G_OBJECT(button),"clicked",
                        G_CALLBACK(on_button_clicked),
              (gpointer)"你好!\n自由的世界。";
        gtk_container_add(GTK_CONTAINER(window),button);
        //下面函数显示窗口控件同时显示其中的所有其它控件
        gtk_widget_show_all(window);
        gtk_main();
        return FALSE;
}



  可以直接用命令"gcc `pkg-config -cflags -libs gtk+2.0` hello.c -o hello"来编译上面的代码,但最好做一个Makefile文件内容如下:

CC = gcc
all:
        $(CC) `pkg-config --cflags --libs gtk+-2.0` hello.c -o hello



  这样的话可以用make命令来编译,使得简单了许多,也不容易出错了。再次强调的是关于引号的问题,很多初学者常犯这个错误,[`]是[~]下面的那个单引号,而非['];这涉及到了LINUX SHELL编程中的命令引用,LINUX下的标准的BASH是支持命令引用的,而其它的SHELL就不一定了。

  下两图分别为程序的运行时的窗口和点击Hello World按钮弹出的对话框:





  初始化、主循环与退出

  与MS WINDOWS下用C开发GUI程序不同,GTK+不用WinMain函数,由C语言中的标准格式的main函数直接切入,这在UNIX操作系统家族中是统一的。函数gtk_init标致GTK+程序的开始,它的两个参数是main函数的两个参数的地址。在此函数之后就可以处理程序的各种相关部分,如控件的创建、显示、为控件的信号加回调函数、设定或修改控件的属性等。最后执行gtk_main函数,程序进入主事件循环,开始接收信号并为信号调用其相应用的回调函数。函数gtk_main_quit用来结束主事件循环,即退出GTK+程序的运行。

  控件的创建、显示与布局

  GTK+中的控件分为容器控件和非容器控件1,非容器控件主要是基础的GUI元素,如文字标签、图像、文字录入控件等,容器控件有多种,共同点是可以按一定方式来排放其它控件,GTK+以此形成了独特的GUI界面布局风格。GTK+控件的创建函数一般形式为:gtk_控件名_new(参数…)或gtk_控件名_new_with_参数名(参数…),它的返回值为GtkWidget型的指针,创建完成后就可以调用gtk_widget_show函数来显示或隐藏此控件,或用相关的函数来修改控件的属性。

  信号连接与回调函数

  GTK+用信号和回调函数的方式来处理来自外部的事件,控件间继承有其父控件的相同信号,不同的控件也有各自不同的信号,如按钮控件有"clicked"信号,而文字标签控件则没有此信号。GTK+2.0采用宏g_signal_connect来完成信号与回调函数的连接,这是它与GTK+1.X版的一个关键不同之处,这个宏有四个参数,第一个参数是连接信号的对象,如此例中的button或window,要用G_OBJECT宏来转换一下,即将对象的类型GtkWidget转换为GObject类型,格式一般为G_OBJECT(button);第二个参数为字符串格式的信号名;第三个参数为回调函数名,用G_CALLBACK宏来转换一下;第四个参数为要传给回调函数的参数的指针。如上例中为按钮的"clicked"的信号加的回调函数"on_button_clicked":

g_signal_connect(G_OBJECT(button),"clicked",
        G_CALLBACK(on_button_clicked),(gpointer)"你好!\n自由的世界。";



  细心的读者马上会看到此宏的一个缺点,即只能为回调函数传递一个参数,当然聪明的读者马上也会想到采用结构类型来传递多个参数。上面的内容对初学者似乎复杂了些,只要过了这个门槛,事实上就步入了GTK+的世界。

  国际化编程

  gettext软件包

  上面的程序运行是主窗口显示为英文,我们完全可以将其改为中文,这样单一的语言版本不适于应用的国际化,GTK+中用gettext软件包来实现国际化,使这一问题变得非常简单。gettext软件包是GNU工程中解决国际化问题的重要工具,目前版本是0.11.x,支持C/C++和JAVA语言,它在开源界应用相当广泛,GNOME/GTK+的国际化问题都是用它来解决的,正常的情况下GNU/LINUX系统是默认安装这一软件包的。

  代码实现

  首先是在源代码中加入相关的C语言头文件如下:

#include <libintl.h>;                //gettext支持
#include <locale.h>;                //locale支持



  然后是定义宏,下面的定义形式在GNOME/GTK+中应用的标准格式:

#define PACKAGE "hello"        //软件包名
#define LOCALEDIR "./locale" //locale所在目录
#define _(string)        gettext(string)
#define N_(string)        string



  在程序的主函数中加入下面相关函数:

bindtextdomain(PACKAGE,LOCALEDIR);
        //以上函数用来设定国际化翻译包所在位置
        textdomain(PACKAGE);
        //以上函数用来设定国际化翻译包名称,省略了.mo



  相关的字符串修改

  将代码中需要国际化--即多语言输出的字符串改写为_()宏,代码如下:

gtk_window_set_title(GTK_WINDOW(window),_("Hello World!");
        ... ...
        button=gtk_button_new_with_label(_("Hello World!");
        g_signal_connect(G_OBJECT(button),"clicked",
                        G_CALLBACK(on_button_clicked),
                (gpointer)(_("Hello, the Free World!"));
... ...



  生成相关文件与翻译

  完成以上修改后,执行如下命令:xgettext -k_ -o hello.po hello.c,它的功能是将hello.c中的以下划线开始括号中(如宏定义所示)的字符串加入到hello.po文件中。po文件的头部可以加入软件包的名称、版本、翻译者的邮件地址等,po文件中以#开始的行为注释内容,以下为省略了头部的hello.po文件内容,msgid后面的内容为英文,msgstr后面的内容为翻译的中文,翻译好后保存为UTF8格式。

#: hello.c:26 hello.c:29
msgid "Hello World!"
msgstr "你好世界!"

#: hello.c:31
msgid "Hello, the Free World!"
msgstr "你好,自由的世界!"



  下一步执行命令:msgfmt -o hello.mo hello.po将 hello.po文件格式化为hello.mo文件,这样程序在运行时就能根据当前locale的设定来正确读取mo文件中的数据,从而显示关语言的信息了。关于.mo文件的位置,本程序设在./locale目录下的中文目录zh_CN下的LC_MESSAGES目录下,即./locale/zh_CN/LC_MESSAGES 目录下,在REDHAT中默认的目录是/usr/share/locale。将此步骤生成的mo文件复制到相应的目录下,将locale设为简体中文,再运行此程序,测试结果就变为中文了(如下图),如locale设为英文则显示仍为上面的英文信息。



  自动生成Makefile与打包

  自动生成Makefile文件是很多LINUX编程爱好者的愿望,事实上只要你运用好AUTOCONF和AUTOMAKE这两个工具,就会很容易的生成Makefile文件,并能实现打包(生成*.tar.gz格式的源代码包)功能。与这两个工具相关的配置文件分别是configure.in和Makefile.am。只要我们弄懂这两个文件的格式和相关的宏,就完全可以了。

  操作过程

  前提是做好相应的目录和源程序文件,如本例中在hello目录中的hello.c等。

  1、首先执行autoscan命令,生成configure.scan文件;

  2、执行mv configure.scan configure.in,将其改名;

  3、编辑configure.in,在AC_INIT(hello.c)之后加入一行,AM_INIT_AUTOMAKE(hello,1.0)表示软件包名为hello,版本为1.0,如此在make编译后,执行make dist会生成一个名为 hello-1.0.tar.gz源代码包,这样是比较附合GNU开源标准的格式。在最后一行AC_OUTPUT()的括号中加入Makefile,表示输出Makefile文件(configure.in文件中还有许多宏定义,详细用法可以参考autobook一书),至此编辑configure.in文件结束;

  4、执行aclocal命令,生成aclocal.m4宏文件;

  5、执行autoconf命令,生成configure shell可执行脚本;

  6、编辑Makefile.am文件,内容如下:

   AUTOMAKE_OPTIONS = foreign
INCLUDES = `pkg-config --cflags gtk+-2.0`
LIBS = `pkg-config --libs gtk+-2.0`
bin_PROGRAMS = hello
hello_SOURCES = hello.c



  说明:第一行为AUTOMAKE命令的参数,表示为外部的,不按GNU标准(即不加说明、安装、更改记录等文件) ;第二行表示包含文件的目录;第三行表示动态链接库的目录和所要链接的库;第四行表示输出的可执行文件名;最后一行表示可执行文件的源程序文件,可以有多个文件名。

  7、执行命令automake --add-missing -copy,表示创建Makefile.in文件并加入遗失的文件,同时复制过来(默认情况下是做符号链接,这在不同的文件系统间会出问题),至此操作完成。

  编译、测试、安装与打包

  执行./configure 生成Makefile;执行make编译;执行./hello运行此程序;执行make install来安装,默认情况下是将可执行文件hello复制到/usr/local/bin目录下;执行make dist会在当前目录下生成hello-1.0.tar.gz源代码包,如此就可以将你的源代码包向外界发布了。

  使用线程

  在GTK+中应用线程, 除了GLIB中的g_thread_init和g_thread_supported两个函数外,还要用到gdk_thread_init来在X WINDOW中初始化线程应用,另外在线程中要对GTK+控件进行操作时还要在操作前执行函数gdk_thread_enter来进入,操作完成后执行函数gdk_thread_leave来离开,在执行GTK+主循环时也是如此,GTK+以此来达到线程安全;下面代码利用线程创建了一个在屏幕上沿顺时针运动的图像(24x24像素):

//thread.c
#include <gtk/gtk.h>;

typedef struct _Ourarg Ourarg;
struct _Ourarg {
        GtkWidget *fixed;
        GtkWidget *image;
        gint right;
        gint left;
};

void        image_go(Ourarg *arg)
{
        gint x, y, toward;
        x = y = arg->;left;
        toward = 1;

        for(;
        {
                g_usleep(1500);
                gdk_threads_enter();
                gtk_fixed_move(GTK_FIXED(arg->;fixed),arg->;image, x, y);
                switch(toward)
                {
                case 1:
                        x = x + 10;
                        if( x >; arg->;right ) toward = 2;
                        break;
                case 2:
                        y = y + 10;
                        if( y >; arg->;right ) toward = 3;
                        break;
                case 3:
                        x = x - 10;
                        if( x < arg->;left ) toward = 4;
                        break;
                case 4:
                        y = y -10;
                        if( y < arg->;left ) toward = 1;
                }
                gdk_threads_leave();
        }
}


int        main(int argc, char* argv[])
{
        GtkWidget *window;
        GtkWidget *vbox, *viewport, *button;
        GtkWidget *image, *fixed;
        Ourarg *arg;

        if(!g_thread_supported()) g_thread_init(NULL);
        gdk_threads_init();

        gtk_init(&argc,&argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window),"线程测试";
        g_signal_connect(G_OBJECT(window),"delete_event",
                        G_CALLBACK(gtk_main_quit),NULL);
        gtk_container_set_border_width(GTK_CONTAINER(window),2);

        vbox = gtk_vbox_new(FALSE,0);
        gtk_container_add(GTK_CONTAINER(window),vbox);

        fixed = gtk_fixed_new();
        gtk_widget_set_usize(fixed,340,340);
        viewport = gtk_viewport_new(NULL,NULL);
        gtk_box_pack_start(GTK_BOX(vbox),viewport,FALSE,FALSE,5);
        gtk_container_add(GTK_CONTAINER(viewport),fixed);

        image = gtk_image_new_from_file("ss.png";
        gtk_fixed_put(GTK_FIXED(fixed),image,40,40);

        button = gtk_button_new_with_label("退出");
        gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,5);
        g_signal_connect(G_OBJECT(button),"clicked",
                        G_CALLBACK(gtk_main_quit),NULL);

        gtk_widget_show_all(window);

        arg = g_new(Ourarg,1);
        arg->;fixed = fixed;
        arg->;image = image;
        arg->;left = 40;
        arg->;right = 260;
        g_thread_create(image_go, arg, FALSE, NULL);

        gdk_threads_enter();
        gtk_main();
        gdk_threads_leave();
        return FALSE;
}



  基于线程安全考虑,你必须将下面代码放在gtk_init函数之前执行:

if(!g_thread_supported()) g_thread_init(NULL);
        gdk_threads_init();



  线程中执行一个死循环,不停的移动GtkFixed控件中的图像控件,根据图像的位置来改变方向。



  (此图像做得很不好,只是为了证明程序的测试结果是可以正常运行的,完全可以删除)

  结束语

  学习GTK+的最好的方法是研究GTK+源码包中带的例程和研究其它应用GTK+的开源软件的源码包,在国内最大LINUX论坛上有很多这方面的高手。

  如果你的英文足够好的话还可以订阅GTK+应用开发的邮件列表,这样你每天都可以收到几封关于GTK+开发的邮件,笔者最多时一天收到过近30封邮件,其中有很多人会热心的回答你的问题或帮你出主意。

  在QT和GTK+的选择上,经常能看到一些网友的争论。对于目前国内LINUX平台上的GUI应用程序的开发,搁置争议、潜心学习、交流心得、形成合力、做出具有应用前景和自己特色的开源项目才是自由社区的当务之急。

  注1:可以参考IBM developerWorks网站上的文章《GTK+2.0中的容器控件和布局技巧》

  关于作者

  宋国伟,乡村小学英语教师,他是《GTK+2.0编程范例》(清华大学出版社出版)一书的作者,业余时间致力于用GTK+开发LINUX GUI应用程序,可以通过电子邮件地址gwsong_52@sohu.com与他联系。

posted on 2007-10-10 11:42  游荡者  阅读(2220)  评论(0编辑  收藏  举报