前回のサンプル集の最後にも書きましたが、Tk の tag を活用すると色々と面白いことができそうです。そこで、tag の使い方を実験するためのスクリプト tkmove3.rb を作りました。下のリンクを左クリックすると全リストを見ることができます。またリンクを右クリックしてファイルをダウンロードできます。tkmove3.rb は簡単なドロープログラムを自分のスクリプトに導入するためのクラスライブラリーになっています。次の説明のようにテスト用の testbed メソッドを持っていますから、使い方は簡単にわかるとおもいます。testbed を使うときは基本的にまずボタンをクリックしてからキャンバス上でマウスを動かすという操作になります。アイテムのグループ化のばあいは、Are ボタンをクリックした後グループ化したいアイテムをボックスで囲みます。そのあと Grp ボタンをクリックすると、選択されたアイテムがグループ化されます。グループ化の解除の場合はまず Gbk ボタンを押してから、グループ化しているアイテムをクリックします。
ファイル名: tkmove3.rb
使い方は次のようにします。テスト用のスクリプトから require 'tkmove3.rb' とします。次に include TestBed でテスト用ルーチンのモジュールを導入します。次に c = TkCanvas.new.pack でキャンバスを作った後、testbed( c ) のようにキャンバスオブジェクト c を引数に testbed メソッドを呼び出します。最後に Tk.mainloop として完成です。スクリプトは次のようになります。
ファイル名: testmove3.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed(c) Tk.mainloop
addtag_all メソッドを使うとキャンバス上の全てのアイテムに同じタグをつけることができます。メソッドの書式は <キャンバスオブジェクト>.addtag_all('タグ名')です。例えばキャンバスオブジェクトが変数 c に代入されていて、タグ名を 'group' にしたいときは、c.addtag_all('group') とします。下のサンプルスクリプトを起動したら、キャンバスに2,3 個のアイテムを作成した後 addtag_all ボタンを押してみてください。何も起こりませんが、その後 Mv ボタンを押して移動モードにした後、マウスカーソルで動かしてみると全てのアイテムが一つのアイテムになったように動きます。こんどは dtag ボタンを押してください。また Mv ボタンを押してアイテムを動かしてみると今度はバラバラになっているのが分かります。dtag メソッドはタグをタグリストから取り外すメソッドです。下の例では c.dtag( 'group' )という使い方をしています。
ファイル名: all.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed( c ) TkFrame.new(nil){|f| TkButton.new(f, 'text'=>'addtag_all', 'command'=>proc{ c.addtag_all( 'group' ) }).pack('side'=>'left') TkButton.new(f, 'text'=>'dtag', 'command'=>proc{ c.dtag( 'group' ) }).pack('side'=>'left') }.pack Tk.mainloop
addtag_above メソッドの書式は canvasobject.addtag_above(tagOrId, targetobject) です。targetobject のアイテムオブジェクトの直上のアイテムに tagOrId のタグがつけられます。サンプルスクリプト addtag_above.rb を起動したら矩形か楕円形のアイテムを数個重ねて描いて(重ねなくても構いませんが重ねた方が上下関係が良くわかります)、addtag_above ボタンをクリックした後適当にアイテムをクリックしてみてください。クリックしたアイテムの直上のアイテムの色が変わります。
ファイル名: addtag_above.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed( c ) f = TkFrame.new.pack TkButton.new(f, 'text'=>'addtag_above', 'command'=>proc{ c.bind('B1-Motion', proc{}) c.bind('1', proc{ item = c.find_withtag('current').shift c.addtag_above( 'above', item ) item = c.find_withtag('above').shift if item != nil item.fill('yellow') end c.dtag('above') }) }).pack('side'=>'left') Tk.mainloop
addtag_below メソッドでは addtag_above メソッドと反対に target のアイテムの直下のアイテムにタグがつけられます。
ファイル名: addtag_below.rb
addtag_closest メソッドの書式は canvasobject.addtag_closest('tagname', x, y, halo, start) です。halo, start は省略できます。このメソッドを使うと点(x、y)に最も近いアイテムに 'tagname' のタグがつけられます。サンプルスクリプトを起動したら黄色い点の周りにアイテムを何個か作成して addtag_closest ボタンをクリックしてください。
ファイル名: addtag_closest.rb
addtag_enclosed メソッドの書式は canvasobject.addtag_enclosed(tagOrId, x1, y1, x2, y2) です。x1, y1, x2, y2 の矩形領域の中にあるアイテムは tagOrId で示されたタグ名がつけられます。矩形領域の境界線上あるいは外にあるアイテムは影響を受けません。テストスクリプトを起動させたら矩形領域の内側と外側にアイテムを作成したあと、addtag_enclosed ボタンと Mv ボタンを押してその効果を確かめてください。
ファイル名: enclosed.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed( c ) x1, y1, x2, y2 = 50, 50, 200, 150 TkcRectangle.new(c, x1, y1, x2, y2) TkFrame.new{|f| TkButton.new(f, 'text'=>'addtag_enclosed', 'command'=>proc{ c.addtag_enclosed('group', x1, y1, x2, y2) }).pack('side'=>'left') TkButton.new(f, 'text'=>'dtag', 'command'=>proc{ c.dtag('group') }).pack('side'=>'left') }.pack Tk.mainloop
addtag_overlapping メソッドは addtag_enclosed メソッドと似ていますが、境界線上のアイテムにもタグがつけられるところが違います。
ファイル名: overlapping.rb"
canvasobject.addtag_withtag( tag1, tag2 ) メソッドでは tag2 のついているアイテム全てに tag1 をつけます。サンプルでは 'tag2' のついている黄色い丸と青い丸は一緒に動きますが、'tag1'のついた赤い丸は黄色と青の丸とは一緒には動きません。'addtag_withtag' ボタンを押すと、'tag2'の二つの丸に 'tag1' のタグがつけられるため三つの丸は一緒に動くようになります。
スクリプトではアイテムに最初に 'item' という余計なタグをはりつけていますが、こののタグは tkmove3.rb を利用してアイテムを動かす場合に必要です。tkmove3.rb の内部仕様なので無視してください。マウスでタグを利用した移動を実現するために TkDraw クラスのサブクラスでアイテムを発生させる場合に、アイテムには 'item' と言うタグとそのアイテムの id 名のタグの二つが自動的につけられます。二つもタグをつけている理由はこうです。マウスでアイテムを動かす場合、itembind メソッドでは 'item' タグがついているかどうかで識別します。したがって、全てのアイテムには 'item' タグがついている必要があります。しかし、その場合 'item' タグしかついていないアイテムを動かすと、他の全てのアイテムも動いてしまいます。そこで、全てのアイテムに対し、共通のタグ 'item' とそのアイテムに固有な id 名を利用したタグの二種類のタグをつけることにしたのです。
ファイル名: withtag.rb
require 'tkmove3.rb' c = TkCanvas.new.pack m = TkMove.new( c ) m.bind item1 = TkcOval.new(c, 70, 70, 100, 100, 'fill'=>'red') item1.addtag('item'); item1.addtag('tag1') item2 = TkcOval.new(c, 120, 70, 150, 100, 'fill'=>'yellow') item2.addtag('item'); item2.addtag('tag2') item3 = TkcOval.new(c, 170, 70, 200, 100, 'fill'=>'blue') item3.addtag('item'); item3.addtag('tag2') TkButton.new(nil, 'text'=>'c.addtag_withtag( tag1, tag2 )', 'command'=>proc{c.addtag_withtag( 'tag1', 'tag2')}).pack Tk.mainloop
gettags メソッドはアイテムにつけられた tag のリストを取得するメソッドです。書式は canvasobject.gettags( 'tagOrid' ) です。戻り値はタグ名のリストになります。サンプルスクリプトではキャンバスにアイテムを作成した後、c.gettags( 'current' )ボタンをクリックしてみてください。表示領域にそのアイテムのタグのリストが表示されます。また、Are ボタンで領域を指定した後 Grp をクリックしてから c.gettags('current') でタグを表示して先程の結果と比較してみてください。
ファイル名: gettags.rb
bbox メソッドは tag のリストで示されるアイテムを全て囲む領域の位置情報を取得するためのメソッドです。書式は canvasobject.bbox('tag1' <,'tag2', ...> ) です。戻り値は領域の位置情報のリストです。サンプルスクリプトは次のようになります。適当にアイテムをマウスで作成した後 bbox ボタンをクリックすると表示したアイテムを全て囲む矩形の領域が表示されます。
ファイル名: bbox.rb
find_enclosed メソッドは領域内にあるアイテムの情報を取得するメソッドです。書式は、canvas_object.find_enclosed(x1, y1, x2, y2) です。戻り値はその領域内のアイテムのオブジェクトになります。次のテストスクリプトを使うと感じが分かると思います。矩形の領域内にオブジェクトを作成して find_enclosed ボタンをクリックするとそのオブジェクトの情報が表示されます。
ファイル名: find.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed( c ) x1, y1, x2, y2 = 50, 50, 200, 150 TkcRectangle.new(c, x1, y1, x2, y2) l = TkMessage.new TkFrame.new{|f| TkButton.new(f, 'text'=>'find_enclosed', 'command'=>proc{ c.dtag('selected'); l.text(c.find_enclosed(x1, y1, x2, y2).inspect) }).pack('side'=>'left') }.pack l.pack Tk.mainloop
find_withtag メソッドは tag 名のついたアイテムオブジェクトを見つけるスクリプトです。書式は cannvasobject.find_withtag( 'tagname' ) です。戻り値はアイテムオブジェクトのリストです。マウスカーソルでアイテムをクリックしたときにそのアイテムのオブジェクトを得るときなどに使います。サンプルスクリプトを下に示します。アイテムを作成したら、find_withtag をクリックした後でそのアイテムをクリックするとオブジェクトのリストが得られます。find_withtag().shift をクリックしてからアイテムをクリックするとそのリストの先頭のアイテムオブジェクトが得られます。アイテムの情報をクリックで取りたいときにこのテクニックを使います。
ファイル名: find_withtag.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed( c ) l = TkMessage.new TkFrame.new{|f| TkButton.new(f, 'text'=>'find_withtag', 'command'=>proc{ c.dtag('selected'); c.bind('1', proc{ eval( "l.text( c.find_withtag('current').inspect )" ) }) }).pack('side'=>'left') TkButton.new(f, 'text'=>'find_withtag().shift', 'command'=>proc{ c.dtag('selected'); c.bind('1', proc{ eval( "l.text( c.find_withtag('current').shift.inspect )" ) }) }).pack('side'=>'left') }.pack l.pack Tk.mainloop
次のスクリプトは find_withtag の応用です。addtag_withtag ボタンをクリックした後マウスカーソルでアイテムをクリックすると tag name: エントリーのタグ名の tag をアイテムにつけることができます。find_withtag ボタンをクリックすると tag name: に表示されたタグ名のついたアイテムのタグの情報がメッセージウィジェットに表示され、アイテムの色が青色になります。
ファイル名: find_withtag2.rb
ウィンドウズなどで見かけるデスクトップ上の複数のアイテムを選択するときにドラッグして作る矩形領域を表示するためのクラスが TkdArea クラスです。スクリプトはこのホームページ冒頭の tkmove3.rb の中にあります。テストプログラムは testarea.rb です。スクリプトは次のようになります。
ファイル名: testarea.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack testbed(c) area = TkdArea.new( c ) f = TkFrame.new.pack l = TkLabel.new(f, 'width'=>32).pack('side'=>'left') def area.bind( label ) @canvas.bind('1', proc{|x, y| create_item(x, y)}, "%x %y") @canvas.bind('B1-Motion', proc{|x, y| coord = adjust_item(x, y); label.text( coord.inspect )}, "%x %y") end area.bind( l ) TkButton.new(f, 'text'=>'Area', 'command'=>proc{ area.bind( l ) }).pack('side'=>'left') Tk.mainloop
できるだけシンプルなテストプログラムにしようと思いましたが、area オブジェクトに特異クラスを作ることで領域の情報を取り出せるように工夫してみました(ラベルに表示させています)。特異メソッドについては、「Ruby トレーニング」に例を挙げています。
tkmove3.rb に折れ線を描くためのクラスは TkcLines です。次のテストスクリプト testlines.rb で操作を確認してください。testlines.rb を起動した後キャンバスをクリックすると伸び縮みする線分が現れます、シングルクリックをする度に頂点が決定されていきます。ダブルクリックで折れ線の描画は終了します。
ファイル名: testlines.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack lines = TkdLines.new( c ) lines.bind testbed(c) Tk.mainloop
このプログラムを次のように変更すると折れ線をベジエ曲線で曲線化することもできます。変更は次のようになります。new_item 関数を特異メソッドの定義でオーバーライドしただけです。このような柔軟性が Ruby の魅力です。また、多角形の曲線化についての知識は何もなくても Tk のほうで受け持ってくれるので楽です。tkmove3.rb にはベジエ曲線を作成する TkdBezier クラスがあります。
ファイル名: testlines2.rb
require 'tkmove3.rb' include TestBed c = TkCanvas.new.pack lines = TkdLines.new( c ) def lines.new_item(x, y) TkcLine.new(@canvas, x, y, x, y, 'width'=>2, 'smooth'=>true) end lines.bind testbed(c) Tk.mainloop
アイテムの属性を操作するスクリプトを作成しました。config.rb はクラスライブラリーとして作ったので、テストにはテストスクリプト testconfg.rb が必要です。両方のファイルをダウンロードしたあと、ruby testconfig.rb で起動してください。itemconfig ボタンをクリックすると属性を操作するためのダイアログボックスが開きます。属性の outline は輪郭線の色、width は輪郭線の太さ、fill は内部を塗りつぶしている色、stipple は内部の網掛けで何も指定しないか、gray25 または、gray50 を指定します。ダイアログボックスの apply ボタンをクリックすると属性の内容がキャンバスのアイテムに反映されます。info ボタンをクリックするとそのアイテムの属性の情報が表示されます。dissmiss ボタンをクリックするとダイアログボックスが閉じます。
ファイル名: config.rb
ファイル名: testconfig.rb
config.rb は all.rb に適用することもできます。次の configall.rb をダウンロードしたあと、 ruby configall.rb で起動してください。それから、矩形 Rct か楕円 Ovl のボタンをクリックした後キャンバスをドラッグしてアイテムを作成してください。次に config ボタンをクリックした後アイテムをクリックすると属性ダイアログが開きます。属性の変更も可能です。
Rct をクリックした後すぐに config をクリックするとアイテムの表面にゴミが残ることがあります。いったん Mv ボタンを押しておいてから config ボタンをおすとゴミは残らないようです。バグの原因は分かりませんが、直す程のスクリプトではないので放置しています。
ファイル名: configall.rb
これらのスクリプトを作成するのに要した時間は 4, 5 日でした。操作感もきびきびしていて、Ruby の記述性の良さと、Tk のツールキットとしての性能の良さのおかげだと思います。Ruby/Tk の文書はまだまだ、少ないのですが、プログラムの操作法と、図形処理のアルゴリズムを丁寧に説明した文書が整備されればアマチュアがドローの機能を自分のプログラムに簡単に取り入れることも夢ではないような気がします。Ruby と Ruby/Tk があれば、アマチュアでもかなり満足できる作品を作ることができるようになるのではないかと期待しています。
config.rb はアイテムの属性をちょっと調べると言うのには大袈裟なので、簡易版の miniconf.rb を作ってみました。こちらの方が汎用性があります。やはりクラスライブラリーなので使い方のテストには、テスト用の testminiconf.rb が必要です。testminiconf.rb の内容は次のようになります。
require 'miniconf.rb' c = TkCanvas.new.pack conf = TkdConfigure.new( c ) item = TkcLine.new(c, 50, 50, 250, 150) TkButton.new(nil, 'text'=>'itemconfigure', 'command'=>proc{ conf.dialog( item ) }).pack Tk.mainloop
miniconf を使うには先ず require 'miniconf.rb' でファイルを読み込みます。次にc = TkCanvas.new.pack でキャンバスオブジェクトを変数 c に代入します。この c を引数にして TkdConfivgure クラスのオブジェクトを作成して変数 conf に代入します。最後にアイテムのオブジェクトを作成して変数に代入します(上の例では item )。準備ができたら、conf.dialog( item )でダイアログボックスを呼び出すことができます。ダイアログボックスの一番上のエントリーには属性のキーワードをいれ、二番目のえんとりーにはキーワードの属性の値をいれます。直線オブジェクトの arrowshape 属性のように三つの数のリストが必要な場合は三つの数を空白で区切って入力します。エントリーの入力後 apply ボタンをクリックすると属性の変更が適用されます。info ボタンをクリックするとそのアイテムの属性の一覧が表示されます。
アイテムの属性情報を取得するメソッドは itemconfiginfo です。書式は canvasobject.itemconfiginfo( targetobject ) で、戻り値は最初の項目が属性名、後の4項目がその値になったリストのリストです。アイテムの属性を変更するメソッドは itemconfigure で、書式は、canvasobject.itemconfigure( targetobject, 'key'=>value )です。
ファイル名: miniconf.rb
ファイル名: testminiconf.rb
アイテムの位置情報を操作するスクリプト coords2.rb を作成しました。これもクラスライブラリーですがテストプログラムを内蔵しているので irb から簡単に実行してみることができます。まず次のプログラムをダウンロードしてください。
ファイル名: coords2.rb
ファイルを手に入れたらさっそく irb から実行してみましょう。次の操作を実行してみてください。
$ irb irb(main):001:0> require 'coords2.rb' true irb(main):002:0> include CoordsTest Object irb(main):003:0> test
ウィンドウが現れたら coords ボタンをクリックすると画面の直線の位置情報が表示されます。表示をクリックすると数値を操作できます。それでは、表示窓の二行目に 150 30 と入力してみましょう。そこで apply ボタンをクリックすると新しい点と元の直線の右端を結んで線が引かれます。
coords2.rb はクラスライブラリーですから本来は他のスクリプトから require して利用します。そこで、次のテストスクリプトをダウンロードしてください。
ファイル名: testcoords.rb
require 'tkmove3.rb' include TestBed require 'coords2.rb' c = TkCanvas.new.pack testbed( c ) cod = Coords.new(c) TkButton.new(nil, 'text'=>'coords', 'command'=>proc{ c.bind('1', proc{ item = c.find_withtag('current').shift cod.dialog( item ) }) }).pack Tk.mainloop
コンソールから ruby testcoords.rb としてテストプログラムを起動したら、ウィンドウの Rct ボタンをクリックした後キャンバスに矩形を作成してください。次に coords をクリックして、さらにキャンバスの矩形をクリックすると矩形の位置情報が表示されます。数値を変更して apply をクリックすると矩形の形が変わります。このように、クラスライブラリーにテストプログラムを埋め込んでおくと使い方を忘れないので便利です。
cget はキャンバスウィジェットの属性情報を取得するメソッドです。
ファイル名: cget.rb
itembindinfo はアイテムのイベント処理情報を取得するメソッドです。書式は canvasobject.itembindinfo( 'tagmame' ) で戻り値はそのアイテムに関連づけられているイベントのリストです。サンプルスクリプト itembindinfo.rb を起動したら 先ず itembindinfo ボタンをクリックしてください。メッセージ領域に空のリストが表示されます。今度は Rct ボタンをクリックした後 itembindinfo ボタンをクリックしてください。'item' タグを持つアイテムに bind されたイベントのリストが表示されます。new bind をクリックすると新しい bind を定義できます。default のバインドが定義されているので、apply をクリックした後 dismiss をクリックしてダイアログを閉じてください。そこで itembindinfo をクリックすると新しいイベントが登録されているのが分かります。Rct か Ovl ボタンをクリックしてキャンバスに何かアイテムを作成してください。それから Mv ボタンを押した後アイテムをダブルクリックするとアイテムの色が変わります。
ファイル名: itembindinfo.rb
tkmove3.rb にアイテムをコピーするためのクラス Tkd クラスを追加しました。testmove3.rbで確認できます。Copy ボタンをクリックしたあと、アイテムをクリックするとコピーが作成できます。グループ化したアイテムもコピーできます。
アイテムの形状を変形させるためのコントロールをつくるクラス TkdControl クラスを作りました。サンプルプログラムでは四角いコントロールをドラッグすると直線アイテムの形状が変化します。TkdControl クラスは tkmove3.rb にも反映させました。testmove3.rb でテストするときは cntrl ボタンをクリックした後アイテムを左クリックするとコントロールが現れます。右クリックするとコントロールが消えます。
ファイル名: control.rb
require 'tk' class TkdControl def initialize( canvas ) @canvas = canvas @item = nil @coords = [] @x0, @y0 = 0, 0 end attr_writer :item def get_coords @coords = [] a = @item.coords while( a != []) x = a.shift y = a.shift @coords.push( [x, y] ) end @coords end def set_coords eval( "@item.coords(" + @coords.flatten.join(',') + ")" ) end def make_control @coords.each_index{|i| x, y = @coords[i][0], @coords[i][1] cont = TkcRectangle.new(@canvas, x-2, y-2, x+2, y+2, 'fill'=>'white') cont.addtag('control') cont.addtag( i ) } end def remove_control @canvas.delete('control') end def plotDown(x, y) @canvas.dtag 'selected' @canvas.addtag_withtag 'selected', 'current' @canvas.raise 'current' @x0, @y0 = x, y end def plotMove(x, y) @canvas.move 'selected', x-@x0, y-@y0 @x0, @y0 = x, y i = @canvas.find_withtag('selected').shift.gettags[1] @coords[i][0], @coords[i][1] = x, y set_coords end def bind @canvas.bind('1', proc{}) @canvas.bind('B1-Motion', proc{}) @canvas.itembind('control', '1', proc{|x,y| plotDown x,y }, "%x %y" ) @canvas.itembind('control', 'B1-Motion', proc{|x,y| plotMove x, y }, "%x %y") end def get_item( item ) @item = item get_coords make_control bind end def get_item_with_cursor item = @canvas.find_withtag('current').shift get_item( item ) end end c = TkCanvas.new.pack cont = TkdControl.new( c ) item = TkcLine.new(c, 50, 50, 100, 150, 150, 100, 'width'=>2) cont.get_item( item ) Tk.mainloop
ドロープログラムを作るためのツールキットとしての tkmove3.rb も大体完成したのでその応用として簡単なお絵書きプログラムを作りました。機能は貧弱ですが、自分の用途に合わせて中身を簡単に変更することができます。これで、Ruby も操作の容易なグラフィック機能を備えていることが分かりました。アマチュア待望の Basic の手軽さをもったグラフィックのできるプログラム言語の登場です。
ファイル名: tkdraw.rb
絵が自動的に動くようなアニメーションを作るためには、一定時間毎に割り込みをかけてくれる TkAfter クラスが便利です。TkAfter クラスのオブジェクトを作るには、TkAfter.new( 割り込み間隔(ミリ秒単位), 割り込み回数, proc{ 割り込みの時の処理 }) とします。TkAfter のメソッドにはタイマー割り込みを開始する start メソッドと停止させる stop メソッドなどがあります。次のサンプルスクリプトを起動すると、赤いまるが横に移動していきます。
ファイル名: tkafter.rb
require 'tkmove3.rb' c = TkCanvas.new.pack TkcOval.new(c, 30, 90, 60, 120, 'fill'=>'red').addtag('item') TkAfter.new( 30, 100, proc{ c.move('item', 1, 0) } ).start Tk.mainloop
このスクリプトにtkmove3.rbを利用すると面白いことができます。次のスクリプトを起動したら Mv ボタンをクリックした後、移動する赤い丸を動かすことができます。また、Rct ボタンや Ovl ボタンをクリックしてアイテムを作成するとそれが右に流れて行ってしまいます。
ファイル名: tkafter2.rb
それでは TkAfter クラスを利用して簡単なシミュレーションをしてみましょう。freefall.rbは物体の自然落下のシミュレーションです。また、freefall3.rbは弾道のシミュレーションです。
これで、Ruby/Tk の説明は終りです。ここまで書いて来たことだけでも色々なことに応用が効くとおもいます。Ruby/Tk で製品版のようなプログラムを作成するのはちょっと無理かも知れませんが、ちょっとしたアイディアを実現するためにかかる手間の少なさはたいへん魅力的です。ここに例示したプログラムを作成しながら、自分がプログラムをしていることすら忘れていた位です。まるで、プラモデルか何かを組み立てているような感じで作って行くことができました。Ruby は決して「易しい」プログラム言語とは思いませんが、少しなれると、アイディアを形にするのに自然に使うことができる道具であることに気づかされます。このページをみて Ruby をやってみようかしらんと思う人がでたらうれしいです。