ラベル GTK の投稿を表示しています。 すべての投稿を表示
ラベル GTK の投稿を表示しています。 すべての投稿を表示

2013年2月27日水曜日

[GTK+]Glade で Hello World 作成

  1. Glade を起動して Top level に Main window, Container に 3 段の virtual box (垂直ボックス), その中に Text entry, label, button を配置する
  2. Main window の名前を Hello World にする。Entry, Label, Button はデフォルトのまま entry1, label1, button1 としておく
  3. button1 のシグナル clicked にハンドラ button1_clicked_cb を登録する
  4. 作成した glade ファイルを保存する (hello_world.glade)
  5. hello_world.c を作成する。main 内で hello_world.glade を読み出して各 widget を紐付ける
    Example: hello_world.c
    #include <gtk/gtk.h>
    
    GtkBuilder *builder;
    GtkWidget *label1;
    GtkWidget *entry1;
    
    G_MODULE_EXPORT void button1_clicked_cb(GtkWidget *widget, gpointer data)
    {
        const gchar *text;
        char buf[256];
    
        g_print("%s is called\n", __FUNCTION__);
        text = gtk_entry_get_text(GTK_ENTRY(entry1));
        sprintf(buf, "%s", text);
        gtk_label_set_text(GTK_LABEL(label1), buf);
    }
    
    int main(int argc, char **argv)
    {
        GtkWidget *window;
        GError *error = NULL;
        GtkSettings *settings;
    
        gtk_init(&argc, &argv);
    
        /* Create a new GtkBuilder object */
        builder = gtk_builder_new();
    
        if (!gtk_builder_add_from_file(builder, "hello_world.glade", &error)) {
         g_warning("%s", error->message);
         g_free(error);
         return 1;
        }
    
        settings = gtk_settings_get_default();
    // gtk_settings_set_string_property (settings, "gtk-font-name", "MS Mincho 14", "");
        gtk_settings_set_string_property (settings, "gtk-font-name", "Sazanami Gothic 14", "");
    
        window = GTK_WIDGET(gtk_builder_get_object(builder, "Hello World"));
        label1 = GTK_WIDGET(gtk_builder_get_object(builder, "label1"));
        entry1 = GTK_WIDGET(gtk_builder_get_object(builder, "entry1"));
    
        gtk_builder_connect_signals(builder, NULL);
        g_object_unref(G_OBJECT(builder));
        gtk_widget_show(window);
    
        gtk_main();
    
        return 0;
    }
    
  6. コンパイル
    Makefile の CFLAGS に CFLAGS に gmodule-2.0 を付ける。LDFLAGS に -mwindows を付けると DOS 窓を開くことなくプログラムが実行できるようになる
    Example: Makefile
    CC=gcc
    PKG_CONFIG = c:/usr/MinGW/bin/pkg-config
    CFLAGS = -Wall -DGTK_DISABLE_DEPRECATED `$(PKG_CONFIG) --cflags gtk+-2.0 gmodule-2.0`
    LDFLAGS = `$(PKG_CONFIG) --libs gtk+-2.0` -mwindows
    TARGET = \
        hello_world.exe
    
    .SUFFIXES: .exe .c .o
    
    # $@ は生成しようとしているターゲット名
    # $< は依存しているファイル
    .c.o:
        $(CC) $(CFLAGS) -c -o $@ $<
    
    .o.exe:
        $(CC) -o $@ $< $(LDFLAGS)
    
    default: $(TARGET)
    
    pkgconfig:
        $(PKG_CONFIG) --cflags gtk+-2.0
        $(PKG_CONFIG) --libs gtk+-2.0
    
    clean:
        rm -rf *.o *.exe
    
  7. 実行結果

[GTK+]Glade のインストール

  1. Glade - A User Interface Designer の Windows Binaries にある glade3-3.6.7-with-GTK+.exe (2009/10/09 現在) をダウンロードする
  2. ダウンロードしたファイルを実行して Glade をインストールする

[GTK+]アプリのフォント変更

GtkSetting を呼び出して gtk-font-name という property を変更することでアプリに使用するフォントを変更できる
    GtkSettings *settings;

    settings = gtk_settings_get_default();
//    gtk_settings_set_string_property (settings, "gtk-font-name", "MS Mincho 14", "");
    gtk_settings_set_string_property (settings, "gtk-font-name", "Sazanami Gothic 14", "");

[GTK+]ボタンにアイコンを追加する

  • box 内に image と label を配置して画像付きボタンを作成する
  • 画像には xpm ファイルを使用する
Example: button.c
#include <gtk/gtk.h>

static GtkWidget *xpm_label_box(gchar *xpm_filename, gchar *label_text)
{
    GtkWidget *box;
    GtkWidget *label;
    GtkWidget *image;

    /* Create box for image and label */
    box = gtk_hbox_new(FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(box), 2);

    /* Load image for the button */
    image = gtk_image_new_from_file(xpm_filename);

    /* Create a label for the button */
    label = gtk_label_new(label_text);

    /* Pack the image and label into the box */
    gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 3);
    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 3);

    gtk_widget_show(image);
    gtk_widget_show(label);

    return box;
}

static void callback(GtkWidget *widget, gpointer data)
{
    g_print("Hello again - %s was pressed\n", (char*)data);
}

int main(int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *button, *toggle_button;
    GtkWidget *box;

    gtk_init(&argc, &argv);

    /* Create a new window */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Pixmap'd buttons");

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);

    /* ボーダーの幅を設定 */
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);

    /* Create a new button */
    button = gtk_button_new();

    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(callback), (gpointer)"cool button");

    box = xpm_label_box("CarGrey.xpm", "cool button");

    /* Create a new toggle_button */
    toggle_button = gtk_toggle_button_new();
    g_signal_connect(G_OBJECT(toggle_button), "clicked", G_CALLBACK(callback), (gpointer)"toggle button");

    /* Pack and show all our widget */
    gtk_widget_show(box);
    gtk_container_add(GTK_CONTAINER(button), box);
    gtk_widget_show(button);
    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show(window);

    gtk_main();

    return 0;
}
実行結果

[GTK+]テキスト入力欄

  • テキスト入力欄に入力した文字列を label に反映する
  • ボタンをクリックすると button_click() が呼び出され、その中で entry に書き込まれた文字列を gtk_entry_get_text() で読み出し、label に gtk_label_set_text() で反映する
Example: entry.c
#include <gtk/gtk.h>

typedef struct main_dialog_type {
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;
    GtkWidget *entry;
    GtkWidget *label;
} MainDialog;

/* ボタンがクリックされたら entry に入力された文字列を読み込み label を更新する */
void button_click(GtkWidget *widget, gpointer data)
{
    const gchar *text;
    char buf[256];

    text = gtk_entry_get_text(GTK_ENTRY(((MainDialog*)data)->entry));
    sprintf(buf, "%s", text);
    gtk_label_set_text(GTK_LABEL(((MainDialog*)data)->label), buf);
}

int main(int argc, char **argv)
{
    MainDialog dialog;

    gtk_init(&argc, &argv);

    dialog.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(dialog.window), "GtkEntry");
    gtk_window_set_position(GTK_WINDOW(dialog.window), GTK_WIN_POS_CENTER);
    /* table を作成し、各要素を table 上に配置する */
    /*  0          1          2
     * 0+----------+----------+
     *  |          |          |
     * 1+----------+----------+
     *  |          |          |
     * 2+----------+----------+
     */
    /* gtk_table_attach_defaults(*table, *child, left_attach, right_attach, top_attach, bottom_attach); */

    dialog.table = gtk_table_new(2, 2, TRUE);
    gtk_container_add(GTK_CONTAINER(dialog.window), dialog.table);

    /* entry を下記の場所に配置する */
    /*  0          1          2
     * 0+----------+----------+
     *  |   XXXX   |          |
     * 1+----------+----------+
     *  |          |          |
     * 2+----------+----------+
     */
    dialog.entry = gtk_entry_new();
    gtk_table_attach_defaults(GTK_TABLE(dialog.table), dialog.entry, 0, 1, 0, 1);

    /* label を下記の場所に配置する */
    /*  0          1          2
     * 0+----------+----------+
     *  |          |   XXXX   |
     * 1+----------+----------+
     *  |          |          |
     * 2+----------+----------+
     */
    dialog.label = gtk_label_new("blank");
    gtk_table_attach_defaults(GTK_TABLE(dialog.table), dialog.label, 1, 2, 0, 1);

    /* button を下記の場所に配置する */
    /*  0          1          2
     * 0+----------+----------+
     *  |          |          |
     * 1+----------+----------+
     *  |   XXXXXXXXXXXXXXX   |
     * 2+----------+----------+
     */
    dialog.button = gtk_button_new_with_label("Enter");
    gtk_table_attach_defaults(GTK_TABLE(dialog.table), dialog.button, 0, 2, 1, 2);
    g_signal_connect(dialog.button, "clicked", G_CALLBACK(button_click), &dialog);

    gtk_widget_show_all(dialog.window);

    g_signal_connect_swapped(G_OBJECT(dialog.window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_main();

    return 0;
}
実行結果

[GTK+]ボタンをクリックした時のイベント

  • 配置したボタンをクリックすることでイベントを実行するには g_signal_connect() で clicked イベントを指定する
  • "+" のボタンを押すと increase() が呼び出され、label 表記が gtk_label_set_text() によって書き換えられる
Example: increase_decrease.c
#include <gtk/gtk.h>

gint count = 0;
char buf[5];

void increase(GtkWidget *widget, gpointer label)
{
    count++;

    sprintf(buf, "%d", count);
    gtk_label_set_text(label, buf);
}

void decrease(GtkWidget *widget, gpointer label)
{
    count--;

    sprintf(buf, "%d", count);
    gtk_label_set_text(label, buf);
}

int main(int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *label;
    GtkWidget *frame;
    GtkWidget *plus;
    GtkWidget *minus;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "+-");
    gtk_window_set_default_size(GTK_WINDOW(window), 250, 180);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    frame = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), frame);

    plus = gtk_button_new_with_label("+");
    gtk_widget_set_size_request(plus, 80, 35);
    gtk_fixed_put(GTK_FIXED(frame), plus, 50, 20);

    minus = gtk_button_new_with_label("-");
    gtk_widget_set_size_request(minus, 80, 35);
    gtk_fixed_put(GTK_FIXED(frame), minus, 50, 80);

    label = gtk_label_new("0");
    gtk_fixed_put(GTK_FIXED(frame), label, 190, 58);

    gtk_widget_show_all(window);

    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(plus, "clicked", G_CALLBACK(increase), label);
    g_signal_connect(minus, "clicked", G_CALLBACK(decrease), label);

    gtk_main();

    return 0;
}
実行結果

[GTK+]アプリケーションアイコンを追加する

gtk_window_set_icon() でアプリの左上に表示されるアイコンを追加できる
Example: application_icon.c
#include <gtk/gtk.h>

GdkPixbuf *create_pixbuf(const gchar *filename)
{
    GdkPixbuf *pixbuf;
    GError *error = NULL;

    pixbuf = gdk_pixbuf_new_from_file(filename, &error);
    if (!pixbuf) {
     fprintf(stderr, "%s\n", error->message);
     g_error_free(error);
    }

    return pixbuf;
}

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

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "icon");
    gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("Hippopotamus.ico"));
    gtk_widget_show(window);

    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_main();

    return 0;
}
実行結果

[GTK+]アプリを画面中央に表示する

gtk_window_set_position() で Center position を指定することでアプリウィンドウを画面中央に表示できる
Example: centering.c
#include <gtk/gtk.h>

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

   gtk_init(&argc, &argv);

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW(window), "Center");
   gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
   gtk_widget_show(window);

   g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

   gtk_main();

   return 0;
}
実行結果

[GTK+]アプリ起動時に DOS 窓を表示させない

リンカーオプションに -mwindows を付けることで DOS 窓を表示させないようにできる
Example: Makefile
CC=gcc
PKG_CONFIG = c:/usr/MinGW/bin/pkg-config
CFLAGS = -Wall -DGTK_DISABLE_DEPRECATED `$(PKG_CONFIG) --cflags gtk+-2.0`
LDFLAGS = `$(PKG_CONFIG) --libs gtk+-2.0` -mwindows

(中略)
.c.o:
   $(CC) $(CFLAGS) -c -o $@ $<

.o.exe:
   $(CC) -o $@ $< $(LDFLAGS)
 

[GTK+]MinGW + GDK+ 環境設定

  1. GTK+ - Download for Windows から boundle パッケージををダウンロードする
  2. 展開したファイルを MinGW をインストールしてあるディレクトリに移動する
  3. サンプルプログラムを準備する
    Example: hello.c
    #include <gtk/gtk.h>
    
    static void destroy(GtkWidget *widget, gpointer data)
    {
        gtk_main_quit();
    }
    
    int main(int argc, char **argv)
    {
        GtkWidget *window;
        GtkWidget *label;
    
        gtk_init(&argc, &argv);
    
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        label = gtk_label_new("Hello, world!");
        gtk_container_add(GTK_CONTAINER(window), label);
        gtk_widget_show(label);
        gtk_widget_show(window);
    
        g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
        gtk_main();
    
        return 0;
    }
    
    Example: Makefile
    CC=gcc
    PKG_CONFIG = c:/usr/MinGW/bin/pkg-config
    CFLAGS = -Wall -DGTK_DISABLE_DEPRECATED `$(PKG_CONFIG) --cflags gtk+-2.0`
    LDFLAGS = `$(PKG_CONFIG) --libs gtk+-2.0`
    TARGET = \
        hello.exe
    
    .SUFFIXES: .exe .c .o
    
    # $@ は生成しようとしているターゲット名
    # $< は依存しているファイル
    .c.o:
        $(CC) $(CFLAGS) -c -o $@ $<
    
    .o.exe:
        $(CC) -o $@ $< $(LDFLAGS)
    
    default: $(TARGET)
    
    pkgconfig:
        $(PKG_CONFIG) --cflags gtk+-2.0
        $(PKG_CONFIG) --libs gtk+-2.0
    
    clean:
        rm -rf *.o *.exe
    
  4. コンパイルする
  5. 作成された hello.exe を実行する