Blog | Tag | Local | Guest | Login | Write |  RSS
Packing Widget _ Table Packing


1. Table을 이용한 Packing

저번것과 같은 Packing이지만, Box를 이용한 Packing이 아닌  테이블을 이용한 것을 설명하려합니다.. 이것은 어떤 상황에서 아주 유용할 것입니다. 테이블을 이용해서 우리는 widget을 넣어둘 격자판을 만들게 됩니다. 그 widget 들은 우리가 설정하는대로 얼마든지 공간을 가지게 될 것입니다.
 
물론 먼저 봐야 할 것은 어떠한 함수가 쓰이는지 봐야겠죠? 그것은 바로.. gtk_table_new 함수입니다.
GtkWidget* gtk_table_new (gint rows,
                          gint columns,
                          gint homogeneous);
첫번째 인자는 테이블에 만들 행의 갯수이고, 두번째는 당연히 열의 갯수입니다.
인자 homogeneous는 테이블의 박스들의 크기가 어떻게 되어야 하는지를 결정 합니다. 이것이 TRUE라면 테이블의 박스들은 그 테이블에서 가장 큰 widget의 크기에 따르게 됩니다. 또 FALSE라면 각 박스들은 같은 행에서 가장 높은 widget의 높이를, 그리고 같은 열에서는 가장 넓은 widget의 너비를 따르게 됩니다.
각 행과 열은 0에서 n까지 차지하게 된다. 여기서 n은 gtk_table_new를 호출할 때 결정된 숫자입니다. 그래서, 만약 우리가 행=2 그리고 열=2, 이렇게 설정하게 되면 구조는 이렇게 됩니다. 

 0               1                2
0+----------+----------+
  |           |           |
1+----------+----------+
  |           |           |
2+----------+----------+

좌표계는 왼쪽 위에서 출발하는 것을 주의하자. 각각의 박스안에 widget을 놓으려면 다음 함수를 이용합니다.

void gtk_table_attach (GtkTable      *table,
                       GtkWidget     *child,
                       gint           left_attach,
                       gint           right_attach,
                       gint           top_attach,
                       gint           bottom_attach,
                       gint           xoptions,
                       gint           yoptions,
                       gint           xpadding,
                       gint           ypadding);

첫번째 인자 table은 우리가 만든 테이블이고 두번째 child는 이 테이블에 놓으려고 하는 widget입니다.
왼쪽과 오른쪽의 attach라는 인자들은 widget을 놓을 위치와 이용할 박스의 갯수를 결정합니다. 만약 우리의 2x2 테이블의 오른쪽 아래 칸에 위치한 버튼을 원한다면, 그리고 그 요소만 가득채우기를 원한다면, left_attach=1, right_ attach=2, top_attach=1, bottom_attach=2, 이렇게 되어야 합니다.
이제, 우리의 2x2 테이블의 첫번째 행 전체를 선택했다면, left_attach=0, right_attach=2, top_attach=0, bottom_attach=1 이라고 하면 됩니다.
인자 xoption과 yoption은 패킹 옵션을 정하기 위한 것으로, 여러가지의 옵션을 주기 위해서 OR 연산자를 쓸 수 있습니다.

이 옵션들은 다음과 같습니다.
• GTK_FILL - GTK_FILL이 설정되면 테이블 박스가 widget보다 클 때 widget은 사용가능한 모든 공간으로 확대됩니다.
• GTK_SHRINK - 테이블 widget이 더 적은 공간을 차지하도록 되었을 때 widget 은 정상적으로 윈도의 아래쪽으로 밀려나서 일부가 보이지 않게 됩니다. 만약 GTK_SHRINK가 설정되면 widget은 자동으로 줄어들어 내부에 꼭 맞게 됩니다.
• GTK_EXPAND - 이것이 설정되면 테이블은 윈도의 남는 공간으로 꽉 차게 확대됩니다.
패딩은 박스 안에서처럼, 픽셀 단위로 뚜렷한 영역을 widget 주위에 만들어 줍니다.
gtk_table_attach()는 수많은 옵션을 가지고 있다. 그래서 이런 shortcut이 있다.

void gtk_table_attach_defaults (GtkTable   *table,
                                GtkWidget  *widget,
                                gint        left_attach,
                                gint        right_attach,
                                gint        top_attach,
                                gint        bottom_attach);

X와 Y 옵션은 디폴트로 GTK_FILL|GTK_EXPAND, 그리고 X와 Y의 패딩은 0 입니다. 나머지 인자들은 이전의 함수와 같습니다.
또한 gtk_table_set_row_spacing()과 gtk_table_set_col_spacing()이란 함수도 있습니다. 이것은 주어진 행 또는 열에 대해 spacing을 설정합니다.

void gtk_table_set_row_spacing (GtkTable      *table,
                                gint           row,
                                gint           spacing);

그리고

void       gtk_table_set_col_spacing  (GtkTable      *table,
                                       gint           column,
                                       gint           spacing);

어떤 열에 대해서 space는 열의 오른쪽으로, 그래고 행에 대해서는 행의 아래쪽 으로 주어진다는 것을 기억하고 있어야 합니다.
모든 행과 열에 대한 일관된 spacing은 다음 두 함수를 사용합니다.

void gtk_table_set_row_spacings (GtkTable *table,
                                 gint      spacing);

void gtk_table_set_col_spacings (GtkTable  *table,
                                 gint       spacing);

이 두 함수는 마지막 행과 마지막 열에 대해서는 spacing을 하지 않는다는 것을 기억하고 있어야 합니다.

2. Table Packing의 예제
우리는 오늘 2x2의  Table 안에 3개의 버튼을 packing할 것입니다. 물론, 윈도우 안에 전부 있어야겠죠? ㅋㅋ 위의 Table Packing을 설명할때 사용한 테이블을 참고하면 가로 세로 2줄씩 생기겠죠? 첫번째 줄에는 Button을 2개 위치 시키고 두번째 줄에는 버튼을 하나만 위치 시킬 것입니다. 그러면 아래와 같은 화면이 나오겠죠? ^ ^


그럼 이제 이녀석의 소스를 볼까요?


/* table.c */
#include <gtk/gtk.h>

/* 우리의 callback.이 함수로 넘겨지는 data는 stdout으로 출력됩니다. */
void callback (GtkWidget *widget, gpointer data)
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

/* 이 callback 프로그램을 종료합니다 */
void delete_event (GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
}

int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;

    gtk_init (&argc, &argv);

    /* 새로운 윈도우를 만듭니다. */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* 윈도우의 제목을 정해줘야겠죠? */
    gtk_window_set_title (GTK_WINDOW (window), "Table");

    /* GTK를 곧장 종료시키는 delete_event 핸들러를 정합니다. */
    gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                        GTK_SIGNAL_FUNC (delete_event), NULL);

    /* 윈도의 border width를 정합니다. */
    gtk_container_border_width (GTK_CONTAINER (window), 20);

    /* 2x2의 테이블을 만듭니다. */
    table = gtk_table_new (2, 2, TRUE);

    /* 테이블을 윈도에 놓습니다. */
    gtk_container_add (GTK_CONTAINER (window), table);

    /* 첫 버튼을 만듭니다. */
    button = gtk_button_new_with_label ("button 1");

    /* 버튼이 눌리면 "button 1"을 인수로 해서 "callback" 함수를 호출 합니다. */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
              GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");


    /* 첫 버튼을 테이블 왼쪽 제일 위에 놓아줍니다. */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);

    gtk_widget_show (button);

    /* 두번째 버튼을 만듭니다. */

    button = gtk_button_new_with_label ("button 2");

    /* 버튼이 눌리면 "button 2"을 인수로 해서 "callback" 함수를 부릅니다. */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
              GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");

    /* 두번째 버튼을 테이블 오른쪽 제일 위에 놓습니다. */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);

    gtk_widget_show (button);

    /* 세번째 "Quit" 버튼을 만듭니다. */
    button = gtk_button_new_with_label ("Quit");

    /* 버튼이 눌리면 "delete_event" 함수를 호출해서 프로그램을 끝냅니다. */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (delete_event), NULL);

    /* 세번째 "Quit" 버튼을 테이블의 아랫행의  두열에 놓습니다. */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);

    gtk_widget_show (button);

    gtk_widget_show (table);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
}


위의 소스를 한번 보셨는지요? 매우 쉽죠? 버튼을 만들고 올려 놓는 방법만 안다면 3개가 아니라 300개도 만들수 있겠죠? 물론, 좌표를 잘 계산 해야 하지만요 ^ ^ 근대, 저 이녀석 사랑할 것 같아요 ㅋ 요즘 재미있어졌거든요 ㅋ 우왕우왕~
다같이 재미있게해보아요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ