GTK+ — 3. Керування позиціонуванням віджетів

Лютий 8th, 2009

У цій “лекції” я спробую пояснити, яким чином додавати на вікно нові віджети, та організувати їхнє бажане для вас позиціонування на ньому.

Власне, річ ось у чім — у GTK+, як і в усіх інших бібліотеках графічних віджетів для UNIX ви не можете (взагалі то можете, але про це, можливо, згодом) тупо накидати будь які віджети (кнопки, мітки, чекбокси, едітбокси, тощо) на форму, встановити зручні для вас розміри і місцерозташування цих віджетів, як, скажімо, у VLC.

UNIX’ові бібліотеки графічних віджетів використовують інших підхід до розміщення елементів на формі. Елементи розміщуються не лише по відношенню до верхнього лівого кута. Їхній розмір ще й задається по відношенню до висоти і ширини форми.

Тобто, якщо ви розмістите на формі лиш одну кнопку, то вона, за замовчуванням, матиме висоту і ширину рівну, відповідно, висоті і ширині форми. Не лякайтесь, ви звісно ж, можете чітко задати позицію та розміри кнопки, однак, даний підхід має низку переваг. Сподіваюсь, пояснити вам їх по ходу…

GtkFixed

Даний контейнер поміщає віджети у чітко фіксовані позиції і задає для них чітко фіксовані розміри. Даний контейнер не виконує автоматичну схему управління позицією та розміром віджетів. За звичай, він використовується досить рідко, наприклад, у програмах, де можна змінювати розміри віджетів або ж міняти їхню позицію.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <gtk/gtk.h>
 
 
int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
 
    GtkWidget *button1;
    GtkWidget *button2;
    GtkWidget *button3;
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
    gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);
 
    button1 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
    gtk_widget_set_size_request(button1, 80, 35);
 
    button2 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
    gtk_widget_set_size_request(button2, 80, 35);
 
    button3 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
    gtk_widget_set_size_request(button3, 80, 35);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}

У даному прикладі, ми створюємо три кнопки, і поміщаємо їх на чітко вказані координати. Коли ми змінюємо розміри вікна, кнопки залишаються на своїх місцях.

Тут ми створюємо віджет контейнер GtkFixed:

fixed = gtk_fixed_new();

А тут, за допомогою функції gtk_fixed_put() поміщаємо першу кнопку у позиц

gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);

gtkfixed

GtkVBox

GtkVBox — контейнер для вертикального вирівнювання віджетів. Він поміщає кожен дочірній віджет в окрему комірку. GtkHBox — дуже простий контейнер.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <gtk/gtk.h>
 
int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *vbox;
 
    GtkWidget *settings;
    GtkWidget *accounts;
    GtkWidget *loans;
    GtkWidget *cash;
    GtkWidget *debts;
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
    gtk_window_set_title(GTK_WINDOW(window), "GtkVBox");
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);
 
    vbox = gtk_vbox_new(TRUE, 1);
    gtk_container_add(GTK_CONTAINER(window), vbox);
 
    settings = gtk_button_new_with_label("Settings");
    accounts = gtk_button_new_with_label("Accounts");
    loans = gtk_button_new_with_label("Loans");
    cash = gtk_button_new_with_label("Cash");
    debts = gtk_button_new_with_label("Debts");
 
    gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), accounts, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), loans, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), cash, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), debts, TRUE, TRUE, 0);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}

У даному прикладі, ми пакуємо п’ять кнопок в одну комірку, кожна. Якщо ми змінимо розміри вікна, дочірні віджети також мінятимуть свій розмір.

Створюємо віджет GtkVBox:

vbox = gtk_vbox_new(TRUE, 1);

Параметр homogeneous ми встановили у TRUE. Це означає, що усі наші кнопки матимуть однаковий розмір. Відстань між віджетами буде рівною 1 пікселю.

gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);

А тут ми “запакували” кнопку settings до контейнера. Перші два параметри — це ім’я контейнера та віджета. Про інші три читайте в документації (ага, її тре читати!).

gtkvbox

GtkTable

Як не дивно, контейнер GtkTable організовує віджети у вигляді таблиці.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <gtk/gtk.h>
 
int main( int argc, char *argv[])
{
    GtkWidget *window;
 
    GtkWidget *table;
    GtkWidget *button;
 
    char *values[16] = { "7", "8", "9", "/",
        "4", "5", "6", "*",
        "1", "2", "3", "-",
        "0", ".", "=", "+"
    };
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 250, 180);
    gtk_window_set_title(GTK_WINDOW(window), "GtkTable");
 
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);
 
    table = gtk_table_new(4, 4, TRUE);
    gtk_table_set_row_spacings(GTK_TABLE(table), 2);
    gtk_table_set_col_spacings(GTK_TABLE(table), 2);
 
    int i = 0;
    int j = 0;
    int pos = 0;
 
    for (i=0; i < 4; i++) {
        for( j=0; j < 4; j++) {
            button = gtk_button_new_with_label(values[pos]);
            gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
             pos++;
        }
    }
 
    gtk_container_add(GTK_CONTAINER(window), table);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}

У цьому прикладі ми створили набір кнопок, які матимуть вигляд калькулятора.

Створюємо віджет GtkTable розміром 4 на 4 комірки:

table = gtk_table_new(4, 4, TRUE);

Встановлюємо відстань між рядками і стовпцями рівною 2-м пікселям:

gtk_table_set_row_spacings(GTK_TABLE(table), 2);
gtk_table_set_col_spacings(GTK_TABLE(table), 2);

А тут створюємо 16 кнопок, і пакуємо їх за допомогою GtkTable:

    for(i=0; i < 4; i++) {
        for(j=0; j < 4; j++) {
            button = gtk_button_new_with_label(values[pos]);
            gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
            pos++;
        }
    }

gtktable

GtkAlignment

Контейнер GtkAlignment контролює вирівнювання і розмір своїх дочірніх віджетів.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <gtk/gtk.h>
 
int main( int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *ok;
    GtkWidget *close;
 
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *halign;
    GtkWidget *valign;
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 350, 200);
    gtk_window_set_title(GTK_WINDOW(window), "GtkAlignment");
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 
    vbox = gtk_vbox_new(FALSE, 5);
 
    valign = gtk_alignment_new(0, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(vbox), valign);
    gtk_container_add(GTK_CONTAINER(window), vbox);
 
    hbox = gtk_hbox_new(TRUE, 3);
 
    ok = gtk_button_new_with_label("OK");
    gtk_widget_set_size_request(ok, 70, 30);
    gtk_container_add(GTK_CONTAINER(hbox), ok);
    close = gtk_button_new_with_label("Close");
    gtk_container_add(GTK_CONTAINER(hbox), close);
 
    halign = gtk_alignment_new(1, 0, 0, 0);
    gtk_container_add(GTK_CONTAINER(halign), hbox);
 
    gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}

У даному прикладі, ми помістили дві кнопки у правий нижній кут вікна. Для досягнення цієї мети, ми використовуємо одну горизонтальний контейнер, і два контейнери alignment.

Створюємо віджет контейнеру:

valign = gtk_alignment_new(0, 1, 0, 0);

А тут пакуємо віджет до контейнера:

gtk_container_add(GTK_CONTAINER(vbox), valign);

Тут ми поміщаємо віджет контейнера alignment до віджета контейнера вертикального вирівнювання:

hbox = gtk_hbox_new(TRUE, 3);
 
ok = gtk_button_new_with_label("OK");
gtk_widget_set_size_request(ok, 70, 30);
gtk_container_add(GTK_CONTAINER(hbox), ok);
close = gtk_button_new_with_label("Close");
gtk_container_add(GTK_CONTAINER(hbox), close);

Створюємо GtkHBox, і покуємо у нього дві кнопки:

halign = gtk_alignment_new(1, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), hbox);
 
gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);

Ми створили контейнер alignment, який розміщатиме свої дочірні віджети зправа. Потім ми додали контейнер GtkHBox до контейнера alignment, і запакували контейнер alignment до контейнера GtkVBox. Ми повинні пам’ятати про те, що контейнер alignment приймає лише один дочірній віджет. Ось чому ми повинні використовувати box’и.

gtkalignment

Використано матеріали: http://zetcode.com/tutorials/gtktutorial/gtklayoutmanagement/

Leave a Reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes