Привіт усім. Сьогодні ми розглянемо створення меню для програми за допомогою віконної бібліотеки GTK+. Хіба можна уявити собі програму без меню? Але перш ніж продовжувати читати, перегляньте мою попередню статтю про створення вікон в GNOME/GTK.

Загальна структура меню програми

Загальну структуру упаковування меню вікна (не враховуючи інші віджети), можна уявити наступним чином: MenuGlobalStructure

Створення і упаковування об'єктів

Для створення панелі меню найвищого рівня використовують функцію
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
Можна отримати результат: gtk_window_with_menu
Категорії: