Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->系统管理 ->正文

GTK入门导引

来源:Linux-cn.com 作者:Webmaster 时间:2007-05-05 点击: [收藏] [投稿]

  That's all, folks!

  13.7 Curves

  14. Menu物件

  有两种方式来产生选单物件, 一种简单的, 一种难的. 两种各有其用途, 但您可以用menu_factory(简单的). 难的方法是一个一个产生. 简单的是用gtk_menu_factory 这个简单多了, 但各有其优劣之处.

  menufactory很好用, 虽然另外写一些函数, 以手动函数来产生这些选单会比较有用. 不过, 以menufactory, 也是可以加影像到选单中.

  14.1 Manual Menu Creation

  在教学的目的上, 我们先来看看难的方法.:)

  先看看产生选单的函数. 第一个当然是产生一个新的选单.


GtkWidget *gtk_menu_bar_new()
GtkWidget *gtk_menu_new();

  这个函数返回一个新的选单, 它还不会显示.

  以下两个函数是用来产生选单项目.


GtkWidget *gtk_menu_item_new()
and 
GtkWidget *gtk_menu_item_new_with_label(const char *label)

  动态新增


gtk_menu_item_append()
gtk_menu_item_set_submenu()

  gtk_menu_new_with_label及gtk_menu_new函数一个产生一个新的选单项目并带标签, 另一个则是个空的选单项目.

  产生选单的步骤大致如下:

  使用gtk_menu_new()来产生一个新的选单

  使用gtk_menu_item_new()来产生一个新的选单项目. 这会是主选单, 文字将会是menu bar本身.

  使用gtk_menu_item_new来将每一个项目产生出来用gtk_menu_item_append()来将每个新项目放在一起. 这会产生一列选单项目.

  使用gtk_menu_item_set_submenu()来接到心产生的menu_items到主选单项目. (在第二步中所产生出来的).

  使用gtk_menu_bar_new来产生一个menu bar. 这一步仅需做一次, 当我们产生一系列选单在menu bar上.

  使用gtk_menu_bar_append来将主选单放到menubar.

  14.2 Manual Menu范例

  我们来做做看, 看看一个范例会比较有帮助.


#include <gtk/gtk.h>
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *menu;
GtkWidget *menu_bar;
GtkWidget *root_menu;
GtkWidget *menu_items;
char buf[128];
int i;
gtk_init (&argc, &argv);
/* create a new window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
gtk_signal_connect(GTK_OBJECT (window), "destroy",
(GtkSignalFunc) gtk_exit, NULL);
/* Init the menu-widget, and remember -- never
 * gtk_show_widget() the menu widget!! */
menu = gtk_menu_new();
/* This is the root menu, and will be the label will 
be the menu name displayed on
 * the menu bar.There won't be
 * a signal handler attached, as it only pops up the rest of 
 the menu when pressed. */
root_menu = gtk_menu_item_new_with_label("Root Menu");
gtk_widget_show(root_menu);
/* Next we make a little loop that makes three menu-entries for
"test-menu".
 * Notice the call to gtk_menu_append.Here we are adding a list 
 of menu items
 * to our menu.Normally, we'd also catch the "clicked" signal on 
 each of the
 * menu items and setup a callback for it, but it's omitted 
 here to save space. */
for(i = 0; i < 3; i++)
{
/* Copy the names to the buf. */
sprintf(buf, "Test-undermenu - %d", i);
/* Create a new menu-item with a name... */
menu_items = gtk_menu_item_new_with_label(buf);
/* ...and add it to the menu. */
gtk_menu_append(GTK_MENU (menu), menu_items);
/* Show the widget */
gtk_widget_show(menu_items);
}
/* Now we specify that we want our newly created "menu" to be the menu 
for the "root menu" */
gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
/* Create a menu-bar to hold the menus and add it to our main window*/
menu_bar = gtk_menu_bar_new();
gtk_container_add(GTK_CONTAINER(window), menu_bar);
gtk_widget_show(menu_bar);
/* And finally we append the menu-item to the menu-bar -- this is the "root"
 * menu-item I have been raving about =) */
gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
/* always display the window as the last step so it all splashes 
on the screen at once. */
gtk_widget_show(window);
gtk_main ();
return 0;
}

  您也可以设定一个选单项目无效, 并使用accelerator table结合按键到选单功能.

  14.3 使用GtkMenuFactory

  我们已经示范了难的方法, 这里是用gtk_menu_factory的方法.

  14.4 Menu Factory范例

  这里是menu factory的范例. 这是第一个档案, menus.h. 另有menus.c及main.c


#ifndef __MENUS_H__
#define __MENUS_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);
void menus_create(GtkMenuEntry *entries, int nmenu_entries);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MENUS_H__ */
And here is the menus.c file. 
#include <gtk/gtk.h>
#include <strings.h>
#include "main.h"
static void menus_remove_accel
(GtkWidget * widget, gchar * signal_name, gchar * path);
static gint menus_install_accel
(GtkWidget * widget, gchar * signal_name, gchar key,
gchar modifiers, gchar * path);
void menus_init(void);
void menus_create(GtkMenuEntry * entries, int nmenu_entries);
/* this is the GtkMenuEntry structure used to create new menus.The
 * first member is the menu definition string.The second, the
 * default accelerator key used to access this menu function with
 * the keyboard.The third is the callback function to call when
 * this menu item is selected (by the accelerator key, or with the
 * mouse.) The last member is the data to pass to your callback function.
 */
static GtkMenuEntry menu_items[] =
{
{"<Main>/File/New", "<control>N", NULL, NULL},
{"<Main>/File/Open", "<control>O", NULL, NULL},
{"<Main>/File/Save", "<control>S", NULL, NULL},
{"<Main>/File/Save as", NULL, NULL, NULL},
{"<Main>/File/<separator>", NULL, NULL, NULL},
{"<Main>/File/Quit", 
"<control>Q", file_quit_cmd_callback, "OK, I'll quit"},
{"<Main>/Options/Test", NULL, NULL, NULL}
};
/* calculate the number of menu_item's */
static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
static int initialize = TRUE;
static GtkMenuFactory *factory = NULL;
static GtkMenuFactory *subfactory[1];
static GHashTable *entry_ht = NULL;
void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table)
{
if (initialize)
menus_init();
if (menubar)
*menubar = subfactory[0]->widget;
if (table)
*table = subfactory[0]->table;
}
void menus_init(void)
{
if (initialize) {
initialize = FALSE;
factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>");
menus_create(menu_items, nmenu_items);
}
}
void menus_create(GtkMenuEntry * entries, int nmenu_entries)
{
char *accelerator;
int i;
if (initialize)
menus_init();
if (entry_ht)
for (i = 0; i < nmenu_entries; i++) {
accelerator = g_hash_table_lookup(entry_ht, entries[i].path);
if (accelerator) {
if (accelerator[0] == '\0')
entries[i].accelerator = NULL;
else
entries[i].accelerator = accelerator;
}
}
gtk_menu_factory_add_entries(factory, entries, nmenu_entries);
for (i = 0; i < nmenu_entries; i++)
if (entries[i].widget) {
gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator",
(GtkSignalFunc) menus_install_accel,
entries[i].path);
gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator",
(GtkSignalFunc) menus_remove_accel,
entries[i].path);
}
}
static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, 
gchar key, gchar modifiers, gchar * path)
{
char accel[64];
char *t1, t2[2];
accel[0] = '\0';
if (modifiers & GDK_CONTROL_MASK)
strcat(accel, "<control>");
if (modifiers & GDK_SHIFT_MASK)
strcat(accel, "<shift>");
if (modifiers & GDK_MOD1_MASK)
strcat(accel, "<alt>");
t2[0] = key;
t2[1] = '\0';
strcat(accel, t2);
if (entry_ht) {
t1 = g_hash_table_lookup(entry_ht, path);
g_free(t1);
} else
entry_ht = g_hash_table_new(g_string_hash, g_string_equal);
g_hash_table_insert(entry_ht, path, g_strdup(accel));
return TRUE;
}
static void menus_remove_accel
(GtkWidget * widget, gchar * signal_name, gchar * path)
{
char *t;
if (entry_ht) {
t = g_hash_table_lookup(entry_ht, path);
g_free(t);
g_hash_table_insert(entry_ht, path, g_strdup(""));
}
}
void menus_set_sensitive(char *path, int sensitive)
{
GtkMenuPath *menu_path;
if (initialize)
menus_init();
menu_path = gtk_menu_factory_find(factory, path);
if (menu_path)
gtk_widget_set_sensitive(menu_path->widget, sensitive);
else
g_warning
("Unable to set sensitivity for menu which doesn't exist: %s", path);
}


 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:GTK+/Gnome应用开发   下一篇:GTK v1.2 Tutorial(英文)

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号