glib, gtk 팝업 사전 만들기 3화


c 언어 익히 알고 있던 사람들은 1,2화 보면서 많이 지루했을거구, c 언어를 모르는 사람은 부담이

되었을 것이라 생각함. c 언어를 조금 아는 사람들에게는 도움이 되었을거구.

이제 c 언어 얘기는 가급적 조금만 하구, 지루했으니까 막바로 창 띄울 준비를 하자구

devhelp 라는 어플, glib2-docs (libglib2.0-doc) 필히 설치하셈.

devhelp 는 api 를 검색하고 문서를 보는 유틸임. 옛날에 msdn 나와서 자유/오픈소스쪽에서 우리도

그런거 함 만들어보자 해서 나왔다 카더라.. devhelp 개편함


tiandict.c 로 덮어쓰기 하셈. 여기에서는 아주 최소한만 다루었음.

gnome.org 홈페이지에서는 예제 코드로 GApplication 을 이용하였을텐데,

여기서는 옛날 예제 코드에 나오는 방식(이 방법도 일반적인 방식임)으로 하였음.


/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */ /* 위에 줄 역할은 TAB 치면 두칸씩 들어가는거. 개취,케바케임 ㅡㅡ;; */ #include <stdlib.h> #include <gmodule.h> #include <gtk/gtk.h> typedef struct _Tiandict Tiandict; /* Tiandict 를 GObject 로 만들지는 않음, 그럴 필요성이 여기서는 없음 */ /* GObject 로 하지 않아도 되는 부분은 그냥 단순하게 이런 식으로 하는게 좋음 */ /* 사전 어플을 두개씩 띄울 필요는 없으므로 나중에 GApplication 으로 바꾸자구 */ struct _Tiandict { /* 요거는 메인 윈도우, GtkWindow 로부터 상속 받아도 되지만 나중에 GUI 코드를 분리시킬 * 것이므로 상속 안 하고 이렇게 변수를 이용하여 접근함. GUI 코드를 분리시키면, 옵션에 따라 * 터미널에서도 작동시켜서 출력 결과 볼 수 있고, GUI 창 띄워서 볼 수도 있음 */ GtkWidget *window; /* GtkWindow *window 이렇게 받을 수도 있음 */ }; /* g_signal_connect (dict->window, "destroy", (GCallback) on_destroy, NULL); 에서 * dict->window 가 widget 에 대응되고, NULL 부분이 user_data 에 대응됨. * 각각의 신호마다 함수 인자가 다를 수 있음. 그래서 api 문서를 봐야 하고 api 문서에서 알려주는 * 함수 형태로 구현하여야 함 */ /* static 은 써도 되고 안 써도 되는데, 외부에서 이 함수를 쓸일이 없으면 쓰는게 좋음. * static 쓰면 만약 이 함수를 참조하는 곳이 없으면 컴파일 경고 떨어짐. * 그거 보려고 static 쓴거임. 별 의미 없음 ㅋㅋㅋ */ static void on_destroy (GtkWidget *widget, gpointer user_data) { /* gtk_widget_destroy (widget); 또는 g_object_unref (widget); 안 해도 됨. * 내부적으로 이미 해제시켰거나 gtk_main() 루프 빠져나오면서 해제시키는 거 같음 * 문서에 명확하게 나와 있지 않음. * 따라서 여기 함수 또는 tian_dict_free() 함수 내에 넣지 않을 거임 */ gtk_main_quit (); } Tiandict *tian_dict_new () { Tiandict *dict; /* 메모리 할당을 malloc 로 해도 되지만, glib 함수를 사용함 */ dict = g_slice_new (Tiandict); /* gtk 함수를 사용하기 전에 반드시 호출해야 하는 함수. 초기화 함수가 이거 말고도 또 있음 */ /* 변수에 뭐가 들어가는지는 devhelp 켜서 gtk_init 검색하면 되구. 구현이 귀찮으니까 * 일단은 tian_dict_new 함수내에 GUI 코드도 몽땅 처 넣자구 ㅋㅋ */ gtk_init (NULL, NULL); /* 요 함수는 윈도우 메인창 만들으라는 함수. 윈도우 종류가 * GTK_WINDOW_TOPLEVEL, GTK_WINDOW_POPUP 이렇게 두 종류 있음. * GTK_WINDOW_TOPLEVEL 는 일반적으로 흔히 보는 창, 타이틀바 있음. 윈도우 매니저가 관리 * GTK_WINDOW_POPUP 는 tooltip, popup 이런 거 만들 때 씀. 타이틀바 없음. */ dict->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 요거는 "destory" 시그널을 연결하라는 의미. glib/gtk 로 뭔가를 만들려면 이런 거에 익숙해져야 * 함. c 언어에서 함수포인터를 이용한 callback 같은 거고, 자바로 따지면 listener 와 같은 * 개념. 사용하기 편리하게 되어 있지. dict->window 는 GtkWindow 이고, GtkWidget 를 * 상속한 것이니까, GtkWindow, GtkWidget, ... GObject 에 있는 시그널을 사용할 수 있음. * 그러면 그걸 어떻게 아느냐. api 문서를 봐야지. devhelp 를 사용해서 보면 상속 관계, 시그널, * 프로퍼티 등 설명이 아주 잘 나와 있음. 아래 문장은 윈도우창에 [x] 표시 누르면 "destroy" * 시그널이 발생되는데, 그 때 on_destroy() 함수를 실행하라는 의미. GCallback 라는 거는 * 그냥 캐스트(형변환)하는 거임. 별 의미 없는데 그거 안 쓰면 에러 떨어짐. 마지막에 NULL * 넣은거는 on_destroy (GtkWidget *object, gpointer user_data) 에서 user_data 에 * 대응되는 위치. user_data 로 NULL 암것도 안 넘김. */ g_signal_connect (dict->window, "destroy", (GCallback) on_destroy, NULL); /* 요거는 화면에 보여주는 함수. gtk_window 에 포함되어 있는 것들까지 보여주라는 함수 */ gtk_widget_show_all (dict->window); return dict; } void tian_dict_free (Tiandict *dict) { /* g_slice_new() 로 할당한 메모리를 이렇게 해제함 */ g_slice_free (Tiandict, dict); } /* main() 에는 줄기만 다루자구, 가지는 함수로 빼구 */ int main (int argc, char **argv) { Tiandict *dict; dict = tian_dict_new (); /* 이벤트 루프. 내부적으로 g_main_loop_run() 실행됨. 내부에 while 같은 loop 가 있다고 * 생각하면 됨. 이 루프를 탈출하기 위해서는 gtk_main_quit() 하면 됨. * 지금은 깊이 알 필요 없고, 나중에 예를 들어, GTK 로 GUI 통신 프로그램(tramission, 메신저) * 같은 고급 프로그래밍을 하려면 반드시 GMainLoop 반드시 알아야 함.. GMainLoop 모르고서는 * 고급 프로그래밍을 할 수 없음. GMainLoop 는 select, poll, epoll, kqueue 같은 입출력 * 다중화 기법임. 내부적으로 select 와 poll 을 사용함. * 현재의 glib 는 epoll(리눅스), kqueue(FreeBSD) 사용 안 함. 이게 좀 아쉽지 */ gtk_main (); /* gtk_main_quit() 를 어디선가 실행하면 gtk_main() 빠져나와서 다음 줄부터 실행되는 거임 */ /* gtk_main() 함수 다음 줄부터는 어플 종료하는 함수들을 써야겠지 */ tian_dict_free (dict); return EXIT_SUCCESS; /* stdlib.h 에 있음. return 0 이랑 똑같음 */ }


여기까지 왔으면 과장이 아니라, GTK+ GUI 프로그래밍 절반 배운 거임. 구라 아님!! 진짜임!!!

GTK로 GUI 프로그래밍하는 방법이 거의 정형화되어 있음. glide 이런거 사용하면 마우스로 GUI

디자인할 수 있는데, 난 그런거 절대 안 씀. GtkBuilder 도 안 씀. 사실 이런게 다 손맛이거덩

어때? 자바 swing, 자바 swt 보다 훨 쉽지? 아님 말구 헤헤~~