热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

GTK编程基础菜单选项

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

菜单控件


创建菜单栏和子菜单时要用到三种构件:
? 一个菜单项(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() 将根菜单项放到菜单栏上。




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


g_signal_connect_swapped (G_OBJECT (widget), "event",
G_CALLBACK (handler),
G_OBJECT (menu));

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


看下面具体的例子:


bubuko.com,布布扣 



/*File:menu_item.c
*Date:2013-11-23
*Author:sjin
*Mail:413977243@qq.com
*/
#include
#include
static void menuitem_response(gchar *string)
{
printf("%s\n",string);
}
static int button_press(GtkWidget *widget,GdkEvent *event)
{
if(event->type == GDK_BUTTON_PRESS){
GdkEventButton *bevent = (GdkEventButton *)event;
gtk_menu_popup(GTK_MENU(widget),NULL,NULL,NULL,NULL,bevent->button,bevent->time);
/*告诉调用代码我们已经处理这个事件,*/
return TRUE;
}
/*else 未处理*/
return FALSE;
}
gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data )
{
/* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。
* 返回 TRUE,你不希望关闭窗口。
* 当你想弹出“你确定要退出吗?”对话框时它很有用。*/
g_print ("delete event occurred\n");
/* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/
return FALSE;
}
/* 另一个回调函数 */
void destroy( GtkWidget *widget,gpointer data )
{
gtk_main_quit ();
}
int main( int argc, char *argv[] )
{
/* GtkWidget 是构件的存储类型 */
GtkWidget *window;
GtkWidget *menu;
GtkWidget *menu_bar;
GtkWidget *root_menu;
GtkWidget *menu_items;
GtkWidget *vbox;
GtkWidget *button;
char buf[128];
int i; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/
gtk_init (&argc, &argv);
/* 创建一个新窗口 */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭”
* 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。
* 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/
g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* 在这里我们连接 "destroy" 事件到一个信号处理函数。
* 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值
* 都会触发这个事件。*/
g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); /* 设置窗口边框的宽度。*/
gtk_container_set_border_width (GTK_CONTAINER (window), 10); /*创建窗口宽度*/
gtk_widget_set_size_request(GTK_WIDGET(window),200,100);
/***********************
* 初始化菜单构件
* 记住这里永远不要用gtk_widget_show()函数来显示菜单控件
* 这个是包含菜单项的菜单,运行程序时点击会弹出来
**********************/
menu = gtk_menu_new();
/*****************××××××××××
*
*
* *********************/
for(i = 0; i <3; i++){
/*将名称复制到buf*/
sprintf(buf,"undetmenu-%d",i);
/*创建一个菜单项*/
menu_items = gtk_menu_item_new_with_label(buf);
/*将它添加到菜单*/
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_items);
/*当菜单被选中时的回调函数*/
g_signal_connect_swapped(G_OBJECT(menu_items),"activate",G_CALLBACK(menuitem_response),g_strdup(buf));
/*显示构件*/
gtk_widget_show(menu_items);
}
/*******************************
*这个是根菜单,将成为现实在菜单栏上的标签
*这里不会附上信号处理函数,因为它只是在被按下时弹出的其余的菜单
*******************************/
root_menu = gtk_menu_item_new_with_label("根菜单");
gtk_widget_show(root_menu);
/****************************
*指定想要穿件的menu成为根菜单
***************************/
gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),menu);
/*将一个菜单和一个按钮放到纵向盒子里面*/
vbox = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show(vbox);
/********************************
*创建一个菜单栏,并添加到主窗口
* *****************************/
menu_bar = gtk_menu_bar_new();
gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,FALSE,2);
gtk_widget_show(menu_bar);
button = gtk_button_new_with_label("点击");
g_signal_connect_swapped(G_OBJECT(button),"event",G_CALLBACK(button_press),menu);
gtk_box_pack_end(GTK_BOX(vbox),button,TRUE,TRUE,2);
gtk_widget_show(button);
/**************************
*最后把惨淡想添加到菜单栏上
* ***************************/
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu);
gtk_widget_show(window);
gtk_main ();
return 0;
}

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



/*******************************
*使用套件生成菜单方式
*gtk_item_factory
**********************/
/*File:menu_item2.c
*Date:2014-03-23
*Author:sjin
*Mail:413977243@qq.com
*/
#include
#include
/*必要的回调函数*/
static void print_hello(GtkWidget *w,gpointer data)
{
g_message("Hello,World!\n");
}
/****************************************
* 这是用来生成新惨淡的GtkItemFactoryEntry结构
* 第一项 菜单路径 下划线后字母指出惨淡打开的快捷键
* 第二项:这个条目的快捷键
* 第三项:回调函数
* 第四项,回调动作
* 第五项:项类型用
* NULL -> "Item"
* "" "Item"
* "" 标题
* "" 创建一个简单的项
* "" 创建一个检查项
* "" 创建一个开关项
* "" 创建一个选择项
* 选择项链接到的路径
* "" 分割线
* "Branch" 创建一个包含子项的项
* "LastBranch" 创建一个右对齐的分支
*************************************/
static GtkItemFactoryEntry menu_items[] = {
{"/_File", NULL, NULL,0,""},
{"/File/_New", "N", print_hello,0,NULL},
{"/File/_Open", "O", print_hello,0,NULL},
{"/File/_Save", "S" ,print_hello,0,NULL},
{"/File/Save _As", NULL,NULL,0,NULL},
{"/File/sepl", NULL,NULL,0,""},
{"/File/Quit", "Q", gtk_main_quit,0,NULL},
{"/_Options", NULL,NULL,0,""},
{"/Options/Test", NULL,NULL,0,NULL},
{"/_Help", NULL,NULL,0,""},
{"/Help/About", NULL,NULL,0,NULL},
};
void get_main_menu(GtkWidget *window,GtkWidget **menu_bar)
{
GtkItemFactory *item_factory;
GtkAccelGroup *accel_group;
gint nmenu_items = sizeof(menu_items)/sizeof(menu_items[0]);
accel_group = gtk_accel_group_new();
/****************************
*这个函数初始化套件
*参数1:菜单类型-
*参数2:菜单路径
*参数3:指向一个gtk_accel_group 的指针
* *****************************/
item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"

",accel_group); /*生成菜单项,把数组里想的数量,数组自身,和菜单项的任意
* 回调函数以此传递给套件*/
gtk_item_factory_create_items(item_factory,nmenu_items,menu_items,NULL);
/*把新的加速组绑定到窗口*/
gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);
if(menu_bar){
/*返回套件已经创建的菜单栏*/
*menu_bar = gtk_item_factory_get_widget(item_factory,"
");
}
}
gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data )
{
/* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。
* 返回 TRUE,你不希望关闭窗口。
* 当你想弹出“你确定要退出吗?”对话框时它很有用。*/
g_print ("delete event occurred\n");
/* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/
return TRUE;
}
/* 另一个回调函数 */
void destroy( GtkWidget *widget,gpointer data )
{
gtk_main_quit ();
}
int main( int argc, char *argv[] )
{
/* GtkWidget 是构件的存储类型 */
GtkWidget *window;
GtkWidget *menu_bar;
GtkWidget *vbox; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/
gtk_init (&argc, &argv);
/* 创建一个新窗口 */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭”
* 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。
* 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/
g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* 在这里我们连接 "destroy" 事件到一个信号处理函数。
* 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值
* 都会触发这个事件。*/
g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); /* 设置窗口边框的宽度。*/
gtk_container_set_border_width (GTK_CONTAINER (window), 10); /*创建窗口宽度*/
gtk_widget_set_size_request(GTK_WIDGET(window),200,100);
vbox = gtk_vbox_new(FALSE,1);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show(vbox);
get_main_menu(window,&menu_bar);
gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,TRUE,0);
gtk_widget_show(menu_bar);
gtk_widget_show(window);
gtk_main ();
return 0;
}


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


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

GTK编程基础----菜单选项,布布扣,bubuko.com


推荐阅读
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
author-avatar
kyf召世星bdc
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有