Gtk+/Glade编程(二)

入门

Posted by Sun Jianjiao on January 18, 2011

  本文将http://zetcode.com/tutorials/gtktutorial/中“Firs tporgrams”一章中内容采用Glade进行界面设计的方法完成“First porgrams”的例子,并且增加一些解释说明。 由于“Simple example”已经在《Gtk+/Glade编程(一)》中实现,这里就不再进行实现。

一、将窗口放置在屏幕中间

主要是窗口属性的设置,在右下角处的“属性”里面进行设置: Window Center

  这样可以从右下角看到窗口对象的名称被设为:“Center”, 窗口的标题被设为“Center”, 长度为:230, 高度:150。保存并且命名为”center.glade”。

代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    GtkBuilder *builder;
    GtkWidget *window;

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "center.glade", NULL);
    window = GTK_WIDGET(gtk_builder_get_object(builder, "center"));

    //用于关闭窗口,也可以在属性的信号中进行设置
    g_signal_connect(GTK_WINDOW(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show(window);

    g_object_unref(builder);

    gtk_main();

    return 0;
}

编译:

1
    $gcc -o center center.c `pkg-config --cflags --libs gtk+-2.0`

执行:

1
    $./center

Window center show

点击关闭按钮可以正常关闭。

如果不使用Glade进行界面设计及生成,生成窗口并且设置属性的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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), "center"); //title is "window"
    gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    gtk_widget_show(window);

    gtk_main();    

    return 0;
}

对比可知:
创建一个组件, 使用Gtk+

  • 需要new一个组件
  • 通过set进行属性设置
    使用Glade/Gtk+
  • 需要在点击生成窗口,
  • 通过属性设置栏进行属性设置 利用GtkBuilder将生成的xml文件加入进来即可   虽然感觉Glade/Gtk+的步骤更多,但是并没有直接使用Gtk+繁琐,尤其是Glade可以设计所见即所得的界面,使得编码更加方便,更加高效!

二、应用程序的图标

只需“常规”的设置中,找到“图标”,选择需要设置为图标的图片即可,如下图: Logo

其他的设置没有改变,Gtk+的代码与“一、将窗口放置在屏幕中间”的代码相同(如果保存的xml的名字进行了改动,需要修改Gtk+中gtk_builder_add_from_file的文件名) 运行结果截图: Logo 左上角出现了我们加入的图标,比上面的图都是“X”漂亮多了!^_^

三、加 - 减

3个子组件,1个“标签”, 2个“按钮” “标签” –>显示一个整数 “+” , “-”—> 增加 或减小标签上的数字。 首先设计界面: 在“顶层”中选 “窗口” 在“容器”中选 “固定的” –用于固定按钮和标签,不然加入这些组件的任何一个都会充满整个“窗口” 在控制和显示中选“按钮” 和 “标签” (标签是黑色的,不带下划线的“Label”)

然后点击 菜单栏最右边的“拖拽并调整工作区部件的大小”,调整“按钮”和“标签的”大小及位置。 设置各个组件的属性: 设置按钮的标签: Logo

设置标签的属性: Logo

最后是Gtk+编程:
unanao@debian:~/gui/first-programs$ cat dec_inc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <gtk/gtk.h>

gint count = 0;
gchar buf[6];

void increase(GtkWidget *widget, GtkLabel *label)
{
    count++;
    sprintf(buf, "%d", count);
    gtk_label_set_text(label, buf);
}

void decrease(GtkWidget *widget,  GtkLabel *label)
{
    count--;
    sprintf(buf, "%d", count);
    gtk_label_set_text(label, buf);
}

int main(int argc, char *argv[])
{
    GtkBuilder *builder;
    GtkWidget *window;
    GtkWidget *plus;
    GtkWidget *minus;
    GtkWidget *result;

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "dec_inc.glade", NULL);
    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
    plus = GTK_WIDGET(gtk_builder_get_object(builder, "plus"));
    minus = GTK_WIDGET(gtk_builder_get_object(builder, "minus"));
    result = GTK_WIDGET(gtk_builder_get_object(builder, "label"));

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(plus, "clicked", G_CALLBACK(increase), result);
    g_signal_connect(minus, "clicked", G_CALLBACK(decrease), result);

    gtk_main();

    return 0;
}

编译:

1
gcc -o dec_inc dec_inc.c `pkg-config --cflags --libs gtk+-2.0`

执行:

1
./dec_inc

Logo 通过点击“+”和“-”就可以改变右边数字的值了。

四、信号和回调函数

  注意这里的回调函数和普通的函数不一样,虽然g_signal_connect只传了一个参数,但是回调函数是两个函数,我开始感觉这个例子写的够笨的, 本来传了一个参数, 回调函数居然写了两个参数, 我就去掉了一个参数, 结果执行结果会报错说传入的参数不是“标签”。

  要使一个按钮执行一个动作,我们需设置信号和信号处理函数之间的连接。可以这 样使用函数来设置连接:

1
2
gulong g_signal_connect(gpointer *object, const gchar *name,
                        GCallback func, gpointer func_data);

第一个参数是要发出信号的构件,第二个参数是你想要连接的信号的名称,第三个 参数是信号被捕获时所要调用的函数,第四个参数是你想传递给这个函数的数据。

第三个参数指定的函数叫做回调函数:

1
void callback_func(GtkWidget *widget, gpointer callback_data); 

第一个参数是一个指向发出信号的构件的指针,第二个参数是一个指向数据的指针 ,就是 g_signal_connect() 函数的最后一个参数。

注意上面回调函数的声明是一种常用的形式,有些构件的特殊信号会用不同的调用 参数。

另一个调用在形式 helloworld 程序中使用,是:

1
2
3
4
gulong g_signal_connect_swapped(gpointer *object,
                                const gchar *name,
                                GCallback func,
                                gpointer *slot_object);

g_signal_connect_swapped() 和 g_signal_connect() 相同,只是回调函数只用 一个参数,一个指向 GTK 对象的指针。所以当使用这个函数连接信号时,回调函 数应该是这样的形式

1
void callback_func(GtkObject *object);

这个对象常是一个构件。然而我们通常不用函数 g_signal_connect_swapped() 设 置连接。它们常被用在只接受一个单独的构件或者对象的回调函数中作为参数,如 同我们的 helloworld 示例中那样。

拥有两个设置信号连接函数的目的是简单的允许回调函数有不同数目的参数。 GTK 库中许多函数仅接受一个单独的构件指针作为其参数,所以对于这些函数你要 用 g_signal_connect_swapped(),然而对你自己定义的函数,你需要附加的数据 提供给你的回调函数。