スクリプトが動作してから、データを読み取り、それを元にしてウィジットを作成したい場合が多々ある。
これにはどうしたら良いのか、やり方を模索する。
TkLabel.new { text 'Hello World' pack('fill' => 'x') }
とする事でラベルが作成される。
これで、確かにラベルは表示されるんだけど……。
一体どうやってラベルを管理しているんだろう。
後からラベルのテキストを変更したりするには、どうしたら良いんだろうか?
別の方法を見つけた。 それはconfigureを使う方法。
l = TkLabel.new.pack l.configure('text', 'Hello World')
これならば、ウィジットを生成し、配列に保存しておけば良さそうだ。
必要がなくなったら、配列を削除して新たに作り直してしまえば動的に操作出来る。
require 'tk' $label_info = Array.new $cnt = 1 def label_make $label_info.clear for cnt in 0..$cnt do l = TkLabel.new.pack l.configure('text', "#{cnt}") $label_info.push(l) end $cnt = $cnt + 1 Tk.after 1000, proc{label_make} end label_make Tk.mainloop
簡単に解説。
$label_info は、ラベルを格納するためのArrayオブジェクト用の変数。これに作成したラベルオブジェクトを格納していく。
def label_makeは、ラベルを作成するための関数。タイマを使用して一定間隔ごとに呼び出されるようにする。
def label_makeの中身は、
・最初に配列をクリアする。
・タイマ処理で呼び出された回数分だけ、ラベルを作成する。
・作成したラベルの表示文字列を設定。
・作成したラベルオブジェクトを配列に格納する。
実際に動かしてみると、ラベルが順番にじゃなくて、どんどん増えていく。
ああ、当たり前だ。配列をクリアしたからって、作ったウィジットまでなくなってるわけじゃないんだから。
と言うことになると、作ったラベルオブジェクトをちゃんと破棄する必要がある。
それにはどうするか、destroyすれば良いことが分かった。
つまり、配列をクリアする前に、作ったラベルをdestroyしちゃえば良いと。
require 'tk' $label_info = Array.new $cnt = 1 def label_make $label_info.each {|label| label.destroy } $label_info.clear for cnt in 0..$cnt do l = TkLabel.new.pack l.configure('text', "#{cnt}") $label_info.push(l) end $cnt = $cnt + 1 Tk.after 1000, proc{label_make} end label_make Tk.mainloop