본문 바로가기
컴퓨터 관련/Linux || Unix

[GTK+] 3. GTK+ Layout 관리

by _BlankSpace 2017. 6. 17.

 0. 들어가기 전.. 

이번에 다룰 부분은 GTK+ 프로그래밍을 할 때, Layout을 관리하기 위한 함수들을 정리하려고 합니다.

이 부분은 자바의 swing과 같은 GUI를 프로그래밍할 때, 꼭 필요한 부분이라고 할 수 있습니다.


GTK+ 도 역시, GUI 프로그래밍이므로, layout을 관리하기 위한 여러 가지의 함수들이 있습니다.

지금부터 그러한 함수들을 소개하도록 하겠습니다.


 1. GtkFixed 

먼저, GtkFixed 함수는 고정된 위치와 사이즈로 child widget[각주:1]을 위치시키는 기능을 합니다.

다시 말하자면, 이 기능은 프로그램을 개발하는 사람 마음대로 widget의 위치를 정할 수 있다는 뜻입니다.

예제를 통해 설명을 이어가겠습니다.


GtkFixedEx.c

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
#include <gtk/gtk.h>
 
int main(int argc, char* argv[]) {
    GtkWidget* window;
    GtkWidget* fixed;
    GtkWidget* btn1;
    GtkWidget* btn2;
    GtkWidget* btn3;
 
    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), 300200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);
    btn1 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), btn1, 15050);
    gtk_widget_set_size_request(btn1, 8030);
    btn2 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), btn2, 1515);
    gtk_widget_set_size_request(btn2, 8030);
    btn3 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), btn3, 100100);
    gtk_widget_set_size_request(btn3, 8030);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
cs

위와 같이 fixed 방법으로 레이아웃을 설정하면 application의 window가 resize해도 버튼의 자리나 크기는 변하지 않습니다. 즉, 해당 widget은 고정된다고 생각하면 될 것입니다.


fixed = gtk_fixed_new();

- get_fixed_new() 함수는 GtkFixed 컨테이너에 생성한다.

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

- 첫 번째 버튼은 150, 50 위치에 고정된다.

gtk_widget_set_size_request(btn1, 80, 30);

- 첫 번째 버튼의 크기를 재조정한다.


 2. GtkAlignment 

GtkAlignment는 widget의 정렬을 제어하는 기능입니다. 또한, scailing도 관리할 수 있습니다.


GtkAlignment.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <gtk/gtk.h>
 
int main(int argc, char* argv[]) {
    GtkWidget* window;
    GtkWidget* align;
    GtkWidget* lbl;
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "GtkAlignment");
    gtk_window_set_default_size(GTK_WINDOW(window), 300200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);
    align = gtk_alignment_new(0100);
    lbl = gtk_label_new("bottom-left");
    gtk_container_add(GTK_CONTAINER(align), lbl);
    gtk_container_add(GTK_CONTAINER(window), align);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
cs

예제를 실행해보시면, bottom-left라는 레이블이 정렬된 것을 보실 수 있습니다. 이러한 효과를 얻고자 할 때, 사용하는 함수입니다.


align = gtk_alignment_new(1, 1, 1, 1);

- gtk_alignment_new()는 GtkAlignment 컨테이너를 생성합니다.

- 파라미터는 0부터 1까지의 값으로 설정할 수 있습니다.

- 첫 번째 인자 : horizontal alignment 0 < a < 1

- 두 번째 인자 : vertical alignment 0 < a < 1

- 세 번째 인자 : horizontal scale, 수평으로 사용되지 않은 공간을 채웁니다,

- 네 번째 인자 : vertical scale, 수직으로 사용되지 않은 공간을 채웁니다.

lbl = gtk_label_new("bottom-left");

- gtk_label_new() 함수는 label widget을 생성합니다.

* gtk_container_add(GTK_CONTAINER(align), lbl);

- GtkAlignment 컨테이너에 label을 더합니다.

* gtk_container_add(GTK_CONTAINER(window), align);

- window에 alignment 컨테이너를 위치시킵니다.


 3. GtkVBox, GtkHBox

이 기능은 레이아웃 중에서, 가장 많이 쓰는 레이아웃 방법이라고 생각합니다. 저 역시도, 이 방법을 자주 사용하여 프로그램을 구현했던 기억이 남습니다.


- GtkVBox는 수평 박스 컨테이너입니다. 하나의 칼럼에 chile widget을 놓습니다.

- GtkHBox는 수직 박스 컨테이너입니다. 하나의 열에 chile widget을 놓습니다.


GtkVBoxEx.c

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
#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), 230250);
    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(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
cs

위의 예제를 실행해보셨나요? 그럼 흔하게 볼 수 있는 버튼 위젯들이 가지런히 놓여있는 것을 보실 수 있습니다.

이 예제는 vbox를 이용하였으므로, 위젯들이 하나의 칼럼에 가지런히 놓이면서, 밑으로 나열되는 것을 볼 수 있습니다.


그렇다면, hbox를 이용한다면 어떨까요? 당연히, 하나의 열에 자식 위젯들이 놓이겠습니다. 이 예제는 vbox 대신에 hbox를 사용하면 되는 것이므로 궁금하신 분들은 직접 해보시기 바랍니다.


vbox = gtk_vbox_new(TRUE, 1);

- gtk_vbox_new() 함수는 GtkVBox 컨테이너를 생성합니다.

- 첫 번째 인자는 homogeneous 인자로 TRUE로 설정하면, 모든 버튼은 같은 사이즈로 설정됩니다.

- 두 번째 인자는 spacing. 여백의 크기라고 생각하면 되겠습니다.

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

- 첫 번째 인자 : box container

- 두 번째 인자 : child widget

- 세 번째 인자 : expand

- 네 번째 인자 : fill

- 다섯 번째 인자 : padding

- expand가 FALSE이면 fill 인자는 효과가 없습니다. 만약 homogeneous가 TRUE이면 expand는 효과가 없습니다. 이 부분은 직접 테스트하면서 하시는 것이 가장 효과적으로 학습하시는 데 도움이 되실 것입니다.


 4. GtkTable 

GtkTable은 이름에서 알 수 있는 것처럼 테이블 형태로 열과 행을 배치할 수 있는 함수입니다.


GtkTableEx.c

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
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
    int i;
    int j;
    int pos = 0;
    GtkWidget *window;
    GtkWidget *table;
    GtkWidget *button;
    gchar *values[20= { "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), 200200);
    gtk_window_set_title(GTK_WINDOW(window), "GtkTable");
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);
    table = gtk_table_new(45, TRUE);
    gtk_table_set_row_spacings(GTK_TABLE(table), 1);
    gtk_table_set_col_spacings(GTK_TABLE(table), 1);
    for (i = 0; i < 4; i++) {
    for (j = 0; j < 5; 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(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
cs

예제를 실행하시면, 아주 간단한 계산기 형태로 widget들이 배치된 것을 확인할 수 있습니다. 이처럼 테이블 형태로 위젯들을 배치하고자 할 때, 이 함수를 사용하시면 되겠습니다.


table = gtk_table_new(4, 5, TRUE);

- GtkTable widget을 4열 5행으로 만듭니다.

- 세 번째 파라미터가 TRUE이면 모든 테이블의 셀은 가장 큰 widget에 포함하는 셀의 사이즈에 맞추어집니다.

gtk_table_set_row_spacings(GTK_TABLE(table), 2);

gtk_table_set_col_spacings(GTK_TABLE(table), 2);

- 테이블의 열과 행 공간을 설정합니다.

gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );

- 동일한 padding과 expansion 옵션으로 table 컨테이너에 child를 더합니다.


 5. 추가적으로 도움이 되는 함수들.. 

separator

- GtkWidget* gtk_hseparator_new ()

- GtkWidget* gtk_vseparator_new ()


separator는 화면에 수평 또는 수직선을 만드는 기능을 합니다. 수평과 수직에 따라서 따로 함수가 나뉘어 지므로, 시의적절하게 사용하시면 되겠습니다.


예제는 https://developer.gnome.org/gtkmm-tutorial/stable/index.html.en 를 참고하였습니다.

해당 예제는 다음 사이트를 참고하시기 바랍니다.

https://github.com/blankspace-dev/C-/blob/master/2017/06/17/


제 글이 도움이 되셨거나 공감이 되시는 부분이 있으셨다면, 밑에 있는 공감 버튼 한 번씩 꾸욱 눌러주시면 감사하겠습니다.


공감 버튼은 저에게 큰 도움이 됩니다. 감사합니다.

  1. child widget는 말 그대로 상위 위젯보다 하위에 위치하는 위젯들을 말합니다 [본문으로]

'컴퓨터 관련 > Linux || Unix' 카테고리의 다른 글

[GTK+] 5. GTK+ 이벤트  (0) 2017.06.17
[GTK+] 4. GTK+ 컨테이너 Widget  (2) 2017.06.17
[GTK+] 2. GTK+ 기본 예제  (0) 2017.06.12
[GTK+] 1. GTK+ 소개  (0) 2017.06.11
[GTK+] GTK를 들어가면서 (목차)  (0) 2017.06.09

댓글