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; }