GTK+2.0编程范例代码分析-第二章(1)

本文详细解析GTK+2.0与3.0的菜单系统区别,通过代码实例展示了如何在GTK+2.0与3.0中创建菜单,并深入探讨了快捷键设置及中文显示等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明:http://blog.youkuaiyun.com/hubbybob1/article/details/49466979
本文主要是针对 GTK+2.0编程范例–宋国伟老师的书内的代码做一些注释,兼并讨论一下GTK+3.0与2.0的区别.其安装,在网上有很多讲解.
查看各个函数的的说明,就得看说明文档,下面这个网址很好,是GTK+3.0API的目录:
https://developer.gnome.org/gtk3/stable/
或者下载我上传的3.0说明文档,查看:
http://download.youkuaiyun.com/detail/hubbybob1/9219553

第2章 菜单与工具栏
2.1添加菜单
本节程序menu.c如下:

/*添加菜单menu.c*/
#include <gtk/gtk.h>
void on_menu_activate(GtkMenuItem* item, gpointer data)
{
    g_print("菜单项 %s 被激活\n",(gchar*)data);
//  g_print("menuitem %s is press!\n ",(gchar*)data);
}

int main (int argc, char* argv[])
{
    GtkWidget* window;
    GtkWidget* box;
    GtkWidget* menubar;//定义菜单条
    GtkWidget* menu;//定义文件菜单
    GtkWidget* editmenu;//编辑菜单
    GtkWidget* helpmenu;//帮助菜单
    GtkWidget* rootmenu;//主菜单,其他菜单要附加到这里面
    GtkWidget* menuitem;//菜单项

    GtkAccelGroup* accel_group;
        gtk_init(&argc,&argv);
//创建window
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),"菜单测试程序");
    gtk_window_set_default_size(GTK_WINDOW(window),200,200);//如果不设置大小的话会出现,窗口很小的问题
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

        accel_group = gtk_accel_group_new();//创建快捷键集
    gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);

    box = gtk_vbox_new(FALSE,0);//非均匀排放
    gtk_container_add(GTK_CONTAINER(window),box);
///////////////////////////////////////////////////////////////////////////////////////
//创建 "文件"菜单

    menu = gtk_menu_new();//创建菜单
//https://developer.gnome.org/gtk3/stable/gtk3-Stock-Items.html#GTK-STOCK-NEW:CAPS
//这识函数gtk_image_menu_item_new_from_stock的中的stock_id的定义,可以自己看看,也是快捷键
//在gtkstock.h文件中定义
    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW,accel_group);//快捷键 CTRL + N,带系统图像
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);//把新建子菜单挂到 他的上一级菜单上去 
    g_signal_connect(G_OBJECT(menuitem),"activate",//调用回调函数,打印新建
                                     G_CALLBACK(on_menu_activate),(gpointer)("新建"));//(gpointer)("New")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN,accel_group);//创建快捷键 CTRL + O,并带系统图像
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);//
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("打开"));//(gpointer)("Open")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE,accel_group);//CTRL + S ,并带有系统图标
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("保存"));//(gpointer)("Save")


    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE_AS,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("另存为"));//(gpointer)("Save As")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("退出"));//(gpointer)("Exit")


    rootmenu = gtk_menu_item_new_with_label(" 文件 ");//创建只带文字的菜单项, "文件"跟菜单
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu),menu);//menu作为rootmenu的子菜单
    menubar = gtk_menu_bar_new();//创建菜单条
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar),rootmenu);//把"文件"根菜单放到才单条上

////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////
//创建"编辑"菜单


    rootmenu = gtk_menu_item_new_with_label(" 编辑 ");
    editmenu = gtk_menu_new();//编辑菜单

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_CUT,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(editmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("剪切"));//(gpointer)("Cut")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(editmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("复制"));//(gpointer)("Copy")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(editmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("粘贴"));//(gpointer)("Paste")

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_FIND,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(editmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("查找"));//(gpointer)("Find")

     gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu),editmenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar),rootmenu);

////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
//创建"帮助"菜单

    rootmenu = gtk_menu_item_new_with_label(" 帮助 ");
    helpmenu = gtk_menu_new();//帮助菜单

    menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_HELP,accel_group);
    gtk_menu_shell_append(GTK_MENU_SHELL(helpmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("帮助"));//(gpointer)("Help")


    menuitem = gtk_image_menu_item_new_with_label(" 关于...");
    gtk_menu_shell_append(GTK_MENU_SHELL(helpmenu),menuitem);
    g_signal_connect(G_OBJECT(menuitem),"activate",
                                     G_CALLBACK(on_menu_activate),(gpointer)("关于"));//(gpointer)("About")

        gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu),helpmenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar),rootmenu);
///////////////////////////////////////////////////////////////////////////////////////////
/*
根据上面的阐述我们总结一下这个过程:
1.首先要创建window->box,这就不讲了,创建快捷键集, accel_group = gtk_accel_group_new();注意这个是绑定到window上的
2.要创建菜单条:使用menubar = gtk_menu_bar_new(),菜单条包括"文件","编辑","帮助"这些根菜单(rootmenu)
3.创建根菜单:rootmenu = gtk_menu_item_new_with_label(" 编辑 "),(需要把打包好的子菜单放到跟菜单上,这一点后面做)
4.创建菜单项,就是 editmenu = gtk_menu_new(),这个的作用就是打包所有的子菜单
5.创建子菜单:menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_CUT,accel_group),已编辑根菜单为例,子菜单为,复制粘贴剪切等
6.把子菜单放到菜单项中,就是打包gtk_menu_shell_append(GTK_MENU_SHELL(editmenu),menuitem);
7.把打包好的菜单项如editmenu放到根菜单上:gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu),editmenu);
8.再把根菜单放到菜单条上:gtk_menu_shell_append(GTK_MENU_SHELL(menubar),rootmenu);

这就是创建菜单的过程,其中回调函数最常用的信号为"activate",就是菜单被激活(被点击)
*/
        gtk_box_pack_start(GTK_BOX(box),menubar,FALSE,FALSE,0);        

        gtk_widget_show_all(window);    //显示
    gtk_main();
        return FALSE;
}//makefile
CC=gcc
all:
    $(CC) -o menu menu.c `pkg-config --cflags --libs gtk+-3.0`

其运行的结果如下,可以使用快捷键.
这里写图片描述
这里写图片描述
到这里大家也许会发现两个问题:
1,为什么我运行的结果中菜单并没有系统图标,而在程序中使用的函数明明是gtk_image_menu_item_new_from_stock函数?
2.仔细观察,我们的对话框内的子菜单是中文的,为什么会是中文呢,千万不要以为中文,来自函数g_signal_connect()内的中文,这只是一个回调函数,中文作为参数用在on_menu_activate上,在终端打印的也就是上面的第二章图片?

这两个问题值得思考,我会在以后慢慢说明这一点.

2.2创建菜单快捷方法
这一节是上一节的简化,程序itemfact.c如下:

/*创建菜单的快捷方法itemfact.c*/
#include <gtk/gtk.h>
void on_menu_activate(GtkMenuItem* item, gpointer data);
static GtkItemFactoryEntry menu_item[] = {//定义菜单集合
//文件     
{"/ 文件 (_F) ",NULL,NULL,0,"<Branch>"},//Branch:create an item to hold sub items,创建包含子项的项
{"/ 文件 (_F) /新建",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_NEW},//"新建"
{"/ 文件 (_F) /打开",NULL,on_menu_activate,1,"<StockItem>",GTK_STOCK_OPEN},//"打开",
{"/ 文件 (_F) /保存",NULL,on_menu_activate,2,"<StockItem>",GTK_STOCK_SAVE},//"保存"
{"/ 文件 (_F) /另存为",NULL,on_menu_activate,3,"<StockItem>",GTK_STOCK_SAVE_AS},//"另存为"
{"/ 文件 (_F) /-",NULL,NULL,0,"<Separator>"},
{"/ 文件 (_F) /退出",NULL,on_menu_activate,4,"<StockItem>",GTK_STOCK_QUIT},//"退出"
//编辑   
{"/ 编辑 (_E) ",NULL,NULL,0,"<Branch>"},
{"/ 编辑 (_E) /剪切",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_CUT},//"剪切"
{"/ 编辑 (_E) /复制",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_COPY},//"复制"
{"/ 编辑 (_E) /粘贴",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_PASTE},//"粘贴"
{"/ 编辑 (_E) /查找",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_FIND},//"查找",
//帮助
{"/ 帮助 (_H) ",NULL,NULL,0,"<Branch>"},
{"/ 帮助 (_H) /帮助",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_HELP},//"帮助"
{"/ 帮助 (_H) /关于...",NULL,on_menu_activate,0,NULL}//"关于"

};
void on_menu_activate(GtkMenuItem* item, gpointer data)
{

    g_print("菜单项 %d 被激活\n",(guint*)data);//%s   gchar
//  g_print("menuitem %s is press!\n ",(gchar*)data);
}


int main (int argc, char* argv[])
{

    GtkWidget* window;
    GtkWidget* box;
    GtkWidget* menubar;//定义菜单条
    GtkAccelGroup* accel_group;
    GtkItemFactory* item_factory;//创建菜单

    gint n = 15;//15
    gtk_init(&argc,&argv);
//创建窗口      
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),"菜单测试程序");
    gtk_window_set_default_size(GTK_WINDOW(window),200,200);//如果不设置大小的话会出现,窗口很小的问题
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

    accel_group = gtk_accel_group_new();//创建快捷键集
    gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);

    box = gtk_vbox_new(FALSE,0);//非均匀排放
    gtk_container_add(GTK_CONTAINER(window),box);
//创建Gtktemactory(条目工厂),gtk_item_factory_new                            
//第一个参数必须是GTK_TYPE_MENU_BAR(菜单条类),
// GTK_TYPE_MENU(菜单类),GTK_TYPE_OPTION_MENU(选项菜单类)中的一个
//gtk_item_factory_create_items,第一个参数是 Gtktemactory(条目工厂),第二个参数为创建条目的个数
//第三个参数为GtkItemFactoryEntry,就是各个实际的条目,第四个为gpointer的回调参数数据
    item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group);
    gtk_item_factory_create_items(item_factory,n,menu_item,NULL);

//  gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);
//gtk_item_factory_get_widget,获取菜单条指针  
       menubar = gtk_item_factory_get_widget(item_factory,"<main>");
       gtk_box_pack_start(GTK_BOX(box),menubar,FALSE,FALSE,0);//到此结束创建菜单条过程 

      gtk_widget_show(menubar);
      gtk_widget_show(window);

     gtk_main();
     return FALSE;

}//makefile
CC=gcc
all:
    $(CC) itemfact.c -o itemfact `pkg-config gtk+-2.0 --cflags --libs`

仔细的人可以看到这个程序与书上的略有不同,那就是在建立条目入口数组时(GtkItemFactoryEntry menu_item[])的第四个参数变化的问题,例如:

书上为:
{"/ 文件 (_F) /新建",NULL,on_menu_activate,"新建","<StockItem>",GTK_STOCK_NEW},
变为了
{"/ 文件 (_F) /新建",NULL,on_menu_activate,0,"<StockItem>",GTK_STOCK_NEW},//"新建"

一开始时使用书上的源码,会报错
这里写图片描述
遮主要的原因就是版本的问题:那么就来查看为的gtk的
版本:命令为:

pkg-config --modversion gtk+-2.0
pkg-config --modversion gtk+-3.0

结果为:
这里写图片描述
发现自己的2.0的版本为2.24.10,版本很高了所以定义肯定不同,那么就去查看这个GtkItemFactoryEntry的格式到底是什么,
目录为:/usr/inclide/gtk-2.0/gtk/gtkitemfactory.h 中定义如下:

typedef struct  _GtkItemFactoryEntry    GtkItemFactoryEntry;
struct  _GtkItemFactoryEntry  
 {   
  gchar *path;
  gchar *accelerator;          
  GtkItemFactoryCallback callback;
  guint      callback_action;//这个参数为无符号整形

  gchar    *item_type;      
 /* possible values:
   * NULL   -> "<Item>"   
   * ""     -> "<Item>"   
   * "<Title>"    -> create a title item
   * "<Item>"   -> create a simple item
   * "<ImageItem>"  -> create an item holding an image
   * "<StockItem>"  -> create an item holding a stock image
   * "<CheckItem>"  -> create a check item
   * "<ToggleItem>" -> create a toggle item
   * "<RadioItem>"  -> create a radio item
   * <path>   -> path of a radio item to link against
   * "<Separator>"  -> create a separator
   * "<Tearoff>"  -> create a tearoff separator
   * "<Branch>"   -> create an item to hold sub items
   * "<LastBranch>" -> create a right justified item to hold sub items
    */
   gconstpointer extra_data;     
   /* Extra data for some item types:
    *  ImageItem  -> pointer to inlined pixbuf stream
   *  StockItem  -> name of stock item
   */ 
};  

可以看到第四个参数为无符号整形的参数,不能使用宋国伟老师书中的字符串来,那么到此问题就解决了吗:
编译运行的结果如下:
这里写图片描述
从中可以看出没有任何
菜单的东西存在,这就时版本内的问题了,使用3.0的版本编译的话根本编译不通过,报错的现象与上面的一样,但是3.0版本根本就没有 GtkItemFactoryEntry这个东西,也就时:/usr/inclide/gtk-3.0/gtk内也没有相关的库文件存在,连gtkitem相关的库都没了,也就是说这个版本摒弃这种编程方式,那么这么快捷的方式为什么要摒弃掉呢,有没有类时的方式呢,这个值得研究。
因此,将在下小结做一个翻外,Glade的使用和2.0与3.0的初步对比

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值