GTKアプリケーション

GTK を用いて、GUI アプリケーションを作成しましょう。今回利用するのは、GTK1.2 です。C言語のライブラリなので、クラスを模した記述をします。

基本ソース例

以下のソースは、ウィンドウ上にラベルとボタンを1つずつ配置した GUI アプリケーションです。ボタンを押すとイベントが発生して、ラベルの内容を書き換えます。

#include <gtk/gtk.h>
#include <stdio.h>

/*************************************************
 * ボタンが押されたときのイベントハンドラ
 ************************************************/
void btn_click(GtkWidget *wig,gpointer p) {
    // ラベルに文字列を設定する
    gtk_label_set_text(label_mes, "いてっ!");
}

/*************************************************
 * メイン関数
 ************************************************/
int main(int argc, char* argv[])
{
    GtkWidget *window;          // ウィンドウ
    GtkWidget *label_mes;       // ラベル
    GtkWidget *button;          // ボタン

    // 適切なロケール情報が設定される(日本語文字列を使う場合は必須)
    gtk_set_locale();
    // GTK の初期化(必須)
    gtk_init(&argc, &argv);

    // ウィンドウを作成する
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    // ウィンドウで「×ボタン」が押されたときのシグナルを登録する
    gtk_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);
    // ウィンドウを表示する
    gtk_widget_show(window);

    // ボタンを、「叩く」というラベルを付けて作成する
    button = gtk_button_new_with_label("叩く");
    // ボタンが押されたときのシグナルを登録する
    gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(btn_click),NULL);
    // ボタンをウィンドウ上に載せる
    gtk_container_add(GTK_CONTAINER(window),button);
    // ボタンを表示する
    gtk_widget_show(button);

    // ラベルを、「空っぽ」という初期文字列を付けて作成する
    label_mes = gtk_label_new("〜♪");
    // ラベルをウィンドウ上に載せる
    gtk_container_add(GTK_CONTAINER(window),label_mes);
    // ラベルを表示する
    gtk_widget_show(label_mes);

    // GTK メインループに入る(イベント待受け状態へ移行する)
    gtk_main();

    return 0;
}

上記のソースが、GTK による GUI プログラミングの基本的な形になります。あとは、必要に応じてコンポーネントやイベントの追加を行なってください。

ビルド方法

ビルドは下記のように行ないます。ヘッダファイルとライブラリは、gtk-config コマンドにより、自動的に設定されます。

gcc -o gtk_test gtk_test.c `gtk-config --cflags` `gtk-config --libs`

各コンポーネントのレイアウト

各コンポーネント(ボタン、ラベルなど)は、垂直ボックスと水平ボックスを組み合わせてレイアウトします。

垂直ボックスコンポーネントを上から順番に、縦方向へレイアウトする
水平ボックスコンポーネントを上から順番に、横方向へレイアウトする

応用ソース例

応用というわけではありませんが、先に紹介した基本ソース例にもう少し多くの要素を加えています。

#include <gtk/gtk.h>
#include <stdio.h>

// イベント内など関数外で利用する変数
// (別ファイルで使う場合は、extern 宣言を追加する)
GtkWidget *label_mes;       // ラベル
GtkWidget *textfield;       // 1行テキストフィールド

/*************************************************
 * ボタン 1 が押されたときのイベントハンドラ
 ************************************************/
void btn_click1(GtkWidget *wig,gpointer p) {
    // 1行テキストフィールドに設定されている文字列を取得する
    gchar* text = gtk_entry_get_text(textfield);
    // ラベルに文字列を設定する
    gtk_label_set_text(label_mes, text);
}

/*************************************************
 * ボタン 2 が押されたときのイベントハンドラ
 ************************************************/
void btn_click2(GtkWidget *wig,gpointer p) {
    // ラベルに空文字列を設定する
    gtk_label_set_text(label_mes, "");
}

/*************************************************
 * タイマーイベントのハンドラ
 ************************************************/
void timer_event(GtkWidget *wig,gpointer p) {
    // 標準出力する
    printf("Timer Call");
}


void* windowThread(void* param);

/*************************************************
 * メイン関数
 ************************************************/
int main(int argc, char* argv[])
{
    pthread_t tid;

    // 適切なロケール情報が設定される(日本語文字列を使う場合は必須)
    gtk_set_locale();
    // GTK の初期化(必須)
    gtk_init(&argc, &argv);

    // 新規にスレッドを生成し、そこで GUI 画面を作成する。
    // もちろんメインスレッド内でも構わないが、その場合バックグラウンドの処理はできない
    pthread_create(&tid,NULL,windowThread,NULL);
    // GUI 画面用のスレッドが終了するまで、待ち受ける
    pthread_join(tid,NULL);

    return 0;
}

/*************************************************
 * GUI 画面生成する関数(スレッド登録用)
 ************************************************/
void* windowThread(void* param) {
    GtkWidget *window;          // ウィンドウ
    GtkWidget *vbox;            // 垂直ボックス
    GtkWidget *hbox;            // 水平ボックス
    GtkWidget *button1;         // ボタン 1
    GtkWidget *button2;         // ボタン 2
    GtkStyle *label_style;      // スタイル

    // スタイルを作成する
    label_style = gtk_style_new();
    // スタイルのフォントを、所定のフォントセットとする。
    // フォントセットとは、フォントをカンマで繋いだものである
    label_style->font = 
    gdk_fontset_load("-*-marumoji-*-*-*--*-*-*-*-*-*-jisx0201.1976-0,-*-marumoji-*-*-*--*-*-*-*-*-*-jisx0208.1990-0");

    // ウィンドウを作成する
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    // ウィンドウで「×ボタン」が押されたときのシグナルを登録する
    gtk_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);
    // ウィンドウを表示する
    gtk_widget_show(window);

    // 垂直ボックスを、要素間隔 5 ピクセルで作成する
    vbox = gtk_vbox_new(FALSE, 5);
    // 垂直ボックスをウィンドウ上に載せる
    gtk_container_add(GTK_CONTAINER(window), vbox);
    // 垂直ボックスを表示する
    gtk_widget_show(vbox);

    // テキストフィールドを作成する
    textfield = gtk_entry_new();
    // テキストフィールドを垂直ボックス上に載せる
    gtk_container_add(GTK_CONTAINER(vbox),textfield);
    // テキストフィールドを表示する
    gtk_widget_show(textfield);

    // 水平ボックスを、要素間隔 5 ピクセルで作成する
    hbox = gtk_hbox_new(FALSE, 5);
    // 水平ボックスをウィンドウ上に載せる
    gtk_container_add(GTK_CONTAINER(vbox), hbox);
    // 水平ボックスを表示する
    gtk_widget_show(hbox);

    // ボタン 1 を、「反映」というラベルを付けて作成する
    button1 = gtk_button_new_with_label("反映");
    // ボタン 1 が押されたときのシグナルを登録する
    gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(btn_click1),NULL);
    // ボタン 1 を水平ボックス上に載せる
    gtk_container_add(GTK_CONTAINER(hbox),button1);
    // ボタン 1 を表示する
    gtk_widget_show(button1);

    // ボタン 2 を、「消去」というラベルを付けて作成する
    button2 = gtk_button_new_with_label("消去");
    // ボタン 2 が押されたときのシグナルを登録する
    gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(btn_click2),NULL);
    // ボタン 2 を水平ボックス上に載せる
    gtk_container_add(GTK_CONTAINER(hbox),button2);
    // ボタン 2 を表示する
    gtk_widget_show(button2);

    // ラベルを、「空っぽ」という初期文字列を付けて作成する
    label_mes = gtk_label_new("空っぽ");
    // ラベルに対して、スタイルを適用する
    gtk_widget_set_style(label_mes, label_style);
    // ラベルに適用されたスタイルを反映させる
    gtk_widget_ensure_style(label_mes);
    // ラベルを垂直ボックス上に載せる
    gtk_container_add(GTK_CONTAINER(vbox),label_mes);
    // ラベルを表示する
    gtk_widget_show(label_mes);

    // タイムアウトイベントを登録する(周期的に呼ばれるイベント)
    gtk_timeout_add(1000, (GtkFunction)timer_event, NULL);

    // GTK メインループに入る(イベント待受け状態へ移行する)
    gtk_main();

    return NULL;
}

FAQ

日本語がまったく表示されない
gtk_set_locale() 関数は、ちゃんと呼び出していますか?
日本語が化けて表示される
正しい文字コードで、ソースファイルが保存されていますか?EUC を指定して、もう一度確認してください。gedit で編集すると、SJIS になっているかもしれません。
GUI の設定内容(ラベルテキストなど)を変えると、GUI の挙動がおかしくなる
別スレッドから値を変更していませんか?gtk_main() で待ち受けているスレッド以外から、GTK に変更を加えてはいけません。イベントなどを利用しましょう。タイマーイベントによるポーリングが有効かもしれません。また、ユーザー定義シグナルも使えるかもしれません。ただし後者については未調査です。

参考


履歴


トップ   編集 凍結解除 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2005-10-02 (日) 00:28:01