やってみようRuby/Tk

Ruby/Tk を使えば Ruby で GUI プログラムを書くことができます。本を買って読むのが面倒な人もちょっとやってみましょう。このチュートリアルでは irb を使わずきちんとファイルに書き込んで行きます。しかし、作成するファイルは rubytk.rb 一個だけです。それを徐々に改良して行って使い方をマスターします。

まず、土台となるスクリプトを作成し、rubytk.rb に保存します。

require 'tk'
TkButton.new(nil, 'text'=>'exit').pack
Tk.mainloop

最初の行は Ruby/Tk ライブラリーを使えるようにするためのお約束です。第2行はボタンの作成です。TKButton クラスのオブジェクトを作成するメソッドが new です。new の引数の第一番目は どのフレームにそのオブジェクトを張り付けるかを示します。フレームとは写真の台紙のようなものでその上にオブジェクトを張り付けます。ここでは nil なのでオブジェクトは直接ウインドウに貼りつけられます。new の 2 番目以降の引数はボタンオブジェクトの属性とその内容の組のハッシュになります。({ と } が省略されています)。最後の pack というメソッドでフレームにそのオブジェクトを貼りつけます。最後の行の Tk.mainloop は Ruby/Tk を使うときのお約束で全ての文の最後に実行します。編集が済んだらコンソールから rubytk.rb を動かしてみてください。

$ ruby rubytk.rb

このウインドウでは、カーソルをボタンのところへ持って行ってクリックでへこませることはできますが、何も起こりません。ウインドウを消すにはタイトルバーのコントロールを使います。ここでボタンに機能を加えてみましょう。青色のところが変更箇所です。

require 'tk'
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack
Tk.mainloop

ボタンに機能を持たせるといっても、command 属性にコードブロックを登録するだけなので簡単です。今度は exit ボタンをクリックするとウインドウは消えてしまいます。ボタンだけでは寂しいのでラベルを追加してみましょう。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack
Tk.mainloop

実行例は次の図のようになります。label オブジェクトは改行のない文字列を表示するためのオブジェクトです。

今度は exit ボタンを右端へ移動しましょう。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack('side'=>'right')
Tk.mainloop

実行結果はこの通りです。

ウインドウに書き込みもできるとうれしいので、エントリー・オブジェクトを追加します。Entry オブジェクトに書き込まれたデータは後で利用したいので変数 e にオブジェクトを代入しておきます。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
e = TkEntry.new.pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack('side'=>'right')
Tk.mainloop

実行結果は次の通りです。エントリー・フィールドをクリックすると文字入力ができます。

段々欲が出て来たので、エントリーフィールドに入力した名前を使ってウインドウ内に挨拶を表示させるようにしてみましょう。方法は次のようにします。結果を表示する無地のラベルと、挨拶の表示をするためのボタンを追加します。エントリーからのデータの取り出しは、エントリー・オブジェクトを代入した変数 e を使って e.value で取り出すことができます。結果を表示するための無地のラベル・オブジェクトも変数 l に代入しておくと、l.text( "Hi, #{e.value}" ) で結果を出力することができます。スクリプトは次のように変更します。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
e = TkEntry.new.pack
l = TkLabel.new.pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack('side'=>'right')
TkButton.new(nil, 'text'=>'Hi', 'command'=>proc{l.text("Hi, #{e.value}")}).pack('side'=>'left')
Tk.mainloop

結果は次のようになります。

こうなると止まりません。エントリーフィールドの大きさを少し小さくして、横に name: というラベルを張り付けて見ましょう。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
e = TkEntry.new(nil, 'width'=>8).pack('side'=>'right')
el = TkLabel.new(nil, 'text'=>'name: ').pack('side'=>'left')
l = TkLabel.new.pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack('side'=>'right')
TkButton.new(nil, 'text'=>'Hi', 'command'=>proc{l.text("Hi, #{e.value}")}).pack('side'=>'left')
Tk.mainloop

結果です。

ちょっとイメージと違うことになってしまいました。name ラベルとエントリーの間に表示用ラベルがはいり込む形になっています。これを解決するためには、name ラベル・オブジェクトとエントリー・オブジェクトを先ず一枚のフレームオブジェクトに張り付けて、そのフレーム・オブジェクトの方をウインドウに pack すれば良いのです。そこでスクリプトを次のように変更します。

require 'tk'
TkLabel.new(nil, 'text'=>'Ruby/Tk is cool').pack
f = TkFrame.new.pack
e = TkEntry.new(f,'width'=>8).pack('side'=>'right')
el = TkLabel.new(f, 'text'=>'name: ').pack('side'=>'left')
l = TkLabel.new.pack
TkButton.new(nil, 'text'=>'exit', 'command'=>proc{exit}).pack('side'=>'right')
TkButton.new(nil, 'text'=>'Hi', 'command'=>proc{l.text("Hi, #{e.value}")}).pack('side'=>'left')
Tk.mainloop

e エントリー・オブジェクトと el ラベル・オブジェクトの new メソッドの第一引数が nil から f に変わっているのに注意してください。こうすることで、e と el をまずフレーム f に貼りつけたあと、f フレームの方をウインドウに貼りつけるようにしたのが分かります。pack を使ってウインドウをデザインするときはフレームを上手に利用するのがコツです。

ついに挨拶をするウインドウが完成です。

ここまで簡単に Ruby/Tk の説明をしてきました。意外と簡単だったでしょう。しかし Ruby/Tk を活用して GUI プログラムをバリバリ作成するためには本を何冊か買った方がよさそうです。

参考図書

Ruby を 256 倍使うための本(界道編)、永井秀利著、ASCII

参考ホームページ

Ruby CUIセンターRuby の公式ホームページの記事です。Ruby/Tk と Ruby/Gtk の文書へのリンクが豊富。
Ruby > (Smalltalk + Perl) / 2greentea さんの Ruby なページ。たくさんの Ruby/Tk のサンプルがあります。
Tk Widget-DemoRuby/TK のウィジェットのデモ(英語版)。ウィジェットの種類とその効果が分かる。
Ruby/Tk TutorialKero さんの Ruby/TK チュートリアル
Tcl/Tk manualTcl/TK のマニュアル