GUI プログラミング

Linux の GUI プログラミングは数多くの種類があって混乱しますが、共通するパターンがあるようです。GTK+, Ruby/GTK, Ryby/Tk, Tcl/Tk を例にしてそのパターンについて見て行きたいと思います。

ライブラリー/ヘッダーの導入

GUI プログラムを一から書き上げるのは手間が大変なのでライブラリーを利用しなければなりません。GUIプログラムの最初にはライブラリーやヘッダーファイルを読みこむための文を書きます。

gtk+
#include <gtk/gtk.h>
Ruby/GTK
require 'gtk'
Ruby/TK
require 'tk'
Tcl/Tk
Tcl/Tk では wish インタープリターがグラフィック関係の命令を解析するので他のファイルを include する必要はありません。

ライブラリーの初期化

GTK+ では、main() の中でライブラリーの初期化が必要です。Ruby/GTK や Ruby/Tk では初期化は自動的に行われるようです。

GTK+
gtk_init(&argc, &argv);

メインループ

GUI のメインループはメインルーチンの最後で必ず呼び出されウィジェットやキーボードからのイベントを捕えて各々の処理を行います。処理は各ウィジェットの属性として定義されるのでいちいちメインループで記述することはありません。

GTK+
gtk_main ();
Ruby/GTK
Gtk.main
Ruby/TK
Tk.mainloop
Tcl/Tk
wish インタープリターが自動的に実行します。

以上が GUI プログラムの骨格です。あとは様々なウィジェットを作成し、処理をイベントと関連付けます。でき上がったウィジェットは pack して配列し。最後に組上がったウィンドウを表示します。

ウィジェットの作成

GUI のプログラムはオブジェクト指向プログラムになるので、ウィジェットを作成するときはコンストラクターを呼び出します。

GTK+
GtkWidget *window;
GtkWidget *button;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label ("EXIT");
Ruby/GTK
window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
button = Gtk::Button.new("EXIT")
Ruby/Tk
button = TkButton.new(nil, 'text'=>'EXIT')
Tcl/Tk
button .b -text EXIT

イベントの処理

ウィジェットを作成したら各ウィジェットで発生するイベントとその処理を関連付けます。

GTK+
gtk_signal_connect (GTK_OBJECT (button), "clicked",
                    GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
Ruby/GTK
button.signal_connect('clicked') { Gtk.main_quit }
Ruby/Tk
button.bind('ButtonPress', proc{ exit })
Tcl/Tk
bind .b <ButtonPress> { exit }

ウィジェットの配置

でき上がったウィジェットはウィンドウに配置します。

GTK+
gtk_container_add (GTK_CONTAINER (window), button);
gtk_widget_show (button);
gtk_widget_show (window);
Ruby/GTK
window.add button
window.show_all
Ruby/Tk
button.pack
Tcl/Tk
pack .b

こうしてでき上がったウィジェットのプログラムを先ほどの骨格におさめるとプログラムの完成です。でき上がったプログラムのリストは次のようになります。

GUI サンプルプログラム

GTK+
#include <gtk/gtk.h>

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

        gtk_init (&argc, &argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        button = gtk_button_new_with_label ("EXIT");

        gtk_signal_connect (GTK_OBJECT (button), "clicked",
                            GTK_SIGNAL_FUNC (gtk_main_quit), NULL);

        gtk_container_add (GTK_CONTAINER (window), button);
        gtk_widget_show (button);
        gtk_widget_show (window);

        gtk_main ();

        exit (0);
}
Ruby/GTK
require 'gtk'

window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
button = Gtk::Button.new('EXIT')

button.signal_connect('clicked') { Gtk.main_quit }

window.add button
window.show_all

Gtk.main
Ruby/Tk
require 'tk'

button = TkButton.new(nil, 'text'=>'EXIT')
button.bind('ButtonPress', proc{ exit })
button.pack

Tk.mainloop
Tcl/Tk
button .b -text EXIT
bind .b <ButtonPress> { exit }
pack .b

GTK+ のプログラムをコンパイルするときは gcc -Wall -g sample.c -o sample `gtk-config --cflags` `gtk-config --libs` でコンパイルしてください。Ruby のプログラムは ruby sampl.rb で実行できます。Tcl/Tk は wish sample.tcl です。