Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1114063
  • 博文数量: 309
  • 博客积分: 6093
  • 博客等级: 准将
  • 技术积分: 3038
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-03 17:14
个人简介

linux学习记录

文章分类

全部博文(309)

文章存档

2014年(2)

2012年(37)

2011年(41)

2010年(87)

2009年(54)

2008年(88)

分类:

2008-09-22 13:37:11

●GTK 简单编程
下面的例子是一个GTK最基本例子,它仅仅在屏幕上弹出一个窗口,并且 即使关闭该窗口,该程序仍未退出。

/* File: base.c */

#include

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_init(&argc, &argv) 是gtk应用程序的初始化部分,它使gtk 应用程序可以接受某些命令行的参量:
   --gtk-module   //载入另外的GTK模块
   --g-fatal-warnings //使所有警告是致命错误
   --gtk-debug   //调试gtk
   --gtk-no-debug   //不调试gtk
   --gdk-debug   //调试gdk
   --gdk-no-debug   //不调试gdk
   --display   //指定display
   --sync    //使X调用按顺序方式
   --no-xshm   //不使用X共享内存
   --name    //指定窗口管理器使用的程序名
   --class    //指定窗口管理器使用的程序类型

其中
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_widget_show (window);

建立顶级窗口并且显示该窗口,它在缺省情况下是200x200大小。
最后 gtk_main() 使程序进入事件循环阶段,gtk将在内部处理事件。

现在让我们编译文件 base.c:

   gcc -Wall -g base.c -o base \
    `gtk-config --cflags`   `gtk-config --libs`

其中 `gtk-config --cflags` 产生编译gtk所使用的头文件位置, `gtk-config --libs` 产生连接gtk程序所使用的库。一般地,涉及 gtk的库有: libgtk.so libgdk.so libgmodule.so libglib.so。
接下来把上面的例子变成一个稍微复杂的例子,该例子弹出一个 窗口,并且在窗口中显示一个按钮。

/* File: helloworld.c */

#include

void hello( GtkWidget *widget, gpointer    data )
{
   g_print ("Hello World\n");
}

gint delete_event( GtkWidget *widget,
                     GdkEvent   *event,
                     gpointer    data )
{
   //打印信息
   g_print ("delete event occurred\n");

   //如果返回FALSE,GTK将发出"destroy"信号; 如果返回TRUE,
   //则不让该窗口关闭
   return(TRUE);
}

void destroy( GtkWidget *widget, gpointer    data )
{
   gtk_main_quit();
}

int main( int    argc, char *argv[] )
{
   //GtkWidget 是 Widget的类型
   GtkWidget *window;
   GtkWidget *button;
     
   //gtk 初始化
   gtk_init(&argc, &argv);
     
   //建立新窗口
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
     
   //当使用窗口管理器关闭窗口时,将调用 delete_event() 函数
   //本例中所传递的参数是 NULL
   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
    GTK_SIGNAL_FUNC (delete_event), NULL);
     
   //把 "destroy" 事件和信号处理器联系起来
   gtk_signal_connect (GTK_OBJECT (window), "destroy",
    GTK_SIGNAL_FUNC (destroy), NULL);
     
   //设置窗口的边界宽度
   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
     
   //建立一个标签是"Hello World"的按钮
   button = gtk_button_new_with_label ("Hello World");
     
   //当按钮被单击时,即接收到"clicked"信号,将调用 hello()函数
   gtk_signal_connect (GTK_OBJECT (button), "clicked",
    GTK_SIGNAL_FUNC (hello), NULL);

   //当按钮被单击时,调用 gtk_widget_destroy(window)关闭窗口。
   //这里将引发 "destroy" 信号
   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
    GTK_SIGNAL_FUNC (gtk_widget_destroy),
    GTK_OBJECT (window));
     
   //把按钮加入顶级窗口中
   gtk_container_add (GTK_CONTAINER (window), button);

   //显示按钮
   gtk_widget_show (button);
     
   //显示顶级窗口
   gtk_widget_show (window);

   //进入事件循环
   gtk_main ();
     
   return(0);
}


编译连接 helloworld.c,执行结果为:


下面总结一下,编写GTK程序的基本步骤:


初始化
创建主窗口
创建并加入子窗口
设置组件回调
显示窗口
进入事件循环

●GTK中文程序示例
上面的例子是英文编程的基本例子,如果在程序中使用中文,还应当 对上面的例子作适当的修改。当然最基本的要求还是Linux系统必须有 一个正确的国际化环境,具体地说就是:


系统支持中文C Locale
系统支持中文X Locale
GTK的资源文件/etc/gtk/gtkrc.zh_CN设置正确
对于上面的几个要求,可以参阅本书的国际化编程部分。
下面是一个典型的 gtkrc.zh_CN文件,其中指定的缺省字体是14点阵 字体。

# $(gtkconfigdir)/gtkrc.zh_CN
#
# This file defines the fontsets for Chinese language (zh) using
# the simplified chinese standard GuoBiao as in mainland China (CN)
#
# 1999, Pablo Saratxaga <>
#

style "gtk-default-zh-cn" {
          fontset = "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-iso8859-*,\
     -cclib-song-medium-r-normal--14-*-*-*-*-*-gbk-0"
}
class "GtkWidget" style "gtk-default-zh-cn"

使上述程序支持中文非常简单,只需要在初始化gtk之前调用locale设置函数:
                 //设置Locale
                 gtk_set_locale();

                 //gtk 初始化
                 gtk_init(&argc, &argv);

把按钮的标签改为中文即可:
                 //建立一个含中文标签的按钮
                 button = gtk_button_new_with_label ("大家好!");

程序运行的结果是:


如果不想用缺省的资源文件中所指定的字体,也可以在程序中指定 资源文件或直接把fontset写在程序中。 指定资源文件使用函数 gtk_rc_parse(filename),直接使用fontset使用函数 gtk_rc_parse_string (gtkrc_string)。


●实例详细剖析
上面的例子中,我们遇到了许多新的数据类型和回调的方式等,下面 一一剖析:


包含的头文件:
如果程序只涉及到gtk部分,而不是直接调用gdk的函数,只须包含 gtk/gtk.h,如涉及到gdk部分,应包含gdk/gdk.h


数据类型:
glib 中定义了许多数据类型如 gpointer,gint等等,它们都是比较 容易理解的。对GTK的组件(GtkWidget),类型都是GtkWidget,它包含了一个 窗口组件所需要的信息。GdkEvent 则封装了X事件的信息。


信号和回调
信号(Signal)是GTK中出现的新的并且比较重要的概念。这里讲的"信号" 不同于UNIX的signal,只是名称一样。当处理X事件时,如鼠标按键按下, GTK的组件接收到这一事件,便发出响应的信号。不同的组件相关信号 可能不一样。

在上述例子中使用函数
   gint gtk_signal_connect( GtkObject      *object,
                           gchar          *name,
                           GtkSignalFunc   func,
                           gpointer        func_data );

把组件 object 与回调函数 func 联系起来,name 是所发出的信号的 名称。func_data 是传递给回调函数的参数。
回调函数的格式是

   void callback_func( GtkWidget *widget,
                      gpointer    callback_data );

其中 widget 是发出信号的组件,callback_data 是传递参数的指针。
在上例中还使用了另外一套类似的函数:

   gint gtk_signal_connect_object( GtkObject      *object,
                                  gchar          *name,
                                  GtkSignalFunc   func,
                                  GtkObject      *slot_object );
   void callback_func( GtkObject *object );

它们与第一套函数的区别是回调函数只使用一个参量。

GTK 的事件:
gtk组件的行为或X服务器发送的事件可以和下列事件联系起来


       button_press_event   //按钮按下
       button_release_event //按钮释放
       motion_notify_event //鼠标移动
       delete_event   //使用窗口管理器关闭
       destroy_event   //关闭
       expose_event   //曝光
       key_press_event   //按键按下
       key_release_event   //按键释放
       enter_notify_event   //鼠标指针进入组件
       leave_notify_event   //鼠标指针离开组件
       configure_event   //属性改变
       focus_in_event   //获得聚焦
       focus_out_event   //失去聚焦
       map_event    //映射
       unmap_event   //消失
       property_notify_event //属性改变
       selection_clear_event //选择清除
       selection_request_event //选择请求
       selection_notify_event //选择通知
       proximity_in_event   //接近
       proximity_out_event //离开
       drag_begin_event   //拖开始
       drag_request_event   //拖请求
       drag_end_event   //拖结束
       drop_enter_event   //放进入
       drop_leave_event   //放离开
       drop_data_available_event //放数据可用


上例中在窗口管理器中关闭窗口失效(它的好处是给用户一个重新确认的机会),原因是函数
   gint delete_event( GtkWidget *widget,
                     GdkEvent   *event,
                     gpointer    data )

返回 TRUE,这样 GTK 组件不会发出 "destroy" 信号。
当按钮按下时,调用函数
   void destroy( GtkWidget *widget, gpointer    data )
   {
    gtk_main_quit();
   }

这样在主程序中的 gtk_main()便退出循环,程序随之结束。
函数gtk_init (&argc, &argv)初始化GTK程序并传递响应的命令行参数给 GTK,当参数符合时,便从列表中清除,剩下的参数再由用户处理
语句 window = gtk_window_new (GTK_WINDOW_TOPLEVEL) 创建顶级窗口, 参量的意义是:
   GTK_WINDOW_TOPLEVEL: 顶级窗口
   GTK_WINDOW_DIALOG:    对话框窗口
   GTK_WINDOW_POPUP:     弹出式窗口,不受窗口管理器管理,即
          无边界窗口

语句 gtk_container_set_border_width (GTK_CONTAINER (window), 10) 把窗口的内边界宽度设置为10。
语句 gtk_container_add (GTK_CONTAINER (window), button) 把刚建立 的按钮组件加入到 window 中。请注意这里在使用 window 时把它投影 成GTK_CONTAINER,在以后的GTK编程中会经常遇到类似的投影。
语句 gtk_widget_show (window); 表示已经设置完窗口的属性,可以显示 了。
事件循环 gtk_main(),由 GTK 内部处理
阅读(2406) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~