Привіт усім.
Сьогодні ми розглянемо створення меню для програми за допомогою віконної бібліотеки GTK+. Хіба можна уявити собі програму без меню? Але перш ніж продовжувати читати, перегляньте мою попередню статтю про створення вікон в GNOME/GTK.
Загальна структура меню програми
Загальну структуру упаковування меню вікна (не враховуючи інші віджети), можна уявити наступним чином:
Створення і упаковування об'єктів
Для створення панелі меню найвищого рівня використовують функцію
GtkWidget* gtk_menu_bar_new (void) ;
У об'єкт, який повертає дана функція, необхідно упаковувати усі необхідні структури меню, які будуть створюватися у програмі. Елементи у ній розміщуються горизонтально.
Для того, щоб створити панель субменю, на якій будуть розміщуватися підпункти меню, необхідно скористуватися функцією gtk_menu_new, оголошення якої виглядає наступним чином:
GtkWidget* gtk_menu_new (void) ;
В подальшому, до об'єкта створеного даною функцією, необхідно приєднувати дочірні елементи меню або/і підпункти дочірніх елементів. Упаковування пунктів виконується без використання контейнерів (себто box-ів).
Для того, щоб створити пункт меню, необхідно викликати функцію:
GtkWidget* gtk_menu_item_new_with_label (const gchar *label) ;
Їй, як бачимо, передається один параметр — текстова мітка, яка буде показуватись на пункті меню і вичерпно повідомлювати, які дії ним виконуються.
Далі нам необхідно упакувати пункти меню в панель меню за допомогою функції, яка виглядає наступним чином:
void gtk_menu_attach (GtkMenu *menu,
GtkWidget *child,
guint left_attach,
guint right_attach,
guint top_attach,
guint bottom_attach) ;
Як Ви вже напевно здогадались, першим і другим параметром їй передаються об'єкти створені за допомогою функцій gtk_menu_new і gtk_menu_item_new_with_label. Наступні параметри не так очевидні, як би хотілось. Вони (left_attach, right_attach, top_attach і bottom_attach) призначені для вказування координат комірки (або комірок) в таблиці, яку буде займати пункт меню. Наприклад, якщо ви вкажете в якості параметра left_attach значення “0”, а в якості right_attach буде значення “2”, тоді ви отримаєте панель меню, яка буде мати два стовпця, і даний елемент буде займати усі створені стовпці (якщо усі інші приймуть дані параметри як “0” і “1”, вони будуть займати тільки одну колонку і в результаті являтись вужчими по відношенню до даного елементу). Якщо Ви створювали перший елемент в якості вказівника на об'єкт GtkWidget, тоді Вам допоможе макрос GTK_MENU, який зробить перетворення типу з GtkWidget до GtkMenu за Вас.
Для того щоб упакувати усю структуру пункта меню разом з його дочірніми панелями і підпунктами використовують функцію:
void gtk_menu_shell_append (GtkMenuShell *menu_shell, GtkWidget *child) ;
Перший параметр це вказівник на об'єкт створений за допомогою gtk_menu_bar_new. Наступний параметр — це вказівник на об'єкт створений за допомогою функції gtk_menu_item_new або gtk_menu_item_new_with_label.
Програма
Код простої програми, який використовує вищенаведену структуру і функції може виглядати наступним чином:
#include <gtk/gtk.h> /* увесь GTK+ */
/* головна функція програми */
int main (int argc, char** argv)
{
/* Дуже важливо! Перед використанням бібліотеки, її необхідно
** ініціалізувати, в іншому випадку ваша програма не буде працювати */
gtk_init (&argc, &argv) ;
/* вказівники на об'єкти (структури) */
GtkWidget* window, /* Вікно */
* menu_bar, /* панель всього меню */
* mi_program, /* меню "Програма" */
* mp_program, /* панель меню "Програма" */
* mi_about, /* підпункт "Про програму" */
* mi_quit, /* підпункт "Вихід" */
* text_view, /* текстовий віджет (для демонстрації) */
* v_box ; /* головний контейнер */
/*
** Створюємо примірники.
*/
/* створюємо віджет найвищого рівня - вікно */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL) ;
/* панель для розміщення меню */
menu_bar = gtk_menu_bar_new () ;
/* пункт меню "Програма" */
mi_program = gtk_menu_item_new_with_label ("Програма") ;
/* панель меню "Програма" */
mp_program = gtk_menu_new () ;
/* підпункти меню "Програм" */
mi_about = gtk_menu_item_new_with_label ("Про програму") ;
mi_quit = gtk_menu_item_new_with_label ("Вихід") ;
/* демонстраційний віджет, який заповнить вільний простір */
text_view = gtk_text_view_new () ;
/* контейнер для упаковування */
v_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1) ;
/*
** Велике Упаковування.
*/
/* приєднюємо підпункти меню до панелі меню "Програма" */
gtk_menu_attach (GTK_MENU(mp_program), mi_about, 0, 1, 0, 1) ;
gtk_menu_attach (GTK_MENU(mp_program), mi_quit, 0, 1, 1, 2) ;
/* упаковуємо панель меню до пункта меню "Програма" */
gtk_menu_item_set_submenu((GtkMenuItem*)mi_program, mp_program) ;
/* упаковуємо сам пункт меню "Програма" до панелі меню */
gtk_menu_shell_append ((GtkMenuShell*)menu_bar, mi_program) ;
/* упаковуємо усе в контейнер*/
gtk_box_pack_start (GTK_BOX(v_box), menu_bar, FALSE, FALSE, 1) ;
gtk_box_pack_start (GTK_BOX(v_box), text_view, TRUE, TRUE, 1) ;
/* головний контейнер у головне вікно */
gtk_container_add (GTK_CONTAINER(window), v_box) ;
/* встановлюємо типові розміри вікна window в 500*500 пікселів */
gtk_window_set_default_size (GTK_WINDOW(window), 500, 500) ;
/* встановлюємо заголовок вікна */
gtk_window_set_title (GTK_WINDOW(window),"Програма з простим меню") ;
/* приєднюємо сигнал на закриття вікна до стандартного обробника */
g_signal_connect (window, "destroy", G_CALLBACK(gtk_main_quit), NULL) ;
/* для меню "Вихід" також встановимо стандартний обробник на закриття вікна */
g_signal_connect (mi_quit, "activate", G_CALLBACK(gtk_main_quit), NULL) ;
/* показуємо увесь віджет window */
gtk_widget_show_all (window) ;
/* запускаємо головний цикл gtk-програми */
gtk_main () ;
/* знищуємо вікно і його елементи, і вивільняємо пам'ять */
gtk_widget_destroy (window) ;
/* вихід з програми */
return 0 ;
}
Після компіляції і виконання даної програми (компілятор GCC; ім'я файлу вихідного коду: “menu_simple.cxx”; вихідний виконуваний файл: “file”) командою:
g++ menu_simple.cxx -o file `pkg-config --cflags --libs gtk+-3.0`
./file
Можна отримати результат: