Blog | Tag | Local | Guest | Login | Write |  RSS
GTK+에 해당되는 글 9건
2008.12.08 :: GTK+의 Menu Widget
2008.11.10 :: GTK+ "Hello World"
2008.10.20 :: GTK 설치 및 컴파일 4
2008.10.13 :: GTK와 GDK
GTK+의 Menu Widget

오늘은 Menu를 수동적으로 만들어 보겠습니다. menu를 만드는 방법은 두가지가 있습니다. 두가지 방법은 menu factory를 사용하는 방법과 고전적인 방법이 있습니다. 고전적인 방법을 먼저 알아보는 것이 공부하는데 도움이 되겠죠? ^ ^;
그렇다고 menu factory를 사용하다고 나쁘다는 것은 아닙니다. 두가지 방법은 장단점이 있으니까 사용하실때는 그때 그때 상황에 맞는 장점을 이용하는 것이 좋겠지요?

수동적인 방법으로 몇 가지 wrapper 함수들을 써 가며 메뉴를 만드는 것이 유용성에 있어서 훨씬 유리함에도 불구하고, menufactory를 이용하는 방법은 훨씬 사용하기 쉽고 또 새로운 메뉴를 추가하기도 쉽습니다. Menufactory를 이용하게 되면, 메뉴에 이미지라든가 '/'를 쓰는 것이 불가능해집니다.

위에 말씀 드렸듯이, 오늘은 수동적으로 menu를 만드는 방법을 선보이겠습니다.

메뉴바와 하위메뉴(submenu)들를 만드는데 쓰는 세가지 widget이 있습니다.

메뉴 아이템(menu item) : 사용자가 선택하는 것. (예: 'Save')
메뉴(menu) : 메뉴 아이템들의 컨테이너.
메뉴바(menubar) : 각각의 메뉴들을 포함하는 컨테이너.

메뉴 아이템 widget이 두가지 다른 용도로 쓰일 수 있다는 점때문에 약간 복잡한 면이 있습니다. 메뉴 아이템은 단순히 메뉴 위에 놓일 수도 있고 또는 메뉴바 위에 놓여서 선택되었을 때 특정 메뉴를 활성화시키도록 쓰일 수도 있습니다.

메뉴와 메뉴바를 만들기 위해 쓰이는 함수들을 살펴보자. 이 첫번째 함수는 새로운 메뉴바를 만들기 위해 쓰입니다.
GtkWidget *gtk_menu_bar_new()
이것은 이름 그대로 새로운 메뉴바를 만듭니다. 버튼과 마찬가지로, 우리는 이것을 윈도에 패킹하기 위해 gtk_container_add를 이용할수도 있고, 또는 박스에 패킹하기 위해 box_pack 함수들을 이용할 수 있습니다. 즉,  버튼과 같다고 보면 됩니다.

GtkWidget *gtk_menu_new();
이 함수는 새로운 메뉴를 향한 포인터를 리턴하는데, 이것은 실제로 보여지지는 않고(gtk_widget_show를 통해) 다만 메뉴 아이템들을 가지고만 있습니다. 이 아래에 나오는 예제를 보며 더 명확히 이해하기를 바랍니다.

이번의 두 함수는 메뉴나 메뉴바 안으로 패킹되는 메뉴 아이템을 만들기 위해 쓰입니다.
GtkWidget *gtk_menu_item_new()
GtkWidget *gtk_menu_item_new_with_label(const char *label)


이 함수들은 보여지기 위한 메뉴를 만들 때 쓰입니다. gtk_menu_new로써 만들어지는 "메뉴"와 gtk_menu_item_new로써 만들어지는 "메뉴 아이템"을 꼭 구별해야 합니다. 메뉴 아이템은 연결된 동작이 있는 실제의 버튼이 될 것이지만, 반면 메뉴는 이것들을 가지고 있는 컨테이너가 될 것입니다.
gtk_menu_new_with_label과 단순한 gtk_menu_new 함수는 여러분이 버튼에 대해 공부한 후에 짐작하는 그대로입니다. gtk_menu_new_with_label은 라벨이 이미 패킹되어 있는 메뉴 아이템을 만들고, gtk_menu_new는 비어있는 메뉴 아이템을 만듭니다.한번 메뉴 아이템을 만들면 반드시 이를 메뉴 안에 넣어야만 합니다. 이는 gtk_menu_append 함수를 이용해서 이루어집니다. 어떤 아이템이 사용자에 의해 선택되었을 때 이를 알아내어 처리하기 위해서는 activate 시그널을 통상적으로 하듯이 연결합니다. 그래서 만일 Open, Save, Quit 옵션을 가진 표준 File 메뉴를 만들고자 한다면 소스 코드는 다음과 같이 됩니다.


file_menu = gtk_menu_new();    /* 메뉴를 보여줄 필요는 없습니다. */

/* 메뉴 아이템들을 만듭니다. */
open_item = gtk_menu_item_new_with_label("Open");
save_item = gtk_menu_item_new_with_label("Save");
quit_item = gtk_menu_item_new_with_label("Quit");

/* 그것들을 메뉴에 붙입니다. */
gtk_menu_append( GTK_MENU(file_menu), open_item);
gtk_menu_append( GTK_MENU(file_menu), save_item);
gtk_menu_append( GTK_MENU(file_menu), quit_item);

/* "activate" 시그널과 callback 함수를 연결합니다. */
gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
                   GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
                   GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");

/* Quit 메뉴 아이템에  exit 함수를 연결합니다. */
gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
                   GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");

/* 이제 메뉴 아이템들을 보여줘야 합니다. */
gtk_widget_show( open_item );
gtk_widget_show( save_item );
gtk_widget_show( quit_item );


여기까지하면 필요한 메뉴는 일단 만든 것입니다. 이제 지금까지 만든 메뉴를 붙일 File 메뉴 아이템과 메뉴바를 만들어야 합니다. 아이템과 메뉴바를 만든면 아래와 같이 됩니다.

menu_bar = gtk_menu_bar_new();
gtk_container_add( GTK_CONTAINER(window), menu_bar);
gtk_widget_show( menu_bar );

file_item = gtk_menu_item_new_with_label("File");
gtk_widget_show(file_item);


이제 file_item을 메뉴와 연결해야 합니다. 이것은 다음 함수를 통해 이루어집니다.
void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, GtkWidget *submenu);

그래서 우리 예제는 다음 코드로 이어집니다.
gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu);


해야할 남은 모든 일은 메뉴를 메뉴바에 붙이는 일이다. 이는 다음 함수를 이용합니다.
void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);

우리가 작성한 코드에서는 다음과 같이 됩니다.
gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );

만일 메뉴들이 help 메뉴가 자주 그러는 것처럼 메뉴바의 오른쪽에 위치하게 하고 싶다면 메뉴바에 메뉴를 붙이기 전에 다음 함수를 쓰면 됩니다. (현재 예제라면 인자로 file_item을 주면 된다.)
void gtk_menu_item_right_justify (GtkMenuItem *menu_item);


메뉴들이 달려있는 메뉴바를 만드는 단계들을 간단히 정리해 보겠습니다. 

gtk_menu_new()를 이용해서 새로운 메뉴를 만듭니다.
gtk_menu_item_new()를 여러번 이용해서 메뉴에 필요한 각각의 메뉴 아이템을 만든다. 그리고 gtk_menu_append()를 이용해서 새 아이템들을 메뉴에 넣습니다.
gtk_menu_item_new()를 사용해서 메뉴 아이템을 하나 만든다. 이 아이템은 자신의 텍스트가 메뉴바 위에 직접 나타나는 root 메뉴 아이템이 됩니다.
gtk_menu_item_set_submenu()를 사용해서 메뉴를 root 메뉴 아이템에 붙입니다.(바로 위 단계에서 만든 메뉴 아이템)
gtk_menu_bar_new()를 이용해서 새로운 메뉴바를 만듭니다. 이 단계는 한 메뉴바 위에 여러 일련의 메뉴를 만들었을 때 한번만 필요합니다.
gtk_menu_bar_append()를 이용해서 메뉴바 위에 root 메뉴를 놓습니다.

팝업메뉴를 만드는 것도 거의 같습니다. 다른 점이 있다면 메뉴는 메뉴바에 의해 자동적으로 붙여지는 것이 아니라, button_press 이벤트로부터 gtk_menu_popup() 함수를 호출함으로써 붙여진다는 것입니다. 이 과정을 따라 설명해보겠습니다.

이벤트 핸들링 함수를 만듭니다. 이것은 아래와 같은 원형을 가져야 합니다.
static gint handler(GtkWidget *widget, GdkEvent *event);
그리고 이것은 메뉴를 팝업시킬 곳을 찾기 위해 이벤트를 이용할 것입니다.
이벤트 핸들러에서는, 만약 이벤트가 마우스 버튼을 누르는 것이라면, 이벤트를 버튼 이벤트로 다루고, gtk_menu_popup()에 정보를 넘겨줍니다.
이 함수를 이용하여 이벤트 핸들러를 widget에 결합시킵니다.
gtk_signal_connect_object(GTK_OBJECT(widget), "event", GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu));
여기서 widget 인자는 우리가 바인딩할 widget이고, handler 인자는 핸들링 함수입니다. 그리고 menu 인자는 gtk_menu_new()로써 만들어진 메뉴입니다. 예제 코드에서 보인대로, 이것은 메뉴바에 붙여져 있는 메뉴가 될 수도 있습니다.

어때요? 설명이 조금 많아서 어려워 보이지만, 따라해보면 금방 이해할 수 있습니다.
오늘은 Menu에 대한 설명을 하였습니다. 다음주에는 위의 내용을 이용하여 하나의 예제를 해보겠습니다.

 


GTK+ Window Widget Paned


안녕하세요. 오늘은 GTK+ widget Paned에 대해서 설명해 보겠습니다. Table을 이용해서 화면을 분할하듯이 paned을 이용해서 분할할 수 있습니다. Paned은 window widget의 한 영역으로 사용자가 크기를 상대적으로 조절하여 두영역으로 나누어서 쓸 수 있습니다.  두 영역 사이에는 handle이 달린 홈이 있고 이를 마우스로 드래그해서 사용자는 원하는 대로 두 영역의 비율을 바꿀 수 있습니다. 이러한 분할은 수평(HPaned)적이거나 수직(VPaned)적이 됩니다.

새 paned window를 만들려면 다음중 하나를 불러 사용합니다.

GtkWidget* gtk_hpaned_new (void)
GtkWidget* gtk_vpaned_new (void)

Paned window widget을 만든 다음에는 나누어진 양쪽에 자식 widget을 주어야 합니다. 이는 다음 함수들을 이용해서 이루어집니다.

void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child)
void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child)
gtk_paned_add1()는 paned 윈도 widget의 왼쪽 혹은 윗쪽에 자식 widget을 더합니다.
gtk_paned_add2()는 반대로 오른쪽 혹은 아랫쪽에 더합니다.

한 예로는 가상적인 E-mail 프로그램의 사용자 인터페이스 일부를 만들어 보려고합니다. 말이 거창할 뿐, 그리 어렵진 않습니다. 앞에 많은 예제를 다루어 봤듯이 GTK+는 반복적인 틀로 만들어지기 때문에 소스만 보아도 이해가 가능할 것입니다.
오늘 만들어 볼 E-mail 프로그램은 E-mail 메시지들의 리스트를 표시하는 윗 부분과 메시지 내용을 표시하는 아랫 부분으로 나누어 집니다. 간단한 프로그램이지만 오늘도 역시 중요한 부분이 있겠죠? 오늘의 중요한 사항은 두가지 입니다. 두가지의 중요한 부분을 집고 넘어 가겠습니다. 두가지 주의해야 할 점은 다음과 같습니다. 텍스트는 텍스트 widget에 이것이 realize되기 전에는 더해질 수 없습니다. 이는 gtk_widget_realize()를 호출해서 이루어지지만 또 다른 방법으로 text를 더하기 위해 "realize" 시그널을 연결할 수도 있습니다. 또한, GTK_SHRINK 옵션을 text 윈도와 스크롤바를 포함하고 있는 테이블 내용 일부에 더해주는 것이 필요합니다. 그래야만 아랫 부분을 작게 만들때 윈도의 바닥이 밀려나는 대신 원하던 부분이 줄어들게 됩니다.

/* paned.c */

#include <gtk/gtk.h>
  
/* "messages"의 리스트를 만듭니다 */
GtkWidget *
create_list (void)
{

    GtkWidget *scrolled_window;
    GtkWidget *list;
    GtkWidget *list_item;
  
    int i;
    char buffer[16];
  
    /* 스크롤바(필요할 때만)가 딸린 스크롤된 윈도를 만듭니다. */
    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                    GTK_POLICY_AUTOMATIC,
                                    GTK_POLICY_AUTOMATIC);
  
    /* 새로운 리스트를 만들어 이를 스크롤된 윈도에 집어넣습니다. */
    list = gtk_list_new ();
    gtk_container_add (GTK_CONTAINER(scrolled_window), list);
    gtk_widget_show (list);
  
    /* 윈도에 메시지 몇개를 더합니다 */
    for (i=0; i<10; i++) {

        sprintf(buffer,"Message #%d",i);
        list_item = gtk_list_item_new_with_label (buffer);
        gtk_container_add (GTK_CONTAINER(list), list_item);
        gtk_widget_show (list_item);

    }
  
    return scrolled_window;
}
  
/* 텍스트 몇개를 텍스트 widget에 더합니다. - 아래 함수는 우리의 윈도가 realize 될
때 불리는 callback합수입니다. gtk_widget_realize로 realize되도록 강제할 수도 있지만
그건 먼저 계층구조의 한 부분이 되어야 할 것입니다.
*/
void
realize_text (GtkWidget *text, gpointer data)
{
    gtk_text_freeze (GTK_TEXT (text));
    gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
    "From: pathfinder@nasa.gov\n"
    "To: mom@nasa.gov\n"
    "Subject: Made it!\n"
    "\n"
    "We just got in this morning. The weather has been\n"
    "great - clear but cold, and there are lots of fun sights.\n"
    "Sojourner says hi. See you soon.\n"
    " -Path\n", -1);
  
    gtk_text_thaw (GTK_TEXT (text));
}
  
/* "message"를 보여주는 스크롤된 텍스트 영역을 만듭니다. */
GtkWidget *
create_text (void)
{
    GtkWidget *table;
    GtkWidget *text;
    GtkWidget *hscrollbar;
    GtkWidget *vscrollbar;
  
    /* 텍스트 위젯과 스크롤바를 갖는 테이블을 만듭니다 */
    table = gtk_table_new (2, 2, FALSE);
  
    /* 텍스트 위젯을 왼쪽 위에 놓습니다. Y 축 방향으로 GTK_SHRINK가 쓰인 것을 주목해야 합니다. */
    text = gtk_text_new (NULL, NULL);
    gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
                      GTK_FILL | GTK_EXPAND,
                      GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
    gtk_widget_show (text);
  
    /* HScrollbar를 왼쪽 아래에 놓습니다. */
    hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
    gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
                      GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
    gtk_widget_show (hscrollbar);
  
    /* VScrollbar를 오른쪽 위에 놓습니다. */
    vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
    gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
                      GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
    gtk_widget_show (vscrollbar);
  
    /* 텍스트 widget이 realize되었을 때 그 widget이 갖고 있는 메시지를 출력해주는 시그널 핸들러를 더합니다. */
    gtk_signal_connect (GTK_OBJECT (text), "realize",
                        GTK_SIGNAL_FUNC (realize_text), NULL);
  
    return table;
}
  
int
main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *vpaned;
    GtkWidget *list;
    GtkWidget *text;

    gtk_init (&argc, &argv);
  
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
    gtk_container_border_width (GTK_CONTAINER (window), 10);
  
    /* vpaned widget을 만들어서 toplevel 윈도에 더합니다. */
  
    vpaned = gtk_vpaned_new ();
    gtk_container_add (GTK_CONTAINER(window), vpaned);
    gtk_widget_show (vpaned);
  
    /* 이제 윈도 두 부분의 내용을 만듭니다. */
  
    list = create_list ();
    gtk_paned_add1 (GTK_PANED(vpaned), list);
    gtk_widget_show (list);
  
    text = create_text ();
    gtk_paned_add2 (GTK_PANED(vpaned), text);
    gtk_widget_show (text);
    gtk_widget_show (window);
    gtk_main ();
    return 0;
}

오늘도 간단한 예제를 해보았습니다. 어떠하였는지요? 정말 길지도 않죠? 처음 배웠던 내용의 기본적인 내용을 뺀다면 정작 프로그램에서 사용하는 내용은 얼마 없죠? GTK+의 매력~~~
 


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개도 만들수 있겠죠? 물론, 좌표를 잘 계산 해야 하지만요 ^ ^ 근대, 저 이녀석 사랑할 것 같아요 ㅋ 요즘 재미있어졌거든요 ㅋ 우왕우왕~
다같이 재미있게해보아요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ


Packing Widget _ Box Packing


안녕하세요.
저번시간에는 아주 간단하지만 중요한 이야기를 했었죠? 저번시간에 이야기했던 Packing에 대해서 좀더 자세히 공부해 볼까 합니다. 우리가 어떤 어플리케이션을 개발하면서, 하나의 윈도우에 하나 이상의 버튼을 놓으려 할 것입니다. 우리의 첫번째 hello world 예제는 하나의 widget만 썼었죠. 그러나 우리가 하나의 윈도우에 더많은 widget을 놓으려 할 때, 어떻게 그들이 놓일 위치를 제어해야 할까? 여기서 바로 "packing"이란 것이 등장한죠!!

1. 박스 packing의 원리
대부분의 은 앞서의 예제에서처럼(저번주 강의) 박스를 만드는 것으로 이루어집니다. 이들은 우리의 widget을 수평 혹은 수직 방향으로 패킹해 넣을 수 있는, 보이지 않는 widget 컨테이너들이었죠. 수평 박스로의 패킹 widget인 경우, object는 호출 하는 방식에 따라 수평으로 왼쪽에서 오른쪽으로 혹은 오른쪽에서 왼쪽으로 삽입 됩니다. 수직 박스에서는 반대로 수직으로 삽입됩니다. 우리는 원하는 효과를 내기 위해 다른 박스들의 안팎에서 어떻게라도 조합해서 사용할 수 있겠죠?
새로운 수평박스를 만들기 위해 우리는 gtk_hbox_new()를, 그리고 수직박스를 위해서는 gtk_vbox_new()를 이용합니다. gtk_box_pack_start()와 gtk_box_pack_end ()는 이런 컨테이너의 내부에 object들을 위치시키기 위해 사용합니다. gtk_box_ pack_start()함수는 수직박스에서는 위에서 아래쪽으로, 그리고 수평박스에서는 왼쪽에서 오른쪽으로 패킹할 것입니다. 그리고 gtk_box_pack_end()는 이와 반대 방향으로 패킹합니다. 이 함수들을 이용함으로써 우리는 오른쪽 또는 왼쪽으로 widget을 정렬할 수 있고, 원하는 효과를 낼 수 있습니다. 우리는 대부분의 예제에서 gtk_box_pack_start()를 이용할 것입니다. Object는 또다른 컨테이너이거나 widget이 될 수 있습니다. 그리고 사실, 많은 widget들은 실제로 버튼을 포함하고 있는 widget 이지만, 우리는 보통 버튼 안의 라벨만을 이용할 것입니다.
이런 함수호출로써, GTK는 우리가 widget을 놓을 위치를 알게되고 따라서 자동적으로 크기를 조절한다든지 또다른 매력적인 일들을 할 수 있게 됩니다. 또한 우리의 widget이 어떻게 패킹되어야 하느냐에 따른 수많은 옵션들도 있습니다. 우리가 상상하듯이, 이런 방식은 widget을 놓고 만드는 데 있어서 상당한 유연성 을 제공해 줍니다. 매우 기특한 녀석이죠? ㅋㅋ 

2. Box에 대해서 좀 더 알아볼까요?
이런 유연성 때문에, GTK에서 박스를 패킹하는 것은 처음엔 혼란스러울지 모릅니다. 많은 옵션들이 있으며, 그들이 어떻게 서로 꿰어 맞춰지는지 바로 알 수는 없을 것입니다. 그러나 결국, 우리는 다섯 가지의 기본적인 스타일을 가지게 됩니다. 


각의 줄은 몇 개의 버튼을 가지고 있는 하나의 수평박스(hbox)를 포함합니다. 함수호출 gtk_box_pack은 이 수평박스에 각각의 버튼을 패킹하는 것을 단축한 것입니다. 각각의 버튼은 이 수평박스에 같은 방법으로 패킹됩니다.
이것은 gtk_box_pack_start함수의 선언이다.

void gtk_box_pack_start (GtkBox    *box,
                         GtkWidget *child,
                         gint       expand,
                         gint       fill,
                         gint       padding);

첫번째 인자는 object를 패킹할 박스고 두번째는 그 object입니다. Object는 여기서 모두 버튼이 될 것이고, 따라서 우리는 박스안에 버튼들을 패킹하게 됩니다.
gtk_box_pack_start() 또는 gtk_box_pack_end()에서의 expand라는 인자가 TRUE 일 때, widget은 여백공간을 가득 채우며 박스에 들어가게 될 것입니다. 그리고 그것이 FALSE라면 widget은 적절히 여백을 두게 된다. 이 expand를 FALSE로 두면 우리는widget의 좌우 정렬을 결정할 수 있습니다. 그렇지 않으면 그들은 박스에 가득차서 gtk_box_pack_start 또는 gtk_box_pack_end 어느 쪽을 이용하든지 같은 효과를 가지게 됩니다.
인자 fill은 TRUE일 때 object 자신의 여백공간을 제어합니다. 그리고 FALSE라면 object 자신의 여백공간을 두지 않습니다. 이것은 expand 인자가 TRUE일 때만 효과가 있어요.

새로운 수평박스를 만들 때는 이런 함수가 있습니다.
GtkWidget * gtk_hbox_new (gint homogeneous,
                          gint spacing);

여기서의 인자 homogeneous는 박스 안의 각 object들이 같은 크기를 가지도록 제어합니다. 즉 수평박스일 경우엔 같은 너비, 수직박스일 경우엔 같은 높이이겠죠? 이것이 세팅되면, gtk_box_pack함수의 expand 인자는 언제나 TRUE가 됩니다.

3. 패킹에 대한 예제 프로그램
/* packbox.c */

#include "gtk/gtk.h"

void
delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
  gtk_main_quit ();
}

/* Button_label들로 이루어진 hbox를 만듭니다.  */
GtkWidget *make_box (gint homogeneous, gint spacing,
                     gint expand, gint fill, gint padding)
{
  GtkWidget *box;
  GtkWidget *button;
  char padstr[80];

  /* 적당한 homogenous와 spacing을 가진 hbox를 만듭니다. */
  box = gtk_hbox_new (homogeneous, spacing);

  /* 적절히 세팅된 버튼들을 만듭니다. */
  button = gtk_button_new_with_label ("gtk_box_pack");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  button = gtk_button_new_with_label ("(box,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  button = gtk_button_new_with_label ("button,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  /* expand의 값에 따르는 라벨을 가진 한 버튼을 만듭니다. */
  if (expand == TRUE)
    button = gtk_button_new_with_label ("TRUE,");
  else
    button = gtk_button_new_with_label ("FALSE,");

  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

    button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  sprintf (padstr, "%d);", padding);

  button = gtk_button_new_with_label (padstr);
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  return box;
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *separator;
  GtkWidget *label;
  GtkWidget *quitbox;
  int which;

  gtk_init (&argc, &argv);

  if (argc != 2) {
    fprintf (stderr, "usage: packbox num, where num is 1, 2, 3.\n");

    /* GTK를 끝내는 부분이며, exit status는 1입니다. */
    gtk_exit (1);
  }

  which = atoi (argv[1]);

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

  /* Main 윈도에 destroy 시그널을 연결시켜 줘야 합니다.  이것은 제대로 된 동작을 위해 매우 중요한 것입니다. */
  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                      GTK_SIGNAL_FUNC (delete_event), NULL);
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  /* 우리는 수평박스들을 패킹해 넣을 수직박스(vbox)를 만듭니다.저번시간에도 말씀 드렸듯이, 스택 구조를 생각하면 될 것입니다. */
  box1 = gtk_vbox_new (FALSE, 0);

  switch (which) {
  case 1:
        /* 새로운 라벨을 만듭니다. */
        label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");

        /* 라벨들을 왼쪽으로 정렬시킵니다. */
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);

        /* 라벨을 수직박스(vbox box1)에 패킹합니다.  */
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);

        /* 라벨을 보여줍니다. */
        gtk_widget_show (label);

        /* make_box 함수를 적절한 인자로써 호출합니다. */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* 하나의 separator를 만듭니다 */
        separator = gtk_hseparator_new ();

        /* separator를 vbox 안으로 패킹합니다.  이들 각각의 widget은 vbox 안으로 패킹되므로, 수직 방향으로 쌓일 것입니다. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        /* 또다른 라벨을 만들어 그것을 보여줍니다. */
        label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        /* 각 인자는 homogeneous, spacing, expand, fill, padding입니다. */
        box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* 또다른 separator */
        separator = gtk_hseparator_new ();

        /* gtk_box_pack_start 의 마지막 3가지 인자들은 expand, fill, padding 입니다. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        break;

    case 2:

        /* 라벨을 새로 만든다. box1은 main()의 시작부분에서 만들어진대로 vbox이다. */
        label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        separator = gtk_hseparator_new ();
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        separator = gtk_hseparator_new ();
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        break;

    case 3:
        /* 이것은 gtk_box_pack_end()를 이용하여 widget을 오른쪽 정렬하는 걸 보여줍니다.  먼저, 앞에서처럼 새로운 박스를 하나 만듭니다. */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        /* 라벨을 하나 만듭니다. */
        label = gtk_label_new ("end");
        /* 그것을 gtk_box_pack_end()로써 패킹하므로, make_box()로 만들어진
         * hbox의 오른쪽으로 놓여지게 됩니다.
        gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
        /* 라벨을 보입니다. */
        gtk_widget_show (label);

        /* box2를 box1 안으로 packing합니다. */
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* bottom 쪽을 위한 separator. */
        separator = gtk_hseparator_new ();

        /* 이것은 400픽셀의 너비에 5픽셀의 높이(두께)로 separator를 세팅합니다. 이것은 우리가 만든 hbox가 또한 400픽셀의 너비이기 때문이고, "end" 라벨은 hbox의 다른 라벨들과 구분될(separated)것입니다.  그렇지 않으면, hbox 내부의 모든 widget들은 가능한만큼 서로 빽빽히 붙어서 패킹될 것입니다. */
        gtk_widget_set_usize (separator, 400, 5);

        /* main()함수의 시작부분에서 만들어진 vbox(box1)으로 separator를 패킹합니다. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
    }

    /* 또다른 hbox를 만듭니다. */
    quitbox = gtk_hbox_new (FALSE, 0);

    /* 우리의 quit 버튼입니다. */
    button = gtk_button_new_with_label ("Quit");

    /* 윈도를 파괴하기 시그널을 세팅합니다.  이것은 위에서 정의된 우리의 시그널 핸들러에 의해 포착될, "destroy"시그널을 윈도로 보내줍니다. */
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               GTK_SIGNAL_FUNC (gtk_widget_destroy),
                               GTK_OBJECT (window));

    /* quitbox로 버튼을 패킹합니다.  gtk_box_pack_start의 마지막 세 인자는 expand, fill, padding입니다. */
    gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
    /* vbox(box1) 안으로 quitbox를 패킹합니다. */
    gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);

    /* 우리의 모든 widget을 포함하게 된 이 vbox를, main윈도로 패킹. */
    gtk_container_add (GTK_CONTAINER (window), box1);

    /* 그리고 남아있는 모든 것을 보여줍니다. */
    gtk_widget_show (button);
    gtk_widget_show (quitbox);

    gtk_widget_show (box1);
    /* 마지막에 윈도를 보여줘서 모든 것이 한번에 튀어나오며 보입니다. */
    gtk_widget_show (window);
    gtk_main ();

    /* gtk_main_quit()을 호출했다면 제어는 이곳으로 오게되고,  gtk_exit()를 호출하면 그렇지 않습니다. */

    return 0;
}


역시나도 재미있는것 같아요 ㅋ 저는 인터넷에서 boxpacking 예제를 참고하였어요 ^ ^ 보고 따라하기식으로 하면서 몇가지 추가하고 바꿨더니 위의 화면과는 조금 다른 것이 나오더라구요 ^ ^ 오늘 강의에 사용한 예제를 제대로 알고있다면 몇가지 바꿔보는건 매우 쉬운듯 해요 ^  ^ 아아아 ㅋㅋ 뭔가 긴 것 같지만, 반복적인 소스들, ㅋ (아! 간단하구나?)라는 생각이 들정도 ㅋ
점점 GTK+ 매력에 빠져들고 계신지요? ㅋㅋㅋㅋㅋ


GTK+ "Hello World"


안녕하세요. 한주동안 잘지내셨는지요?^ ^;
오늘은 Hello World를 출력하는(?) 화면을 만들어 볼 생각입니다. ^ ^

모든 Programming 언어의 책의 첫장을 보면 화면에 Hello World를 띄우는 것부터 연습를 하죠? ^ ^; 그래서 저도 오늘은 Hello World를 화면에 보여주려고 합니다. 가장 기초적인 부분부터 뼈대를 만들어 가볼까요? ㅋㅋㅋ

이번에는 Source를 분석할때는 시그널(이벤트) 함수와 시그널 핸들러 함수에 대해서 집중적으로 설명해 볼까 합니다.

1. Hello World를 들어가기에 앞서..

이번에는 여태까지 내용과는 달리 중요한 부분이 몇가지 나오는 것 같아요. 중요한 부분이라면, gtk프로그래밍에서 interface를 다루는 부분이죠. interface란 사용자와 컴퓨터(or 윈도우) 사이의 관계를 말하며, 사용자가 요구하는 대로 반응하는 환경을 구현하는 것이 interface 프로그래밍이라고 합니다.

어떤 식으로 Hello World를 출력해 볼까요? 일단, 버튼과 label을 하나 만들어 볼까해요~ 버튼을 누르면 label의 내용이 "Hello World Open"으로 바뀌었다가 다시 한번 더 누르면 "Hello World Closed"로 바꾸도록 만들어 보겠습니다. 그럼 여기서도 알 수 있듯이 오늘은 버튼을 누름에 따라 변화를 구현하는부분이 핵심이라는 것을 알 수 있죠?

2. Hello World


#include <gtk/gtk.h>

GtkWidget *label;

void button_clicked ( gtkwidget *widget, gpointer data)
{

          static int toggle = 1; 

          if (toggle == 1) 
          { 
                    gtk_label_set_text ( gtk_label(label) , "hello world opened"); 
                    toggle = 0; 
          } 
          else 
          { 
                    gtk_label_set_text ( gtk_label(label) , "hello world closed"); 
                    toggle = 1; 
          }
}

void delete_event ( gtkwidget *widget, gdkevent *event, gpointer data)

          gtk_main_quit ();
}

int main( int argc,char *argv[] )

          gtkwidget *window, *button; 
          gtkwidget *vbox; 
          gtk_init (&argc, &argv); 
          window = gtk_window_new (gtk_window_toplevel); 
          gtk_window_set_title(gtk_window (window), "upgrade hello world");

          gtk_signal_connect ( gtk_object(window), "delete_event", 
          gtk_signal_func ( delete_event), null); 
          gtk_container_set_border_width ( gtk_container ( window), 10 ); 
          vbox = gtk_vbox_new ( false,0); 
          gtk_container_add ( gtk_container ( window ), vbox); 

          label = gtk_label_new ("hello world closed");

          gtk_box_pack_start (gtk_box(vbox), label, true, true, 0); 
          gtk_widget_show ( label);

          button = gtk_button_new_with_label ("Click");

          gtk_signal_connect ( gtk_object (button), "clicked");
          gtk_signal_func ( button_clicked ), null); 
          gtk_box_pack_start (gtk_box(vbox), button, true, true, 0); 
          gtk_widget_show (button); 
          gtk_widget_show (vbox); 
          gtk_widget_show (window); 

          gtk_main (); 
          return(0);
}


3. Hello World Source 설명

main()을 보면 보지못했던 새로운 함수들이 보이죠?

                    gtk_window_set_title(); 
                    gtk_signal_connect(); 
                    gtk_container_set_border_width(); 
                    gtk_vbox_new(); 
                    gtk_button_new_with_label(); 
                    gtk_box_pack_start();

gtk_window_set_title();
위의 함수는 메인 윈도우의 제목을 정해 주는 부분입니다. title!! 이 글자만 봐도 대충 감이 잡히죠? ^ ^; 

gtk_container_set_border_width();
이 함수는 window 의 border 의 크기를 정의합니다.

gtk_vbox_new();
gtk에서 윈도우 안의 여러가지 위젯들을 배열하기 위해서 box라는 위젯을 많이 씁니다. gtk는 window 안에 window를 삽입 할 수 가 없어서 이러한 도구를 앞으로도 많이 사용할 것입니다. table과 frame이 주로 사용되는 도구들 중의 하나이죠 ^ ^
box는 실제로 보여지는 위젯은 아니지만 다른 widget들을 배열하기 위해 사용하지요. box인데 vbox라고 사용한 것에 대해 의심이 가지 않아요? box는 두가지 종류가 있습니다. vbox와 hbox가 사용됩니다. 이것은 수직박스와 수평박스를 나타내지요. 물론 gtk_*_new()으로 정의할 수 있습니다. hbox와 vbox의 조합으로 위젯의 위치를 정해서 좀더 직관화된 인터페이스를 만들 수 있죠.
위의 "Hello World" source는 vbox를 정의하고 그곳에 레이블과 버튼을 올려놓습니다(packing). packing이라는 말은 widget들을 쌓아 넣는다고 보면됩니다. 예를들어 커다란 여행 가방에 여러가지 물품들을 차곡차곡 정리해야 한다면 vbox로 나눈뒤 수직 방향의 박스에 차곡차곡 widget을 넣어서 보기좋게 정돈되는 과정이라고 생각하시면 되죠 ^ ^ 머리속으로 그림을 그리면 좀더 쉽게 이해가 되실 겁니다.

gtk_button_new_with_label();
button을 정의하는데 label을 넣고 싶을 때 쓰는 함수입니다. 버튼에는 일반적으로 label이 보여서 사용자에게 어떤 역할을 하는지 알려주는 역할을 하죠.  

gtk_box_pack_start();
gtk_container_add와 비슷한데.(기억나시죠? container에 무언가 추가하는^ ^;) 여기서는 박스에 쌓기(packing) 위해서 위 함수를 쓴다. gtk_box_pack_start()는 hbox 위젯의 왼쪽에서 오른쪽, vbox부분에서는 위쪽에서 아래쪽의 순으로 쌓는다는 의미이며, 반대 역할을 하는 gtk_box_pack_end()함수도 있습니다. 뒤에 붙는 인자들은 expand, fill할 것인가에 대한 선택이며, 마지막이 padding의 크기를 정의합니다. 

이제부터.. 가장 중요한 부분을 설명해 보겠습니다. 제가 처음에 말씀드렸죠. 오늘은 가~장 중요한 무언가가 나올것이라구요.
이제 나타날 때가 되었습니다. 짜~~~잔!!!^ ^* 

gtk_signal_connect(   gtkobject *object, 
                                gchar *name, 
                                gtksignalfunc func, 
                                gpointer func_data
                             );

위 함수는 interface , 즉 사용자가 뭔가를 행하였을(signal) 때 반응 하는 함수에 대해서 연결 (connect ) 시켜주는 역할을 합니다.


위의 예제(Hello World)중에서..
gtk_signal_connect ( gtk_object (button), 
                                 "clicked", 
                                 gtk_signal_func ( button_clicked ), 
                                 null); 

예로 들자면, 사용자가 button이라는 위젯을 눌렀(click)을 경우 'clicked' 라는 이벤트가 발생하며, button_clicked라는 함수를 불러 실행하라는 의미가 됩니다. 실제 button_clicked는 소스의 윗부분에 정의하였습니다.

두 번째 인수인 "clicked"는 임의로 정해지는 것이 아닙니다. 이것은 각각의 위젯에 대해서 사용자가 행한 행동 (event라고도 할수 있다)을 말하며, 버튼이라면 누르는 것이 있을 것이며, 메뉴에서는 선택하는 부분등이 예가 될 수 있습니다. 이 event는 각각의 위젯에 따라 다르며, 그 이름또한 틀립니다. 그 이름은 미리 정의되어 있습니다. 물론 사용자가 임의의 위젯을 만들고 임의의 이벤트를 만들수는 있지만, 그것은 좀더 고차원적인 기술이기에 다음 기회에 해보아야겠습니다.
사용자가 버튼을 눌렀더니, button_clicked이라는 함수가 불러집니다. 실제 위 소스에서는 버튼이 눌러지면 label 의 내용을 토글시키는 작용을 하게 해놓았습니다. c 프로그래밍을 접한 우리들은 쉽게 접근할 수 있겠죠. 여기에서 마지막 인수는 함수에 넘겨질 데이터입니다. 이 데이터는 대부분 프로그래밍에서는 null이지만 사용자가 필요에 의해 임의의 값을 넘겨주어야 할 때 적어주면 됩니다.
위에 또다른 gtk_signal_connect가 있죠? 'delete_event' 이며 이는 시스템 버튼 (오른쪽 위의 x모양의 버튼) 이 눌러졌을 경우 gtk 내부에 미리 정의된 기본 함수, gtk_main_quit을 부르게 되어 있습니다. 단순히 윈도우를 종료시키는 함수죠. 사용자가 만들지 않아도 되는 (일반적인 이벤트 함수) 함수들은 미리 정의된 것들을 쓰기도 합니다.


그럼. 정리를 해볼까요? ^ ^; 

(1) 우선 window을 생성하고, 박스를 만듭니다.
(2) label을 생성하고 초기 이름은 'hello world closed'이고 이것을 박스에 쌓아봅니다(packing).
(3) button을 만들고 초기 label은 '클릭해 주세요'이며, 버튼이 눌러질 경우 행하여질 이벤트 함수를 'button_clicked'라고 정의하였고 이벤트와 연결하였습니다. 버튼 또한 box에 packing시킵니다.
(4) 각각의 위젯을 보이게 합니다.

4. 결과 화면
 


오늘 저의 설명은 어떠하였는지요? ^ ^; 궁금한 사항이 있으면 댓글을 달아주세요 ^ ^
무언가 하나씩 해나아가는 듯한 느낌이 들지 않아요? ㅋㅋ 오늘은 무언가 설명 좀 한것 같아서 나름 뿌듯한걸요? ^ ^;
함수를 좀더 쉽게 설명하기 위해 책과 블로그들을 참고하였는데, 아직 많이 미흡-_-+ 이쁘게 봐주세요 ^ ^

저의 글을 열심히 읽어주신 분이 부탁하셔서, 이번주에는 GTK+ Widget 들을 보충하기 위한 class 계층 구조 트리를 올려드리겠습니다. 저도 widget이 많은 관계로 자주 사용하는것만 외우고 있을 뿐, 아래의 표를 참고하고 있습니다. GTK+를 정말 능숙하게 사용한다면, 전부 외우고 있겠죠? ㅋㅋㅋ 앞으로 그런 날이 올거라 믿고 열심히 포스팅 하겠습니다.ㅋ
사실은 공부를 하면서 widget을 올린 window를 하나씩 만들어 보려고했지만, 아래의 계층구조 트리를 보면서 하나씩 제작하는것도 괜찮다는 생각이 드네요 ^ ^;

GtkObject
   +GtkData
   | +GtkAdjustment
   | `GtkTooltips
   `GtkWidget
     +GtkContainer
     | +GtkBin
     | | +GtkAlignment
     | | +GtkEventBox
     | | +GtkFrame
     | | | `GtkAspectFrame
     | | +GtkHandleBox
     | | +GtkItem
     | | | +GtkListItem
     | | | +GtkMenuItem
     | | | | `GtkCheckMenuItem
     | | | |   `GtkRadioMenuItem
     | | | `GtkTreeItem
     | | +GtkViewport
     | | `GtkWindow
     | |   +GtkColorSelectionDialog
     | |   +GtkDialog
     | |   | `GtkInputDialog
     | |   `GtkFileSelection
     | +GtkBox
     | | +GtkButtonBox
     | | | +GtkHButtonBox
     | | | `GtkVButtonBox
     | | +GtkHBox
     | | | +GtkCombo
     | | | `GtkStatusbar
     | | `GtkVBox
     | |   +GtkColorSelection
     | |   `GtkGammaCurve
     | +GtkButton
     | | +GtkOptionMenu
     | | `GtkToggleButton
     | |   `GtkCheckButton
     | |     `GtkRadioButton
     | +GtkCList
     |  `GtkCTree
     | +GtkFixed
     | +GtkList
     | +GtkMenuShell
     | | +GtkMenuBar
     | | `GtkMenu
     | +GtkNotebook
     | +GtkPaned
     | | +GtkHPaned
     | | `GtkVPaned
     | +GtkScrolledWindow
     | +GtkTable
     | +GtkToolbar
     | `GtkTree
     +GtkDrawingArea
     | `GtkCurve
     +GtkEditable
     | +GtkEntry
     | | `GtkSpinButton
     | `GtkText
     +GtkMisc
     | +GtkArrow
     | +GtkImage
     | +GtkLabel
     | | `GtkTipsQuery
     | `GtkPixmap
     +GtkPreview
     +GtkProgressBar
     +GtkRange
     | +GtkScale
     | | +GtkHScale
     | | `GtkVScale
     | `GtkScrollbar
     |   +GtkHScrollbar
     |   `GtkVScrollbar
     +GtkRuler
     | +GtkHRuler
     | `GtkVRuler
     `GtkSeparator
       +GtkHSeparator
       `GtkVSeparator

계층구조 트리 부분중 굵은 글씨로 표기한 것은 제가 이전에 포스팅했던 내용입니다. 겨우 2개밖에 하지 못했네요,
앞으로 하나씩 하나씩 굵은 글씨로 만들어 볼 생각입니다. ^ ^ 아! 위의 계층구조는 window와 관련된 widget입니다.

GTK+를 하다보면 window가 없는 Event를 종종 사용해야 할 것입니다. window와 무관한 widget을 몇가지 설명할까합니다.EventBox widget은 전혀 쓸모없을 수도 있습니다. 이것은 스크린에 아무것도 그리지 않으며 이벤트에도 응답하지 않습니다. 하지만 이것은 자신의 child widget으로 X윈도를 제공하는 한 함수를 지원하게됩니다. 이것은 많은 GTK widget들이 관련된 X윈도를 가지지 않는다는 점이 중요합니다. X윈도를 가지지 않는 것은 메모리를 절약하고 퍼포먼스를 증대합니다. 완벽할 수 없기에몇가지 약점도 가지고 있습니다. X윈도가 없는 widget은 이벤트를 받을 수 없고, 그리고 그의 항목들에 대한 클리핑도 하지 않습니다. EventBox라는 이름은 이벤트를 다루는 함수라는 의미도 있지만, widget들이 클리핑될 수도 있다는 것을 의미하기도 합니다.

GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkImage
GtkItem
GtkLabel
GtkPaned
GtkPixmap
GtkScrolledWindow
GtkSeparator
GtkTable
GtkViewport
GtkAspectFrame
GtkFrame
GtkVPaned
GtkHPaned
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator

우리는 window에 무언가의 widget을 올릴때마다 위의 Event widget을 사용할 것입니다. 각각의 widget을 차례로 시험하고 보여줄 수 있는 간단한 함수를 만들어 GTK+에 관한 공부를 해볼 생각입니다. 하나의 Project를 할때마다 Event widget을 최대한 넣어서 보여줄 생각입니다.

다음주에는 window에 버튼을 올려볼까 합니다. 간단히 만들어 보는 GTK+ 버튼 Widget!!!!

위의 계층 구조는 앞으로 계속 사용할 듯 합니다. SIG가 끝나기 전에 위의 widget을 전부 사용해보는게 목표로 잡고 열심히 만들겠습니다. 이번 한주도 열심히 열심히 공부하세요 ^ ^*

GTK+에서의 window code 설명

저번시간에 window를 만들어 보았습니다. 아주 간단하게 몇줄 끄적였더니 하나의 귀엽고 앙증맞은 window가 생성되었죠?
오늘은 소스 코드에 대하여 설명하도록 하겠습니다. 처음 전 몇줄 없다고 대충 훌터 보았었지만, 그렇게 되면 결국 다시한번 보게 되더라구요 ^ ^ GTK+의 소스 하나하나 설명을 해보겠습니다.

#include <gtk/gtk.h>
이것은 gtk를 사용하기 위해 꼭 필요한 헤더입니다. /usr/include/gtk/ 
실제 gtk의 함수들은 여러 헤더 파일에 함수를 선언하고 있지만 위의 헤더파일만 선언해 주면 되지만, 가끔은 위의 헤더에 내장되어있지 않은 함수가 있기도 합니다. (그럴 경우에는 따로 프로젝트를 진행하면서 설명하도록 하겠습니다.) 그렇지만, 위의 헤더함수가 다른 하위 헤더파일을 거의 포함하고 있습니다.

gtkwidget *window;
이것은 gtk프로그래밍 할 때 꼭 선언되는 변수입니다. c나 c++ 등 프로그래밍을 할때 변수를 선언해 주듯이 선언해 주면 됩니다. gtkwidget은 문자 그대로 gtk widget의 한종류라는 것을 나타내줍니다. 우리는 window를 생설할 것이기 때문에 저는 window 로 선언하겠습니다. gtkwidget 은 여러 가지가 있지만, gtk로 짜여진 프로그램의 대부분 인터페이스는 저 자료형 하나로 선언가능한 것이 많습니다. 버튼 메뉴, 아이콘, 상태바, 레이블 등 모든 것이 저 자료형(gtkwidget)으로 선언하면 됩니다.

 gtk_init (&argc, &argv);
이것은 프로그램 실행 파일에 인수로 넘겨받는 것을 처리 하는 부분이며, 기본으로만 실행하기 위해서 내부 함수를 쓰는 부분이다. c에서 사용하시는 함수의 개념을 생각하시면 이해를 하시기에 조금의 도움이 됩니다.

 window = gtk_window_new (gtk_window_toplevel);
위에서 변수를 선언 했으니 이제 사용을 해보겠습니다. 모든 것이 저 하나로 선언가능하다면 어느 부분에 사용할 것인가를 정해야 할 것이다.위의 선언문을 하나씩 풀어보겠습니다.
window라는 변수는 단순히 변수에 window라는 형태를 갖는 역학을 하는 부분입니다. 윈도우는 말그대로 창을 의미합니다. (MFC에서의 Dialog와는 다른 개념입니다.) gtkwidget의 가장 기본이 되고 바탕이 되는 부분입니다. 가장 기본적이고 심플한 window를 생성할 것이 기때문에 우리는 gtk_window_toplevel 이라는 window의 특징을 선언해 준것입니다.
즉, 다시 말해서 window라는 변수안에 gtkwidget중 가장 기본적인 toplevel(가장 기본적인 window)을 정의해준 것입니다.

앞으로 여러 가지 widget을 만들어 보겠지만, 대부분 gtk_*_new 형태의 함수로 위젯을 정의 하게 될 것이다. '*'은 button, menu, label, box, frame 등이 됩니다.

gtk_widget_show (window);
위의 선언문을 해석하면 widget을 show하라는 뜻이며, 이로써 화면에 보이게 됩니다. gtk_widget_show 뒤의 인수 부분에서 화면에 보여질 위젯을 결정합니다. 우리는 window를 하나 만들었고 window만 보여줄 것이라 window만 show하게 되는거겠죠? 여러가지 widget을 생성한다면 widget을 각각 보여줘야겠죠? ^ ^;

gtk_main();
이부분도 마찬가지로 gtk프로그래밍에서 빠지지 않는 부분입니다. 인수도 없으며 단순히 저렇게 적어주면 됩니다. 물론 main 함수의 끝부분쯤에서 써줘야겠죠. 조금 중요한 부분이니 이부분은 나중에 따로 다루어 보도록 하겠습니다. (약간 미루는듯한-_-+)

여기까지가 저번시간에 작성한 코드였습니다. 흠.. 아주 귀엽고 앙증맞지만, 생각외로 close버튼도 있고 전 매우 놀랐습니다. 달랑 윈도우만 만들어 지는줄 알았는데 close 버튼이 있는게 어디입니까~ 다들 그냥 넘기시겠지만, 전!! 매우 좋았습니다. 분명 찾아보면 최소화, 최대화 버튼도 달린 윈도우를 만들수 있을거라는 생각이 들기 때문입니다.

위에 살짝쿵 설명했듯이, GTK+에서는 window와 dialog는 다른 방식입니다. gtk_window_new()를 위한 또다른 define으로 GTK_WIDNOW_TOPLEVEL말고 GTK_WINDOW_DIALOG 도 있습니다. 이것은 윈도매니저와 약간 다른 방식으로 상호작용하며, 일시적인 윈도 들에 대해 쓰여지고 있습니다. 예를 들어 기본 윈도우에 팝업 정도의 개념이라고 생각하시면 됩니다.

그럼 위의 코드를 응용하여 dialog를 만들어 낼 수 있겠죠? 다들 한번 응용해 보세요~
이제부터 위의 코드에 widget을 하나씩 추가하여 기능성 있는 window를 만들어 볼까 합니다.

오늘은 사정상 새로운 내용을 첨가 하지 못하였습니다. 다음주부터는 분발하겠습니다 ^ ^ 넓으신 마음으로 봐주세요 ~
그럼 이번주도 매일매일 올라오는 즐겁고 흥미로운 블로그를 보면서 열공하겠습니다..ㅋㅋ




GTK 설치 및 컴파일


오늘은 GTK를 설치해 보려고 합니다.^ ^
저는 처음 GTK를 배울때, 누군가(아주 멋진분)의 도움으로 쉽게 설치 할 수 있었습니다.
그래서 이번 블로그를 쓰기위해 그분의 자료를 살포시 참고했지요.
설치 방법대로 제 컴도 살펴 보았어요. 그럼.. 시작해볼까요? ㅋㅋ

gtk 설치하려면 여러가지가 필요합니다.
패키지로 받아서 설치하는 방법이 있다고 하네요.
http://www.gtk.org 에서 받아서 설치하면 된다네요.
tar xvfz gtk+-2.0.0.tar.gz
tar xvfj gtk+-2.0.0.tar.bz2   

./configure --prefix=/opt/gtk

make
make install    /etc/profile에 집어 넣어주고

PPFLAGS="-I/opt/gtk/include/gtk-2.0/"
LDFLAGS="-L/opt/gtk/lib"
PKG_CONFIG_PATH="/opt/gtk/lib/pkgconfig"
export CPPFLAGS LDFLAGS PKG_CONFIG_PATH
LD_LIBRARY_PATH="/opt/gtk/lib"
PATH="/opt/gtk/bin:$PATH"
export LD_LIBRARY_PATH PATH   

/bin/gtkgcc 라고 만들어서 집어넣주면 된다네요~
gcc -Wall -g helloworld.c -o helloworld `pkg-config --cflags gtk+-2.0` \    `pkg-config --libs gtk+-2.0`

위의 처럼 bin/gtkgcc에 설정을 해주면, 컴파일 할 때 복잡하게 쓰지 않고
gtkgcc 파일명.c 파일폴더
이렇게 하면, 파일폴더안에 쫘잔~ (에러가 없다면)그럼 실행파일을 볼 수 있답니다.

GTK 실행 환경도 만들었는데 오늘은 맛보기로 윈도우 창 하나 띄워 보겠습니다.
일단 파일을 만들어야겠죠? ^ ^
아래와 같이 코딩을 해주세요 ~ 당연! 파일을 만든다음 해주셔야해요 ~


#include <gtk/gtk.h>

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

        gtk_init(&argc, &argv);

        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

        gtk_widget_show(window);

        gtk_main();

        return 0;

}


위의 내용을 저장한후, 컴파일을 해주세요.^ ^
저는 gtkgcc window.c window 이렇게 했답니다.

GTK 녀석 얼마나 이쁜 윈도우 창을 만들었는지 한번 봐야겠죠? ^ ^

우왕우왕! 이쁘고 귀엽죠~

다음시간에는 윈도우를 만들기위하여 사용한 위의 코드를 설명하겠습니다.
윈도우에 대해 공부도 해보구요 ^ ^*

좋은하루되세요 ^ ^

GTK와 GDK


오늘은 GTK를 공부하기전에, GTK와 GDK에 대해 알아보도록 하겠습니다.
이전에 공부를 할때 찾아봤던 기억이 있으나, 아직 제것으로 만들지 못했던것 같아, 다시 찾아보기로 하였습니다 ^ ^
이번 시그를 통하여 저번 공부때 마무리 하지 못했던 GTK를 마무리 해볼까 합니다.
공부를 하면서 올리는 내용이라 많이 부족하지만, 지적도 쏠쏠하게 해주시면 감사하겠습니다 ^ ^

처음부터 주저리주저리.. 너무 긴것 같습니다. (자~자~! 시작해 보겠습니다,)

 



1. GTK는 "GIMP Toolkit"의 약자이다.
- ( 와, 이부분은 기억이 나려고 하네요, ㅋ 처음 찾아본 자료가 아는 내용인거 보니 출발이 좋은것 같네요^ ^)
그럼 GIMP는 무엇인가 리눅스에 관심이 있는 사람들이라면 한번쯤 들어봤을만한 이미지 편집기입니다.
바로 리눅스에서 사용할 수 있는 포토샵인것입니다. (두둥.. 너무 거창한가? 그림판이라고 해둬야겠네요.ㅋ)

GTK의 천재가 아니라 잘은 모르지만, GTK의 Tutorial을 보면 이런말이 가장 처음 적혀있습니다. "GTK (GIMP Toolkit) is a library for creating graphical user interfaces" 그렇습니다!! GUI를 만들기 위한 툴킷 라이브러리입니다.

2. GDK의 친구는 그리기와 Event이다.
- (GDK는 그리기와 Event의 친구이다.. 친구라는 표현이.. 어울리지 않을 수 있습니다. 여기서 친구란, GDK로 우리가 가장 많이 해야할 일들은 그리기와 Event라는 것을 강조하기 위함입니다.)
"GDK 라이브러리는 GTK+ 위젯(어플리케이션)과 윈도우 시스템을 이어주는 추상적 계층을 제공해줍니다" 라는 문장을 많이 보셨을 겁니다. 그 이전은 저도 안해봐서 잘은 모르겠으나 듣기로는 GTK와 GDK의 구분이 없었다고 합니다. 하지만 지금은 GTK와 윈도우 시스템 사이에 GDK가 있다고 합니다.

실제로 X Window든 MS Windows든 플랫폼과의 대화는 GDK가 맡아서 하고 GTK는 GDK와 좀더 쉬운 대화를 하는것입니다. Event나 Drawing처럼 X Window와 친하게 지내야하는 작업들을 GTK와 플랫폼(일반적으로 X Window) 사이에서 처리 해 주는것입니다. 그뿐 아니라 Font, Style, 이미지 제어 등 GUI의 중요한 부분들을 담당하고 있습니다. GTK는 이러한 GDK를 이용하여 구조적인 부분을 담당합니다.

현재에는 Xlib을 래핑하고 있는것은 GDK입니다. GTK는 그 GDK를 이용하는것입니다.

3. GTK와 GDK 그리고 X Window
- X Window에서는 GUI 구현을 편리하게하고 개발자를 여유롭게 만들어 줍니다.
우리가 X Window에서 GUI를 만들려면 어떻게 해야할까요? 가장 기본적인 방법으로는 Xlib을 이용하여 개발하는 것이 있습니다. 이것은 매우 귀찮고 어려울 수 있는 일입니다.

Xlib은 X Window에서 GUI 개발을 할 수 있는 가장 기본적인 라이브러리입니다. 화면에 필요한 Widget들을 그려내고 GUI뿐만 아니라 X Window 시스템에 관련된 대부분의 기능을 지원하지만 원초적인 정보와 기능들만을 제공합니다. 개발자가 Xlib을 사용하여 GUI부분을 구현한다면 직접 정보를 관리하고 안정성을 책임져야 합니다.

GTK와 GDK를 사용한다면 Xlib이 해주는 역할외에도 GUI 프로그램을 제작함에 있어 필요한 대부분의 유형과 기능들을 미리 구현해 놓았습니다.

GTK와 GDK도 X Windows에 실제로 무언가 표시할때나 X Window에 관련된 작업을 할때는 Xlib을 사용합니다. 결국 Xlib을 사용하지만 이부분은 모두 GTK와 GDK가 내부적으로 처리해주는것입니다. 그럼 GTK와 GDK는 그냥 Xlib 래핑 해 놓은것 아니냐라고 할 수 있겠으나 그렇다고 하기엔 GTK와 GDK는 너무나 많은 일을 대신해주고 많은 부분을 확장하여 미리 만들어 놓았습니다.

버튼 하나만 보더라도 Xlib은 가장 기본적인 부분만 처리해 줍니다. 버튼을 화면에 그리고 이벤트 처리하고 정도입니다. 하지만 GTK와 GDK는 버튼을 구현함에 있어 관련된 대부분의 필요한 정보들과 기능을 확장하여 미리 준비해놓았기 때문에 우리는 그것을 사용하면 됩니다. 또한 기본적인 Widget들을 GUI 프로그램에서 일반적으로 사용하는 다양한 형태로 변이시켜서 새롭게 구성해 놓았습니다.

GTK와 GDK는 물론 아주 특수한 상황까지 고려되어있는것은 아니지만 GUI 프로그램을 제작함에 있어 불편함을 느낄수 없을만큼 많이 준비되어있습니다.

Xlib은 X Window 시스템을 제어하기 위한 가장 기본적인 라이브러리이고 GTK와 GDK는 GUI 프로그램 개발에 필요한 툴킷 라이브러리 인것입니다. 개발자는 GUI를 구현하기 위해 엄청난 시간을 보내야하는것이 아니라 비지니스로직 등의 구현에 더 많은 시간을 할애하고 GUI관련해서는 GTK와 GDK에 맡기면 되는것입니다.





나름 쉽게 정리를 해본다고 이것저것 자료를 참고해 보았습니다.
처음에는 이론 부분을 설명하고 점차 실전으로 해보고 올릴 생각입니다.
궁금하신 내용이나 추가해야할 내용이 있다면, 이야기해주세요,
저의 서치 실력으로는 거의 같은 내용이 나오는 듯 하네요 ^ ^
오늘은 사정상 내용이 많이 짧네요, 다음부터는 분발하겠습니다 ㅋㅋ