GTK 菜单控件

菜单控件

创建菜单栏和子菜单时要用到三种构件:
• 一个菜单项(menu item),就是用户要选择的东西,比如,"Save"
• 一个菜单(menu),作为菜单项的容器。
• 一个菜单栏(menubar),是各个单独菜单的容器。

下面是创建菜单控件的一般步骤:

• 用 gtk_menu_new() 创建一个新的菜单
• 多次调用 gtk_menu_item_new() 创建每个你想在你的菜单上出现的菜单项。并使用 gtk_menu_append() 将每个新的菜单项放到
菜单上。
• 用 gtk_menu_item_new() 创建一个菜单项。这将是菜单的根(root),上面显示的文本将自己出现在菜单栏上。
• 用 gtk_menu_item_set_submenu() 将菜单绑定到根菜单项(就是上一步创建的那个)。
• 用 gtk_menu_bar_new 创建一个新的菜单栏。在一个菜单栏上创建一系列菜单时这步只要做一次就行了。
• 用 gtk_menu_bar_append() 将根菜单项放到菜单栏上。


创建一个弹出菜单和上面的几乎是一样,只是在设置回调函数时,如下:

  1. g_signal_connect_swapped (G_OBJECT (widget), "event",  
  2.                               G_CALLBACK (handler),  
  3.                               G_OBJECT (menu));  

其中widget是你要绑定到的构件,handler是处理函数,而menu是一个用 gtk_menu_new() 创建的菜单。它可以是一个也被菜单栏弹出的菜单。

看下面具体的例子:

 

  1. /*File:menu_item.c 
  2.  *Date:2013-11-23 
  3.  *Author:sjin 
  4.  *Mail:413977243@qq.com 
  5.  */  
  6.   
  7. #include <gtk/gtk.h>  
  8. #include <stdio.h>  
  9.   
  10. static void menuitem_response(gchar *string)  
  11. {  
  12.     printf("%s\n",string);  
  13. }  
  14.   
  15. static int button_press(GtkWidget *widget,GdkEvent *event)  
  16. {  
  17.     if(event->type == GDK_BUTTON_PRESS){  
  18.         GdkEventButton *bevent = (GdkEventButton *)event;  
  19.         gtk_menu_popup(GTK_MENU(widget),NULL,NULL,NULL,NULL,bevent->button,bevent->time);  
  20.         /*告诉调用代码我们已经处理这个事件,*/  
  21.         return TRUE;  
  22.     }  
  23.     /*else  未处理*/  
  24.     return FALSE;  
  25. }  
  26.   
  27. gint delete_event( GtkWidget *widget,GdkEvent  *event,gpointer   data )  
  28. {  
  29.     /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 
  30.      * 返回 TRUE,你不希望关闭窗口。 
  31.      * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/  
  32.     g_print ("delete event occurred\n");  
  33.     /* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/  
  34.     return FALSE;  
  35. }  
  36. /* 另一个回调函数 */  
  37. void destroy( GtkWidget *widget,gpointer   data )  
  38. {  
  39.     gtk_main_quit ();  
  40. }  
  41. int main( int   argc, char *argv[] )  
  42. {  
  43.     /* GtkWidget 是构件的存储类型 */  
  44.     GtkWidget *window;  
  45.     GtkWidget *menu;  
  46.     GtkWidget *menu_bar;  
  47.     GtkWidget *root_menu;  
  48.     GtkWidget *menu_items;  
  49.     GtkWidget *vbox;  
  50.     GtkWidget *button;  
  51.     char buf[128];  
  52.     int i;  
  53.       
  54.     /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/  
  55.     gtk_init (&argc, &argv);  
  56.         /* 创建一个新窗口 */  
  57.     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);  
  58.   
  59.     /*设置窗口标题*/  
  60.     gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!");  
  61.       
  62.     /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” 
  63.      * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。 
  64.      * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/  
  65.     g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL);  
  66.       
  67.     /* 在这里我们连接 "destroy" 事件到一个信号处理函数。   
  68.      * 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值 
  69.      * 都会触发这个事件。*/  
  70.     g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL);  
  71.       
  72.     /* 设置窗口边框的宽度。*/  
  73.     gtk_container_set_border_width (GTK_CONTAINER (window), 10);  
  74.       
  75.    /*创建窗口宽度*/  
  76.     gtk_widget_set_size_request(GTK_WIDGET(window),200,100);  
  77.   
  78.     /*********************** 
  79.      * 初始化菜单构件 
  80.      * 记住这里永远不要用gtk_widget_show()函数来显示菜单控件 
  81.      * 这个是包含菜单项的菜单,运行程序时点击会弹出来 
  82.      **********************/  
  83.     menu = gtk_menu_new();  
  84.   
  85.     /*****************×××××××××× 
  86.      * 
  87.      * 
  88.      * *********************/  
  89.     for(i = 0; i < 3; i++){  
  90.         /*将名称复制到buf*/  
  91.         sprintf(buf,"undetmenu-%d",i);  
  92.   
  93.         /*创建一个菜单项*/  
  94.         menu_items = gtk_menu_item_new_with_label(buf);  
  95.   
  96.         /*将它添加到菜单*/  
  97.         gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_items);  
  98.   
  99.         /*当菜单被选中时的回调函数*/  
  100.         g_signal_connect_swapped(G_OBJECT(menu_items),"activate",G_CALLBACK(menuitem_response),g_strdup(buf));  
  101.   
  102.         /*显示构件*/  
  103.         gtk_widget_show(menu_items);  
  104.     }  
  105.   
  106.     /******************************* 
  107.      *这个是根菜单,将成为现实在菜单栏上的标签 
  108.      *这里不会附上信号处理函数,因为它只是在被按下时弹出的其余的菜单 
  109.      *******************************/  
  110.   
  111.     root_menu = gtk_menu_item_new_with_label("根菜单");  
  112.     gtk_widget_show(root_menu);  
  113.   
  114.     /**************************** 
  115.      *指定想要穿件的menu成为根菜单 
  116.      ***************************/  
  117.   
  118.     gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),menu);  
  119.   
  120.     /*将一个菜单和一个按钮放到纵向盒子里面*/  
  121.     vbox = gtk_vbox_new(FALSE,0);  
  122.     gtk_container_add(GTK_CONTAINER(window),vbox);  
  123.     gtk_widget_show(vbox);  
  124.   
  125.     /******************************** 
  126.      *创建一个菜单栏,并添加到主窗口 
  127.      * *****************************/  
  128.     menu_bar = gtk_menu_bar_new();  
  129.     gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,FALSE,2);  
  130.     gtk_widget_show(menu_bar);  
  131.   
  132.     button = gtk_button_new_with_label("点击");  
  133.     g_signal_connect_swapped(G_OBJECT(button),"event",G_CALLBACK(button_press),menu);  
  134.     gtk_box_pack_end(GTK_BOX(vbox),button,TRUE,TRUE,2);  
  135.     gtk_widget_show(button);  
  136.   
  137.     /************************** 
  138.      *最后把惨淡想添加到菜单栏上 
  139.      * ***************************/  
  140.     gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu);  
  141.   
  142.     gtk_widget_show(window);  
  143.     gtk_main ();  
  144.     return 0;  
  145. }  

下面是利用gtk_item_factory来实现菜单选项:

  1. /******************************* 
  2.  *使用套件生成菜单方式 
  3.  *gtk_item_factory 
  4.  **********************/  
  5.   
  6. /*File:menu_item2.c 
  7.  *Date:2014-03-23 
  8.  *Author:sjin 
  9.  *Mail:413977243@qq.com 
  10.  */  
  11.   
  12.   
  13. #include <gtk/gtk.h>  
  14. #include <stdio.h>  
  15.   
  16. /*必要的回调函数*/  
  17. static void print_hello(GtkWidget *w,gpointer data)  
  18. {  
  19.     g_message("Hello,World!\n");  
  20. }  
  21.   
  22. /**************************************** 
  23.  * 这是用来生成新惨淡的GtkItemFactoryEntry结构 
  24.  * 第一项 菜单路径 下划线后字母指出惨淡打开的快捷键 
  25.  * 第二项:这个条目的快捷键 
  26.  * 第三项:回调函数 
  27.  * 第四项,回调动作 
  28.  * 第五项:项类型用 
  29.  *         NULL   -> "Item" 
  30.  *         ""        "Item" 
  31.  *         "<Title>"  标题 
  32.  *         "<Item>"   创建一个简单的项 
  33.  *         "<CheckItem>" 创建一个检查项 
  34.  *         "<ToggleItem>" 创建一个开关项 
  35.  *         "<RadioItem>" 创建一个选择项 
  36.  *         <path>     选择项链接到的路径 
  37.  *         "<Separator>" 分割线 
  38.  *         "Branch"    创建一个包含子项的项 
  39.  *         "LastBranch" 创建一个右对齐的分支 
  40.  *************************************/  
  41.   
  42. static GtkItemFactoryEntry menu_items[] = {  
  43.     {"/_File", NULL, NULL,0,"<Branch>"},  
  44.     {"/File/_New""<control>N", print_hello,0,NULL},  
  45.     {"/File/_Open""<control>O", print_hello,0,NULL},  
  46.     {"/File/_Save""<control>S" ,print_hello,0,NULL},  
  47.     {"/File/Save _As", NULL,NULL,0,NULL},  
  48.     {"/File/sepl", NULL,NULL,0,"<Separator>"},  
  49.     {"/File/Quit""<control>Q", gtk_main_quit,0,NULL},  
  50.     {"/_Options", NULL,NULL,0,"<Branch>"},  
  51.     {"/Options/Test", NULL,NULL,0,NULL},  
  52.     {"/_Help", NULL,NULL,0,"<LastBranch>"},  
  53.     {"/Help/About", NULL,NULL,0,NULL},  
  54. };  
  55.   
  56.   
  57. void get_main_menu(GtkWidget *window,GtkWidget **menu_bar)  
  58. {  
  59.     GtkItemFactory *item_factory;  
  60.     GtkAccelGroup *accel_group;  
  61.     gint nmenu_items = sizeof(menu_items)/sizeof(menu_items[0]);  
  62.   
  63.     accel_group = gtk_accel_group_new();  
  64.   
  65.     /**************************** 
  66.      *这个函数初始化套件 
  67.      *参数1:菜单类型- 
  68.      *参数2:菜单路径  
  69.      *参数3:指向一个gtk_accel_group 的指针 
  70.      * *****************************/  
  71.   
  72.     item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group);  
  73.       
  74.     /*生成菜单项,把数组里想的数量,数组自身,和菜单项的任意 
  75.      * 回调函数以此传递给套件*/  
  76.     gtk_item_factory_create_items(item_factory,nmenu_items,menu_items,NULL);  
  77.   
  78.     /*把新的加速组绑定到窗口*/  
  79.     gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);  
  80.   
  81.     if(menu_bar){  
  82.         /*返回套件已经创建的菜单栏*/  
  83.         *menu_bar = gtk_item_factory_get_widget(item_factory,"<main>");  
  84.     }  
  85.   
  86. }  
  87.   
  88. gint delete_event( GtkWidget *widget,GdkEvent  *event,gpointer   data )  
  89. {  
  90.     /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 
  91.      * 返回 TRUE,你不希望关闭窗口。 
  92.      * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/  
  93.     g_print ("delete event occurred\n");  
  94.     /* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/  
  95.     return TRUE;  
  96. }  
  97. /* 另一个回调函数 */  
  98. void destroy( GtkWidget *widget,gpointer   data )  
  99. {  
  100.     gtk_main_quit ();  
  101. }  
  102. int main( int   argc, char *argv[] )  
  103. {  
  104.     /* GtkWidget 是构件的存储类型 */  
  105.     GtkWidget *window;  
  106.     GtkWidget *menu_bar;  
  107.     GtkWidget *vbox;  
  108.       
  109.     /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/  
  110.     gtk_init (&argc, &argv);  
  111.         /* 创建一个新窗口 */  
  112.     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);  
  113.   
  114.     /*设置窗口标题*/  
  115.     gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!");  
  116.       
  117.     /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” 
  118.      * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。 
  119.      * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/  
  120.     g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL);  
  121.       
  122.     /* 在这里我们连接 "destroy" 事件到一个信号处理函数。   
  123.      * 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值 
  124.      * 都会触发这个事件。*/  
  125.     g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL);  
  126.       
  127.     /* 设置窗口边框的宽度。*/  
  128.     gtk_container_set_border_width (GTK_CONTAINER (window), 10);  
  129.       
  130.    /*创建窗口宽度*/  
  131.     gtk_widget_set_size_request(GTK_WIDGET(window),200,100);  
  132.   
  133.   
  134.     vbox = gtk_vbox_new(FALSE,1);  
  135.     gtk_container_add(GTK_CONTAINER(window),vbox);  
  136.     gtk_widget_show(vbox);  
  137.   
  138.     get_main_menu(window,&menu_bar);  
  139.     gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,TRUE,0);  
  140.     gtk_widget_show(menu_bar);  
  141.   
  142.   
  143.     gtk_widget_show(window);  
  144.     gtk_main ();  
  145.     return 0;  
  146. }  


 问题:在运行后无法将菜单栏显示出来的的问题?

            运行程序需要ROOT权限。具体原因不清楚。。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值