C言語でGTK+ 2を扱う上での幾つかのメモ(第4回)
「C言語でGTK+ 2を扱う上での幾つかのメモ(第3回)」の続き。
メインループを用いた簡単な例
下の例を実行すると、ラベル(文字列を表示するGUI部品)のみを含むウィンドウを表示し、これを閉じると終了する。
[任意]ファイル名: gtkhello.c
#include <gtk/gtk.h> #include <stdlib.h> /* * gcc -O2 -Wall -Wextra $(pkg-config --cflags --libs gtk+-2.0) gtkhello.c -o gtkhello */ int main (int argc, char **argv) { /* GUI部品 */ GtkWidget *mainwindow, *label; /* GTK+の初期化 */ gtk_init (&argc, &argv); /* * 新しいウィンドウを生成 * 通常のウィンドウはGTK_WINDOW_TOPLEVELを引数に指定 * ポップアップするメニューやツールチップのようなものに限りGTK_WINDOW_POPUP * GTK_WINDOW_POPUPではウィンドウ装飾が付かないが * 通常のウィンドウでは *そのためにGTK_WINDOW_POPUPを指定してはいけない* 代わりに * 「GTK_WINDOW_TOPLEVEL指定かつgtk_window_set_decorated()でFALSE指定」をする * * なお、Vala言語のGtk.WindowクラスではGtk.WindowType.TOPLEVELの指定は初期値なので不要 */ mainwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 新しいラベルウィジェットを生成 */ label = gtk_label_new ("Hello, Work !!"); /* * ウィンドウにラベルを入れる * この入れ方ではウィンドウにラベルを1つだけしか入れられない(メニューバーも入らない) * 複雑にレイアウトしたい場合はGtkVBox(縦分割)やGtkHBox(横分割)などを用いる * * これはGtkContainerクラスの関数なので引数は「GtkContainer *」型となり * 宣言したGtkWidget型構造体へのポインタはGTK_CONTAINER()マクロで型変換する必要がある * 型変換マクロは「GTK_XXX」の形で色々とあり、部品ごとの型で宣言したり * ハンドラの引数として入る場合に「GtkWidget *」型で関数に渡すような場面では * GTK_WIDGET()マクロを用いて型変換する * * 操作を行う関数では1番目の引数に対象のGUI部品を指定する */ gtk_container_add (GTK_CONTAINER (mainwindow), label); /* * 子のGUI部品を含め、指定したGUI部品以下を全て表示される状態にする * GtkWidgetクラスの関数なので型変換はしない * 単体版gtk_widget_show()や逆のgtk_widget_hide(), * 逆の全体(子を含む)版のgtk_widget_hide_all()もある */ gtk_widget_show_all (mainwindow); /* * ウィンドウのタイトルを変更 * GtkWindowクラスの関数なのでGTK_WINDOW()で型変換する */ gtk_window_set_title (GTK_WINDOW (mainwindow), "Hello"); /* GUI部品の最小サイズを指定 */ gtk_widget_set_size_request (mainwindow, 100, 30); /* ウィンドウに対してサイズの変更をする(GtkWindowクラス) */ gtk_window_resize (GTK_WINDOW (mainwindow), 200, 150); /* * 閉じるボタンが押されたときにメインループを抜けてgtk_main()の先に進むようにする * 1番目の引数が処理対象(GObjectオブジェクト)の場所 * 2番目がGObjectシグナル名 * 3番目がハンドラの場所 * 4番目は追加のデータ(任意/なければNULL) * 追加データの種類や使い方によっては * g_signal_connect_object()やg_signal_connect_swapped()などの * 別の関数でシグナル接続することもある */ g_signal_connect (G_OBJECT (mainwindow), "delete-event", G_CALLBACK (gtk_main_quit), NULL); /* gtk_main_quit()が呼ばれるまでメインのループが回り続ける */ gtk_main (); /* 終了 */ return EXIT_SUCCESS; }
GLibの提供する基本データ型について
C言語のGLibライブラリではint型の代わりにgint型,char型の代わりにgchar型などといった独自のデータ型を用いる。これは移植性を考えてGLibが用意したものとなっており、真偽値のgbooleanという型*1なども新しく追加されている。ただし、標準Cライブラリの関数を用いる際に引数に型変換なしでGLibの提供する型の変数を用いたり、main()関数の戻り値の型をgint型などにしたりはしないようにする。GNU/Linuxに限定すれば、例えばgintとintは偶然(内部的に)同じ型となっており、実用上大きな問題にはならないかもしれないが、OSの仕様で決まっている型をわざわざ別の型にはしない。
(2010/7/1)補足として、gintやgcharなどの型はそれぞれリファレンスによると「Corresponds to the standard C [C言語の標準の型の名前] type. 」つまりそれぞれのC言語の標準の型に相当するものだとしており、内部的にも環境を問わず「typedef int gint;」のようになっているので、同じものとして扱っても動作上の問題はない(GLib上のgint型は各OSごとのint型と内部的に等しい、と言える)。OSに依存しない固定bit数を要求するときにはgint64などのbit数の保証されているものを用いる。gint64型などの内部的な定義は環境ごとに異なり/usr/lib(64)/glib-2.0/include/glibconfig.hに記述されている。
提供されている型に関する詳細は
- バージョン2.8系日本語訳: http://web.archive.org/web/20080222233546/www.gnome.gr.jp/docs/glib-2.8.x-refs/glib/glib-Basic-Types.html
- 最新安定版(英語): http://library.gnome.org/devel/glib/stable/glib-Basic-Types.html
も参照。また、型ごとの値の上限/下限も
- バージョン2.8系日本語訳: http://web.archive.org/web/20080322030231/www.gnome.gr.jp/docs/glib-2.8.x-refs/glib/glib-Limits-of-Basic-Types.html
- 最新安定版(英語): http://library.gnome.org/devel/glib/stable/glib-Limits-of-Basic-Types.html
のマクロで確認できる。
なお、関連する項目として、基本データ型以外に、よく用いられる連結リスト(リスト構造)のようなものはデータ型(単方向 双方向)が標準で利用可能で、かつこれを扱う上で便利な関数も用意されている。
(2010/8/23)「GLib 2が用意している基本的なデータ型について(ページ1/3)」も参照。
(「C言語でGTK+ 2を扱う上での幾つかのメモ(第5回)」に続く)
関連記事:
*1:TRUE(真)かFALSE(偽)のどちらかをとり、大文字で記述する