Gtk+/Glade编程(三)

窗口和菜单

Posted by Sun Jianjiao on March 7, 2011

  本文将http://zetcode.com/tutorials/gtktutorial/中“Menus and Toolbars in GTK+”一章中内容采用Glade进行界面设计的方法完成这一章中的例子,并且增加一些解释说明和学习体会。

一、简单的菜单

1.创建一个窗口
2.添加菜单
add menu 如上图:菜单就在“容器”中,鼠标指的地方。 这个图时已经添加了“菜单”

3.为“退出”菜单设置信号

  • 获得对象:gtk_builder_get_object
  • 信号处理:g_signal_connect

图形界面设计完了,下面编写我们的GTK+程序:

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

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

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "simple-menu.glade", NULL);

    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
    quit_menu = GTK_WIDGET(gtk_builder_get_object(builder, "imagemenuitem5"));

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(quit_menu, "activate", G_CALLBACK(gtk_main_quit), NULL);

    gtk_main();
    return 0;
}

编译:

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

执行:

1
$ ./simple-menu

add menu 开始写这个程序的时候,忘记写gtk_main()了,结果一执行就退出了,感觉添加菜单会复杂一些,在回宿舍的路上就想是吧return 0 写在gtk_main()的前面了,原来是忘记写gtk_main()了。晚上困了干什么都没效率,所以建议时刻保持充沛的精神,精力充沛的一天比熬夜的2天更有效果。

二、图片菜单和快捷键

2.1 设置菜单的图片: add menu 在“常规”中,打开“Custom label and image”,在下面有现则图片。

2.2 设置快捷键

add menu

在“公共中”设置“加速键”,就可以使用Ctrl + q 退出窗口了。

2.3 Gtk+程序: unanao@debian:~/Experiment/Programming/gui/menu-toolbars$ cat image-shortcuts.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
#include <gtk/gtk.h>

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

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "image-shortcuts.glade", NULL);

    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
    quit_menu = GTK_WIDGET(gtk_builder_get_object(builder, "quit_menu"));

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(quit_menu, "activate", G_CALLBACK(gtk_main_quit), NULL);

    gtk_main();
    return 0;
}

执行结果图:

add menu

三、复选菜单

在要添加复选菜单处,右键选择:“Edit”,如“视图”:

add menu add menu 在“视图”上右键,选择“Add child check item item”。

在窗口中添加“Status bar”

add menu

编写Gtk+代码: unanao@debian:~/Experiment/Gui/menu-toolbars$ cat check-menu.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
#include <gtk/gtk.h>

void toggle_statusbar(GtkWidget *widget, gpointer *status_bar)
{
    if (gtk_check_menu_item_get_active(widget))    
    {
        gtk_widget_show(GTK_WIDGET(status_bar));
    }
    else
    {
        gtk_widget_hide(GTK_WIDGET(status_bar));
    }
}

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

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "image-shortcuts.glade", NULL);

    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
    quit_menu = GTK_WIDGET(gtk_builder_get_object(builder, "quit_menu"));
    status_bar = GTK_WIDGET(gtk_builder_get_object(builder, "statusbar1"));
    tog_stat = GTK_WIDGET(gtk_builder_get_object(builder, "checkstatus"));

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(quit_menu), "activate", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(tog_stat), "activate", G_CALLBACK(toggle_statusbar), status_bar);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

执行结果:

add menu

四、工具条

工具条为最长用的功能提供快速访问。这里省略加窗口、垂直框和菜单。 添加工具条:
add menu

在toolbar上选择“Edit…”
add menu 选择“Hierarchy” –>”添加”,在“Edit Image” 的“保留ID”中选择需要添加的图片。

unanao@debian:~/Experiment/gui/menu-toolbars$ cat toolbar.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
/**
 * @file toolbar.c
 * @brief Simple Toolbar
 * @author unanao <sunjianjiao@gmai.com>
 * @version 0.1
 * @date 2011-02-27
 */
#include <gtk/gtk.h>

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

    gtk_init(&argc, &argv);

    
    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "toolbar.glade", NULL);

    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));    
    quit = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "quit"));

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    //Attention please, here is "clicked"
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);

    gtk_main();
    
    return 0;
}

运行结果:

add menu

这样点击红色的关闭按钮,就可以关闭这个窗口。

五、撤销 重做

与四中添加“新建”中的方法相同,添加“撤销”和“重做”按钮。 编写代码:
unanao@debian:~/Experiment/gui/menu-toolbars$ cat undo-redo.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
 * @file undo_redo.c
 * @brief Simple Toolbar
 * @author unanao <sunjianjiao@gmai.com>
 * @version 0.1
 * @date 2011-02-28
 */
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>

void undo_redo(GtkWidget *widget, gpointer item)
{
    static int count = 2;
    const char *name = gtk_widget_get_name(GTK_WIDGET(widget));
    
    if (strcmp(name, "undo") == 0)
    {
        count--;
    }
    else if (strcmp(name, "redo") == 0)
    {
        count++ ;
    }
    else
    {
        exit(1); //If the name is not "undo" and "redo" , it means that parameter is error
    }

    if (count < 0)
    {
        gtk_widget_set_sensitive(widget, FALSE);
        gtk_widget_set_sensitive(item, TRUE);        
    }
    else if (count > 5)
    {
        gtk_widget_set_sensitive(widget, FALSE);
        gtk_widget_set_sensitive(item, TRUE);        
    }

}

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

    gtk_init(&argc, &argv);

    
    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "toolbar.glade", NULL);

    window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));    
    quit = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "quit"));
    undo = (gtk_builder_get_object(builder, "undo"));
    redo = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "redo"));
    //undo = (gtk_builder_get_object(builder, "undo"));
    //redo = (gtk_builder_get_object(builder, "redo"));
    //printf below is used for debugging
    printf("undo: %s\n", gtk_widget_get_name(undo));
    printf("quit: %s\n", gtk_widget_get_name(quit));
    printf("window: %s\n", gtk_widget_get_name(window));

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    //Attention please, here is "clicked"
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(undo, "clicked", G_CALLBACK(undo_redo), redo);
    g_signal_connect(redo, "clicked", G_CALLBACK(undo_redo), undo);

    gtk_main();
    
    return 0;
}

gtk_widget_get_name存在一个bug:https://bugzilla.gnome.org/show_bug.cgi?id=614782。还没有想好解决办法。如果真的需要可以是这是用gtk+编程,而不是直接使用glade.