본문 바로가기
오픈소스 읽기 (OLD)/리눅스 어플리케이션 만들기 - Gtk4

3-1. 간단한 어플리케이션 만들기 (Window, Label, Button)

by 커널패닉 2021. 4. 18.
반응형

앞으로 약 3개정도의 포스트를 통해서 Gtk4 프로그래밍 기초에 대해서 다루려고 한다. 기본적인 내용 구성은 많은 부분을 Gtk4 공식 튜토리얼 문서(developer.gnome.org/gtk4/stable/gtk-getting-started.html)에서 가져오되, 내가 생각하기에 보완이 필요한 부분은 내용을 보충하고, 불필요한 내용은 쳐내면서 내용을 재구성할 예정이다.

 

3.1.1 간단한 앱 그리기

Gtk의 첫 시작으로 창 하나를 띄우는 간단한 앱을 제작하려한다. 이번 절에서는 Gtk 어플리케이션이 가지는 기본적인 구조와, 시그널과 콜백 함수를 사용하는 기본적인 방법에 대해서 살펴볼 예정이다. 그리고 GtkWindow 위젯(혹은 GtkApplicationWindow 위젯)의 속성을 관리하는 방법에 대해서도 간략하게 다루려 한다.

#include <gtk/gtk.h>

static void activate (GtkApplication* app,gpointer user_data) {
    GtkWidget *window;

    /* 
     * GtkApplication 객체에 기본 윈도우를 생성 및 등록한다. 
     */
    window = gtk_application_window_new(app);
    /* 
     * 윈도우 타이틀을 설정한다. 설정된 이름은 윈도우 상단에 표시된다.
     * window는 GtkWidget 객체로 선언되었기 때문에, GTK_WINDOW() 매크로를 사용해서,
     * 형 변환을 해주었다. GTK_WINDOW() 매크로로 형 변환을 하지 않더라도 
     * 컴파일 및 동작에는 아무런 영향이 없다. 
     * 대신 컴파일러에서 경고가 발생하는 것은 감수해야 하낟.
     */
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    /* 
     * 윈도우의 기본 크기를 설정한다.
     */
    gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
    /* 
     * 윈도우 위젯을 드로잉한다.
     */
    gtk_widget_show(window);
}

int main (int argc, char **argv) {
    GtkApplication *app;
    int status;

    /* 
     * 어플리케이션 이름은 도메인 주소와 유사한 형식을 사용한다.
     * D-Bus 포스트 참조 https://www.kernelpanic.kr/22
     */
    app = gtk_application_new("kr.kernelpanic.gtkexample", G_APPLICATION_FLAGS_NONE);

    /* 
     * g_application_run() API 호출 시, activate 시그널이 발생한다.
     * 따라서 activate 시그널이 발생할 때, 호출될 콜백 함수를 등록한다.
     */
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);

    /* 
     * 실제 어플리케이션이 동작하는 메인 루프이다.
     * 앱이 종료되기 전까지 다음 코드 블록으로 넘어가지 않는다.
     */
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);

    return status;
}

위 코드는 아래 명령어로 컴파일 가능하다.

$ gcc `pkg-config --libs --cflags gtk4` gtk-example.c -o example
$ ./example

결과로 아래와 같은 창이 나오면 정상적으로 컴파일 & 실행된 것이다.

 

더보기

이번에 기본 프로그램을 작성하면서, 초반부터 Gtk3 대비 큰 차이점을 발견할 수 있었다. Gtk3에서는 gtk_init()과 gtk_main() API를 이용해서 GtkApplicaion 없이 간단한 프로그램을 만들 수 있었다. 하지만 Gtk4로 넘어오면서 gtk_init() API가 변경되고, gtk_main() API는 deprecated 되었다는 점이다. 기존에 Gtk3을 사용하던 개발자라면 gtk_main() API로 widget의 생명주기를 관리하는 대신 GtkApplicaiton 객체를 사용해야 한다는 점을 알고가자.

 

3.1.2 Hello, world (w/ Label & Button)

창을 띄우는데 성공했으니, 이제 뭐라도 내용물을 채우는 것이 다음 순서이다. 이번에는 GtkLabel, GtkButton 위젯을 이용해서 글을 표시하고, 간단한 버튼을 만드는 방법에 대해서 다룰 예정이다. 나아가서 GtkBox를 사용해서 어플리케이션의 구획을 나누는 방법에 대해서 살펴보려 한다.

#include <gtk/gtk.h>

static void activate (GtkApplication* app, gpointer user_data) {
    GtkWidget *window;
    GtkWidget *label;

    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);

    /*
     * GtkLabel: 간단한 텍스트를 보여주는 위젯이다.
     */
    label = gtk_label_new("Hello, world");

    /*
     * gtk_window_set_child을 통해서 Window 위젯에 label 위젯을 자식으로 추가한다. 
     * 자식으로 추가되어야 아래 gtk_widget_show(window)에서 label도 함께 출력이 된다.
     */
    gtk_window_set_child(GTK_WINDOW(window), label);
    gtk_widget_show(window);
}

int main (int argc, char **argv) {
    GtkApplication *app;
    int status;

    app = gtk_application_new("kr.kernelpanic.gtkexample", G_APPLICATION_FLAGS_NONE);

    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);

    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);

    return status;
}

컴파일 명령어는 "3.1.1 간단한 앱 그리기"와 동일하다. 정상적으로 컴파일 되었다면 아래와 같은 창이 출력된다.

Label 대신에 다른 위젯을 Window의 자식으로 추가할 수도 있다. 아래 코드는 Button 위젯을 Window의 자식으로 추가하는 예시이다.

 

// ... < 상략 > ...

static void clicked(GtkButton* button, gpointer user_data) {
    gtk_button_set_label(button, "Clicked");
}

static void activate(GtkApplication* app, gpointer user_data) {
    GtkWidget *window;
    GtkWidget *button;

    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);

    /* 
     * GtkButton: 클릭 가능한 위젯 객체를 생성한다.
     * gtk_button_new_with_label == gtk_button_new + gtk_button_set_label
     */
    button = gtk_button_new_with_label("Hello, world");
    /* 
     * 앞에서 activate를 콜백으로 등록하였듯이 여기서는 "clicked" 시그널이 발생하면, 
     * clicked 함수를 콜백으로 호출하도록 등록하였다.
     */
    g_signal_connect(button, "clicked", G_CALLBACK(clicked), NULL);
    gtk_window_set_child(GTK_WINDOW(window), button);
    gtk_widget_show(window);
}

// ... < 하략 > ...

 

컴파일을 하면 아래와 같이 클릭 가능한 창이 생성된다.

 

자, 이제는 Gtk에서 하나의 위젯을 그리는 방법에 대해서는 어느정도 감을 잡았다. 다음 포스트에서는 Container를 사용해서 여러개의 위젯을 관리 및 그리는 방법에 대해서 살펴볼 예정이다.

 

www.kernelpanic.kr/category/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4%20%EC%9D%BD%EA%B8%B0/%EB%A6%AC%EB%88%85%EC%8A%A4%EC%97%90%EC%84%9C%20%EA%B0%80%EC%9E%A5%20OOO%ED%95%9C%20GUI%20%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC%20-%20GTK

 

'오픈소스 읽기/리눅스에서 가장 OOO한 GUI 라이브러리 - GTK' 카테고리의 글 목록

 

www.kernelpanic.kr

반응형