gtk_widget_add_accelerator
関数でウィジェットにアクセラレータを追加します。ショートカットキーのことを
正確にはアクセラレータと言います。引数は次のとおりです。
- 第1引数にアクセラレータを追加するウィジェットを指定します
- 第2引数にアクセラレータと結びつけるイベントを指定します
- 第3引数にアクセルグループを指定します
- 第4引数に登録するキーを指定します。これは定数になっていますが、
多くのキーは、GDK_KEY_キー という形で登録できるみたいです
- 第5引数にキーと組み合わせるモディファイキー(modify key、修飾キー)
を指定します。登録できる修飾キーは次のとおりです
GDK_SHIFT_MASK | シフトキー |
GDK_CONTROL_MASK | コントロールキー |
GDK_MOD1_MASK | アルト(Alt)キー |
- 第6引数にアクセラレータの状態を指定するみたいです。状態は次のとおりです
GTK_ACCEL_VISIBLE | 見える状態 |
GTK_ACCEL_LOCKED | 取り外しできない状態 |
GGTK_ACCEL_MASK | どういう状態か分かりません |
shortcutmenu2.c
- 次は、ショートカットキーとイメージの両方がついたサンプルです。
-
このサンプルは、GTK3では、コンパイル時に警告が出ますが、実行に問題はありません。
-
ショートカットキー付きメニューは、すべてのプラットフォームで有効になります。
-
イメージ付きメニューは、Linux Mintだけで有効になります。
-
Linuxでは、gconf-editorというアプリケーションで、
desktop→gnome→interfaceのmenus_have_iconsをオンにすれば
イメージ付きメニューが表示されるという説明もありますが、
試してみた限りでは Mint 以外では有効になりませんでした。
#include <gtk/gtk.h>
void on_new();
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *filemenu;
GtkWidget *editmenu;
GtkWidget *filemenuitem;
GtkWidget *editmenuitem;
GtkWidget *newmenuitem;
GtkWidget *openmenuitem;
GtkWidget *savemenuitem;
GtkWidget *separator1;
GtkWidget *quitmenuitem;
GtkWidget *undomenuitem;
GtkWidget *redomenuitem;
GtkWidget *separator2;
GtkWidget *cutmenuitem;
GtkWidget *copymenuitem;
GtkWidget *pastemenuitem;
GtkAccelGroup * accel_group = NULL;
gtk_init(&argc, &argv);
window = gtk_window_new (0);
/* GTK_WINDOW_TOPLEVEL定数の値は 0 です */
gtk_window_set_title (GTK_WINDOW(window), "SubMenu");
gtk_window_set_default_size (GTK_WINDOW(window), 320, 240);
gtk_window_set_position (GTK_WINDOW(window), 1);
/* GTK_WIN_POS_CENTER定数の値は 1 です */
gtk_container_set_border_width (GTK_CONTAINER(window), 15);
vbox = gtk_box_new (1, 0);
/* GTK_ORIENTATION_VERTICAL定数の値は 1 です */
gtk_container_add (GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new ();
filemenu
= gtk_menu_new ();
editmenu
= gtk_menu_new ();
accel_group
= gtk_accel_group_new ();
gtk_window_add_accel_group (GTK_WINDOW(window), accel_group);
filemenuitem
= gtk_menu_item_new_with_label("File");
newmenuitem
= gtk_image_menu_item_new_from_stock("gtk-new", accel_group);
openmenuitem
= gtk_image_menu_item_new_from_stock("gtk-open", accel_group);
savemenuitem
= gtk_image_menu_item_new_from_stock("gtk-save", accel_group);
separator1
= gtk_separator_menu_item_new ();
quitmenuitem
= gtk_image_menu_item_new_from_stock("gtk-quit", accel_group);
editmenuitem
= gtk_menu_item_new_with_label("Edit");
undomenuitem
= gtk_image_menu_item_new_from_stock("gtk-undo", accel_group);
redomenuitem
= gtk_image_menu_item_new_from_stock("gtk-redo", accel_group);
separator2
= gtk_separator_menu_item_new ();
cutmenuitem
= gtk_image_menu_item_new_from_stock("gtk-cut", accel_group);
copymenuitem
= gtk_image_menu_item_new_from_stock("gtk-copy", accel_group);
pastemenuitem
= gtk_image_menu_item_new_from_stock("gtk-paste",accel_group);
gtk_menu_item_set_submenu (GTK_MENU_ITEM(filemenuitem),
filemenu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM(editmenuitem),
editmenu);
gtk_menu_shell_append (GTK_MENU_SHELL(menubar),
filemenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(menubar),
editmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(filemenu),
newmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(filemenu),
openmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(filemenu),
savemenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(filemenu),
separator1);
gtk_menu_shell_append (GTK_MENU_SHELL(filemenu),
quitmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
undomenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
redomenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
separator2);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
cutmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
copymenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(editmenu),
pastemenuitem);
gtk_box_pack_start (GTK_BOX(vbox), menubar, 0, 0, 0);
/* 第3引数と第4引数の 0 はFALSEという意味です */
g_signal_connect (newmenuitem, "activate",
G_CALLBACK(on_new), NULL);
g_signal_connect (quitmenuitem, "activate",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void on_new()
{
printf("New\n");
}
実行結果
-
新しいGTKでは、gtk_image_menu_item_new_from_stock関数が
非推奨(deprecated)になっているため、コンパイル時に警告(warning)が出ますが、
問題なく動作します。
-
ショートカットキーの付いたメニューアイテムには
イベントハンドラーを設定できますが、今回は、
「新規」と「終了」だけに処理を施しました。
-
「新規」メニューを選ぶとターミナルに「New」と表示されます。
コード説明
-
GtkAccelGroup * accel_group = NULL;
GtkAccelGroupのaccel_groupというポインターを定義しています。
メニューアイテムはアクセルグループに登録することによってショートカットキーが
有効になります。
-
gtk_accel_group_new()関数でアクセルグループを作ります。引数はありません。
-
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
ウィンドウにアクセルグループを登録します。
-
gtk_image_menu_item_new_from_stock("gtk-new", accel_group);
画像付きメニューを作っています。
-
第1引数の"gtk-new"で、イメージと
メニューアイテムに各言語に合わせて表示される文字列を指定します
-
第2引数にアクセルグループを指定します。ここに NULL
を指定するとショートカットキーは作られません。
-
Undo(元に戻す) と Redo(やり直す)にはショートカットキーが付かないみたいです。
ステータスバーとチェックメニュー
statusbar.c
#include <gtk/gtk.h>
void showmessage();
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *viewmenuitem;
GtkWidget *viewmenu;
GtkWidget *showmenuitem;
GtkWidget *statusbar;
guint statusbar_id;
gtk_init(&argc, &argv);
window = gtk_window_new (0);
/* GTK_WINDOW_TOPLEVEL定数の値は 0 です */
gtk_window_set_title (GTK_WINDOW(window),
"SatusBar");
gtk_window_set_default_size (GTK_WINDOW(window), 320, 240);
gtk_window_set_position (GTK_WINDOW(window), 1);
/* GTK_WIN_POS_CENTER定数の値は 1 です */
gtk_container_set_border_width (GTK_CONTAINER(window), 0);
/* 今回はウィンドウのボーダー幅を 0 にしました */
vbox = gtk_box_new (1, 0);
/* GTK_ORIENTATION_VERTICAL定数の値は 1 です */
gtk_container_add (GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new ();
viewmenu
= gtk_menu_new ();
viewmenuitem
= gtk_menu_item_new_with_label("View");
showmenuitem
= gtk_check_menu_item_new_with_label
("Show statusbar message");
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(showmenuitem),
TRUE);
gtk_menu_item_set_submenu (GTK_MENU_ITEM(viewmenuitem),
viewmenu);
gtk_menu_shell_append (GTK_MENU_SHELL(menubar),
viewmenuitem);
gtk_menu_shell_append (GTK_MENU_SHELL(viewmenu),
showmenuitem);
statusbar
= gtk_statusbar_new ();
statusbar_id
= gtk_statusbar_get_context_id
(GTK_STATUSBAR(statusbar), "none");
gtk_statusbar_push (GTK_STATUSBAR(statusbar),
statusbar_id,
"This is a statusbar.");
gtk_box_pack_start (GTK_BOX(vbox), menubar, 0, 0, 0);
/* 第3引数と第4引数の 0 はFALSEという意味です */
gtk_box_pack_end (GTK_BOX(vbox), statusbar,0, 1, 0);
g_signal_connect (showmenuitem, "activate",
G_CALLBACK(showmessage),
statusbar);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void showmessage(GtkWidget *menuitem, GtkWidget *statusbar)
{
guint id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar),
"none");
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
{
gtk_statusbar_push(GTK_STATUSBAR(statusbar), id,
"This is a statusbar.");
} else {
gtk_statusbar_push(GTK_STATUSBAR(statusbar), id,
"");
}
}
実行結果
コード説明
-
guint statusbar_id;
guintはGTKで再定義された unsigned int です。
ステータスバーにメッセージを記述する時に id 番号を格納するために使います。
-
gtk_container_set_border_width(GTK_CONTAINER(window), 0);
GTKのメニューとステータスバーはウィンドウの中に配置されるので、
ボーターをなくしました。
-
gtk_check_menu_item_new_with_label関数でチェックメニューアイテムを作ります
引数にメニューに表示される文字列を指定します。
-
gtk_check_menu_item_set_active関数で
チェックメニューアイテムにチェックをつけます。
- 第1引数に対象のチェックメニューアイテムを指定します
- 第2引数にTRUEを指定するとチェックメニューアイテムにチェックが付きます
-
gtk_statusbar_new関数でステータスバーを作ります。引数はいりません。
-
gtk_statusbar_get_context_id関数でステータスバーのIDを整数で取得します。
- 第1引数にステータスバーを指定します
- 第2引数に任意の文字列を指定します
-
gtk_statusbar_push関数でステータスバーに文字列を表示します。
- 第1引数にステータスバーを指定します
- 第2引数に先ほど取得したIDを指定します
- 第3引数にステータスバーに表示する文字列を指定します
-
gtk_check_menu_item_get_active関数で
引数で指定したチェックメニューアイテムがチェックされているかどうかを調べます。
チェックされていればTRUE、されていなければFALSEが返されます。
ポップアップメニュー
- ポップアップメニューは、右クリックすると、その場所に現れるメニューです。
- コンテキストメニューとも呼ばれます。
popupmenu.c
#include <gtk/gtk.h>
void show_popup();
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *menu;
GtkWidget *ebox;
GtkWidget *minimize;
GtkWidget *quit;
gtk_init(&argc, &argv);
window = gtk_window_new (0);
/* GTK_WINDOW_TOPLEVEL定数の値は 0 です */
gtk_window_set_title (GTK_WINDOW(window), "PopupMenu");
gtk_window_set_default_size (GTK_WINDOW(window), 320, 240);
gtk_window_set_position (GTK_WINDOW(window), 1);
/* GTK_WIN_POS_CENTER定数の値は 1 です */
//gtk_container_set_border_width (GTK_CONTAINER(window), 15);
/* ボーダーは今回設定しません */
ebox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER(window), ebox);
menu = gtk_menu_new ();
minimize
= gtk_menu_item_new_with_label
("Minimize");
quit = gtk_menu_item_new_with_label
("Quit");
gtk_menu_shell_append (GTK_MENU_SHELL(menu), minimize);
gtk_menu_shell_append (GTK_MENU_SHELL(menu), quit);
gtk_widget_show (minimize);
gtk_widget_show (quit);
g_signal_connect_swapped (minimize, "activate",
G_CALLBACK(gtk_window_iconify),
window);
g_signal_connect (quit, "activate",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect_swapped (ebox, "button-press-event",
G_CALLBACK(show_popup), menu);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void show_popup(GtkWidget *widget, GdkEvent *event)
{
const gint RIGHT_CLICK = 3;
GdkEventButton *eventbutton = (GdkEventButton *)event;
if (eventbutton->button == RIGHT_CLICK)
{
gtk_menu_popup_at_pointer(GTK_MENU(widget), event);
}
}
実行結果
コード説明
-
gtk_event_box_new関数でイベントボックス(GtkEventBox)を作っています。
イベントボックスは目には見えないウィジェットで
ウィンドウなどに新しいイベントを追加するために使います。
-
gtk_container_add(GTK_CONTAINER(window), ebox);
イベントボックスをウィンドウ一杯に配置しています。
-
gtk_widget_show(minimize);
minimizeとquitは個別にshowしておかなければならないみたいです。
ウィンドウに所属していないから? と考えれば良いのでしょうか。
-
g_signal_connect_swapped(minimize,"activate",
G_CALLBACK(gtk_window_iconify), window);
g_signal_connect関数では、イベントを発生したウィジェットが
イベントハンドラーの第1引数に渡されます。
g_signal_connect_swapped関数では、第4引数のウィジェットが
イベントハンドラーの第1引数に渡されます。
-
g_signal_connect(quit,"activate", G_CALLBACK(gtk_main_quit), NULL);
gtk_main_quit関数は引数を取りませんので
g_signal_connect関数とg_signal_connect_swapped関数のどちらでも
正常に動作します。
-
g_signal_connect_swapped(ebox, "button-press-event",
G_CALLBACK(show_popup), menu);
g_signal_connect_swapped関数を使っていますので
show_popupイベントハンドラーの第1引数に渡されるのはイベントボックスではなく
menu ウィジェットです。
ボタンが押された時のイベントは "button-press-event" です。
-
void show_popup(GtkWidget *widget, GdkEvent *event)
イベントボックスで発生したイベントでは、イベントハンドラーの第2引数として、
イベントそのものが自動的に渡されます。
-
const gint RIGHT_CLICK = 3;
マウスの右ボタンは 3 という数値で表されています。
後で分かりやすいように定数化しています。そして続けて次の処理をします。
-
GdkEventButton *eventbutton = (GdkEventButton *)event;
プレスされた(押された)ボタンを eventbutton ポインターに入れます。
-
if (eventbutton->button == RIGHT_CLICK)
そして、ボタンが 3 (右ボタン)だったら
-
gtk_menu_popup_at_pointer(GTK_MENU(widget), event);
gtk_menu_popup_at_pointer関数でポップアップメニューを表示します。
第1引数にメニューを、第2引数にイベントを渡します。
ツールバー
-
GTK3対応のサンプルを作りました。
-
ただし、今の段階では、UbuntuとMint以外では
ツールバーのアイコンが正しく表示されないみたいです。
toolbar.c
#include <gtk/gtk.h>
#include <stdlib.h> // for atoi
#include <string.h> // for strcmp
GtkToolItem *undo;
GtkToolItem *redo;
void undo_redo();
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *toolbar;
GtkWidget *undo_icon;
GtkWidget *redo_icon;
GtkWidget *quit_icon;
GtkToolItem *sep;
GtkToolItem *quit;
GtkWidget *label;
gtk_init(&argc, &argv);
window = gtk_window_new (0);
gtk_window_set_title (GTK_WINDOW(window), "ToolBar");
gtk_window_set_default_size (GTK_WINDOW(window), 320, 240);
gtk_window_set_position (GTK_WINDOW(window), 1);
vbox = gtk_box_new (1, 0);
/* 1 はGTK_ORIENTATION_VERTICAL定数の値です */
gtk_container_add (GTK_CONTAINER(window), vbox);
toolbar = gtk_toolbar_new ();
/*
gtk_toolbar_set_style (GTK_TOOLBAR(toolbar),
GTK_TOOLBAR_ICONS);
設定しなくてもデフォルトでアイコン表示(GTK_TOOLBAR_ICONS)みたいです
*/
gtk_container_set_border_width (GTK_CONTAINER(toolbar), 0);
undo_icon
= gtk_image_new_from_icon_name("gtk-redo",
GTK_ICON_SIZE_LARGE_TOOLBAR);
undo = gtk_tool_button_new (undo_icon, "Undo");
gtk_widget_set_name (GTK_WIDGET(undo), "undo");
/*
この関数は必須ではありませんが、後でツールボタンを区別するために名前を使います */
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), undo, -1);
redo_icon
= gtk_image_new_from_icon_name("gtk-redo",
GTK_ICON_SIZE_LARGE_TOOLBAR);
redo = gtk_tool_button_new (redo_icon, "Redo");
gtk_widget_set_name (GTK_WIDGET(redo), "redo");
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), redo, -1);
gtk_widget_set_sensitive (GTK_WIDGET(redo), FALSE);
sep = gtk_separator_tool_item_new();
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), sep, -1);
quit_icon
= gtk_image_new_from_icon_name("gtk-quit",
GTK_ICON_SIZE_LARGE_TOOLBAR);
quit = gtk_tool_button_new (quit_icon, "Quit");
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), quit, -1);
label = gtk_label_new ("4");
gtk_box_pack_start (GTK_BOX(vbox), toolbar, 0, 0, 0);
gtk_box_pack_end (GTK_BOX(vbox), label, 1, 0, 0);
g_signal_connect (undo, "clicked",
G_CALLBACK(undo_redo), label);
g_signal_connect (redo, "clicked",
G_CALLBACK(undo_redo), label);
g_signal_connect (quit, "clicked",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void undo_redo(GtkWidget *widget, GtkLabel *label)
{
const gchar *text = gtk_label_get_text(label);
const gchar *name = gtk_widget_get_name(widget);
guchar num = atoi(text);
if (strcmp(name, "undo") == 0)
/* g_strcmp0 という関数もあります */
{
num--;
switch (num)
{
case 0:
gtk_widget_set_sensitive(GTK_WIDGET(undo), FALSE);
break;
case 3:
gtk_widget_set_sensitive(GTK_WIDGET(redo), TRUE);
break;
}
} else {
num++;
switch (num)
{
case 1:
gtk_widget_set_sensitive(GTK_WIDGET(undo), TRUE);
break;
case 4:
gtk_widget_set_sensitive(GTK_WIDGET(redo), FALSE);
break;
}
}
gchar *str = g_strdup_printf("%d", num);
gtk_label_set_text(label, str);
g_free(str);
}
実行結果
コード説明
-
#include <stdlib.h> // for atoi
#include <string.h> // for strcmp
環境によっては記述しないと警告が出る場合があります。
-
GtkToolItem *undo;
GtkToolItem *redo;
g_signal_connect関数では
イベントハンドラーに渡せる引数は、イベントを発したウィジェット以外に
追加で一つだけです。そのため undoとredoはグローバル変数にしました。
ツールボタンはGtkToolItem型になります。
-
void undo_redo();
GTKでは、プロトタイプ(関数前方宣言)には、引数の明記は必要ないみたいです。
気になる方は、引数も記述してください。
-
toolbar = gtk_toolbar_new();
ツールバーを作っています。引数はありません。
-
gtk_toolbar_set_styleGTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
ツールバーのスタイルを設定するのにこの関数を使います。
ただしツールバーはデフォルトでTOOL_BAR_ICONS(アイコン表示)に設定されています。
-
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 0);
この関数でツールバーの周りのボーダー(border、枠)の幅を設定できます。
-
-
undo_icon = gtk_image_new_from_icon_name("gtk-undo",
GTK_ICON_SIZE_LARGE_TOOLBAR);
アイコンを作ります。引数は次のとおりです。
- 第1引数にアイコンの名前を "gtk-undo" という形で指定します
- 第2引数にアイコンのサイズを指定します。次のような定数があります
GTK_ICON_SIZE_INVALID | 無効なサイズ |
GTK_ICON_SIZE_MENU | メニューに適したサイズ(16px) |
GTK_ICON_SIZE_SMALL_TOOLBAR |
小さなツールバーに適したサイズ(16px) |
GTK_ICON_SIZE_LARGE_TOOLBAR |
大きなツールバーに適したサイズ(24px) |
GTK_ICON_SIZE_BUTTON |
ボタンに適したサイズ(16px) |
GTK_ICON_SIZE_DND |
ドラッグ&ドロップに適したサイズ(32px) |
GTK_ICON_SIZE_DIALOG |
ダイアログに適したサイズ(48px) |
- redo = gtk_tool_button_new(redo_icon, "Redo");
ツールボタンを作っています。第1引数にアイコンウィジェットを、
第2引数にツールボタンに表示する文字列を指定します。
-
gtk_widget_set_name(GTK_WIDGET(redo), "redo");
ウィジェットには、ウィジェットを識別するための名前を付けられます。
この名前は後で使います。
-
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1);
ツールバーにツールアイテムを挿入しています。引数は次のとおりです。
- 第1引数に挿入されるツールバーを指定します。ツールバーが一つとは限りません
- 第2引数に挿入するツールアイテムを指定します
- 第3引数に挿入する位置を指定します。挿入順序は左から 0、1、
2 になります。-1 を指定すると最後に追加されます。
-
gtk_widget_set_sensitive(GTK_WIDGET(redo), FALSE);
ウィジェットの使用が可能かどうかを設定しています。
- 第1引数に対象のウィジェットを指定します
- 第2引数にTRUEを指定した場合は、対象のウィジェットは使用可能になります。
FALSEを指定した場合は、対象のウィジェットは仕様不可能になります。
-
sep = gtk_separator_tool_item_new();
ツールバーのセパレーター(縦線)を作っています。
-
g_signal_connect(undo, "clicked", G_CALLBACK(undo_redo), label);
ツールボタンが押された時のイベントは "clicked" です。
-
const gchar *name = gtk_widget_get_name(widget);
先ほど設定したウィジェットの名前を取得しています。
-
guchar num = atoi(text);
atoiは C の関数です。引数の文字列を整数に変換した新たな値を作ります。
guchar は、GTKで再定義された unsigned char です。
-
if (strcmp(name, "undo") == 0)
strcmpも C の関数です。第1引数と第2引数の文字列を比較して、
第1引数が大きい場合は 1 を、第2引数が大きい場合は -1 を、
第1引数と第2引数が同じ場合は 0 を返します。
文字の大小は辞書の順序になります。辞書の末尾の方が大きい文字列になります。
GTKには同じ働きをする g_strcmp0 という関数もあります。
-
gchar *str = g_strdup_printf("%d", num);
g_strdup_printf関数は、変換指定子で変換された新しい文字列を作ります。
-
gtk_label_set_text(label, str);
この関数でラベルに表示される文字列を設定します。
- 第1引数に対象となるラベルを指定します
- 第2引数に設定する文字列を指定します
-
g_free(str);
g_strdup_printf関数で作った文字列は、g_free関数で
文字列に割り当てられたメモリーを解放しておいた方が良いです。
toolbar2.c
-
念のために、GTK2対応のサンプルも残しておきます。
-
このサンプルもmacOSではツールバーのアイコンは正しく表示されません。
#include <gtk/gtk.h>
GtkToolItem *undo;
GtkToolItem *redo;
void undo_redo();
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *toolbar;
GtkToolItem *sep;
GtkToolItem *quit;
GtkWidget *label;
gtk_init(&argc, &argv);
window = gtk_window_new (0);
/* GTK_WINDOW_TOPLEVEL定数の値は 0 です */
gtk_window_set_title (GTK_WINDOW(window), "ToolBar");
gtk_window_set_default_size (GTK_WINDOW(window), 320, 240);
gtk_window_set_position (GTK_WINDOW(window), 1);
/* 1 はGTK_WIN_POS_CENTER定数の値です */
//gtk_container_set_border_width (GTK_CONTAINER(window), 15);
/* メニューやツールバーを設定する場合はボーダーはない方が良いです。 */
vbox = gtk_box_new (1, 0);
/* 1 はGTK_ORIENTATION_VERTICAL定数の値です */
gtk_container_add (GTK_CONTAINER(window), vbox);
toolbar = gtk_toolbar_new ();
//gtk_toolbar_set_style (GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
/* 設定しなくてもデフォルトでアイコン表示(GTK_TOOLBAR_ICONS)みたいです */
gtk_container_set_border_width (GTK_CONTAINER(toolbar), 0);
undo = gtk_tool_button_new_from_stock("gtk-undo");
gtk_widget_set_name (GTK_WIDGET(undo), "undo");
/* この関数は必須ではありませんが、後でツールボタンを区別するために名前を使います */
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), undo, -1);
redo = gtk_tool_button_new_from_stock("gtk-redo");
gtk_widget_set_name (GTK_WIDGET(redo), "redo");
/* この関数は必須ではありませんが、後でツールボタンを区別するために名前を使います */
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), redo, -1);
gtk_widget_set_sensitive (GTK_WIDGET(redo), FALSE);
sep = gtk_separator_tool_item_new();
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), sep, -1);
quit = gtk_tool_button_new_from_stock("gtk-quit");
gtk_toolbar_insert (GTK_TOOLBAR(toolbar), quit, -1);
label = gtk_label_new ("4");
gtk_box_pack_start (GTK_BOX(vbox), toolbar, 0, 0, 0);
/* gtk_box_pack_start関数の第3引数と第4引数の 0 はFALSEという意味です */
gtk_box_pack_end (GTK_BOX(vbox), label, 1, 1, 0);
/* gtk_box_pack_start関数の第3引数と第4引数の 1 はTRUEという意味です */
g_signal_connect (undo, "clicked",
G_CALLBACK(undo_redo), label);
g_signal_connect (redo, "clicked",
G_CALLBACK(undo_redo), label);
g_signal_connect (quit, "clicked",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void undo_redo(GtkWidget *widget, GtkLabel *label)
{
const gchar *text = gtk_label_get_text(label);
const gchar *name = gtk_widget_get_name(widget);
guchar num = atoi(text);
if (strcmp(name, "undo") == 0)
/* g_strcmp0 という関数もあります */
{
num--;
switch (num)
{
case 0:
gtk_widget_set_sensitive(GTK_WIDGET(undo), FALSE);
break;
case 3:
gtk_widget_set_sensitive(GTK_WIDGET(redo), TRUE);
break;
}
} else {
num++;
switch (num)
{
case 1:
gtk_widget_set_sensitive(GTK_WIDGET(undo), TRUE);
break;
case 4:
gtk_widget_set_sensitive(GTK_WIDGET(redo), FALSE);
break;
}
}
gchar *str = g_strdup_printf("%d", num);
gtk_label_set_text(label, str);
g_free(str);
}
実行結果
コード説明
-
GtkToolItem *undo;
GtkToolItem *redo;
g_signal_connect関数では
イベントハンドラーに追加で一つまでしか引数を渡せないので、undoとredoは
グローバル変数にしました。ツールボタンはGtkToolItem型で受けます。
-
toolbar = gtk_toolbar_new();
ツールバーを作っています。引数はありません。
-
//gtk_toolbar_set_styleGTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
ツールバーのスタイルを設定するのにこの関数を使います。
ただしツールバーはデフォルトでTOOL_BAR_ICONS(アイコン表示)に設定されています。
-
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 0);
この関数でツールバーの周りのボーダー(border、枠)の幅を設定できます。
-
undo = gtk_tool_button_new_from_stock("gtk-undo");
この関数はGTK3では、非推奨(deprecated)になっています。
"gtk-undo"がストックアイコンになります。
-
gtk_widget_set_name(GTK_WIDGET(redo), "redo");
ウィジェットには、ウィジェットを識別するための名前を付けられます。
-
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1);
この関数でツールバーにツールアイテムを挿入します。
- 第1引数に挿入されるツールバーを指定します。ツールバーが一つとは限りません
- 第2引数に挿入するツールアイテムを指定します
- 第3引数に挿入する位置を指定します。挿入順序は左から 0、1、
2 になります。-1 を指定すると最後に追加されます。
-
gtk_widget_set_sensitive(GTK_WIDGET(redo), FALSE);
この関数でウィジェットの使用が可能かどうかを設定できます。
- 第1引数に対象のウィジェットを指定します
- 第2引数にTRUEを指定した場合は、対象のウィジェットは使用可能になります。
FALSEを指定した場合は、対象のウィジェットは仕様不可能になります。
-
sep = gtk_separator_tool_item_new();
この関数でツールバーのセパレーター(縦線)を作ります。
-
g_signal_connect(undo, "clicked", G_CALLBACK(undo_redo), label);
ツールボタンが押された時のイベントは "clicked" です。
-
const gchar *name = gtk_widget_get_name(widget);
この関数で引数に指定したウィジェットの名前を取得できます。
-
guchar num = atoi(text);
atoiは C の関数です。引数の文字列を整数に変換した新たな値を作ります。
guchar は、GTKで再定義された unsigned char です。
-
if (strcmp(name, "undo") == 0)
strcmpも C の関数です。第1引数と第2引数の文字列を比較して、
第1引数が大きい場合は 1 を、第2引数が大きい場合は -1 を、
第1引数と第2引数が同じ場合は 0 を返します。
文字の大小は辞書の順序になります。辞書の末尾の方が大きい文字列になります。
GTKには同じ働きをする g_strcmp0 という関数もあります。
-
gchar *str = g_strdup_printf("%d", num);
g_strdup_printf関数は、変換指定子で変換された新しい文字列を作ります。
-
gtk_label_set_text(label, str);
この関数でラベルに表示される文字列を設定します。
- 第1引数に対象となるラベルを指定します
- 第2引数に設定する文字列を指定します
-
g_free(str);
g_strdup_printf関数で作った文字列は、g_free関数で
文字列に割り当てられたメモリーを解放しておいた方が良いです。