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

转载请注明:http://blog.csdn.net/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.csdn.net/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的初步对比

GTK+ 2.0 教程 译者: huzheng,konghui,ferry,carton,yang_yi,ddd,tingle 版本号: V_0.1.0 2002年 6 月25 日 本文是有关通过 C 语言接口使用 GTK (the GIMP Toolkit) 的教程。 Table of Contents 中文版说明 简介 从这里开始 用 GTK 来写 Hello World 编译 Hello World 程序 信号和回调函数的原理 事件 Hello World 详解 继续 数据类型 深入探索信号处理函数 改进了的 Hello World 组装构件 组装盒的原理 盒的细节 组装示范程序 用表组装 表组装示例 构件概述 类型转换 构件的组织 无窗口构件 按钮构件 一般按钮 Normal Buttons 开关按钮 Toggle Buttons 复选按钮 Check Buttons 单选按钮 Radio Buttons 调整对象 Adjustments 创建一个调整对象 轻松使用调整对象 “调整对象”的内部机制 范围构件 Range Widgets 滚动条构件 Scrollbar Widgets 比例构件 Scale Widgets 创建一个比例构件 函数和信号(至少讲了函数) 常用的范围函数 设置更新方式 获得和设置调整对象 键盘和鼠标绑定 示例 杂项构件 标签 Labels 箭头 Arrows 工具提示对象 The Tooltips Object 进度条 Progress Bars 对话框 Dialogs 标尺 Rulers 状态栏 Statusbars 文本输入构件 Text Entries 微调按钮 Spin Buttons 组合框 Combo Box 日历 Calendar 颜色选择 Color Selection 文件选择 File Selections 容器构件 Container Widgets 事件盒 The EventBox 对齐构件 The Alignment widget 固定容器 Fixed Container 布局容器 Layout Container 框架 Frames 比例框架 Aspect Frames 分栏窗口构件 Paned Window Widgets 视角 Viewports 滚动窗口 Scrolled Windows 按钮盒 Button Boxes 工具栏 Toolbar 笔记本 Notebooks 菜单构件 手工创建菜单 手工菜单示例 使用套件 套件示例 无文档构件 快捷标签 Accel Label 选项菜单 Option Menu 菜单项 Menu Items 复选菜单项 Check Menu Item 单选菜单项 Radio Menu Item 分隔菜单项 Separator Menu Item 分离菜单项 Tearoff Menu Item 曲线图 Curves 绘图区 Drawing Area 字体选择对话框 Font Selection Dialog 消息对话框 Message Dialog Gamma 曲线图 图像 Image 插头和插座 Plugs and Sockets 树视区 Tree View 文本视区 Text View 设置构件的属性 超时、IO 和 Idle 函数 超时 Timeouts 监控IO Idle 函数 高级事件和信号处理 信号函数 连接和断开信号处理函数 阻塞和反阻塞信号处理函数 发出和停止信号 信号的发射和传播 操作选中区 概述 获取选中区信息 提供选中区 拖放 概述 属性 函数 设置源构件 源构件上的信号 设置目的构件 目的构件上的信号 GLib 定义 双向链表 单向链表 存储管理 计时器 字符串处理 实用程序和错误处理函数 GTK 的 rc 文件 rc 文件的功能 GTK rc 文件的格式 rc 文件示例 编写你自己的构件 概述 一个构件的剖析 创建一个复合构件 介绍 选择一个父类 头文件 _get_type() 函数 _class_init() 函数 _init() 函数 其余的... 从头创建构件 介绍 在屏幕上显示构件 表盘构件的原形 主体 gtk_dial_realize() 大小磋商 gtk_dial_expose() 事件处理 可能的增强 深入的学习 涂鸦板,一个简单的绘图程序 概述 事件处理 绘图区构件和绘图 添加XInput支持 允许扩展设备信息 使用扩展设备信息 得到更多关于设备的信息 进一步的讲解 编写 GTK 应用程序的技巧 投稿 鸣谢 教程的版权和许可声明
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值