07
22
[Ruby] ThreadからGUIに画像を表示する / 外部のThreadから指定されたタイミングでRuby/Tkに画像を表示する
2012.07.22(21:53)
GUIシステムは自分でイベントドリブンのしくみを持ち、自分がわかっているマウス操作やキー入力に対する再描画のしくみを実現することができる。しかし実行中はイベントドリブンを全力で実行しているため、自分が決めた好きなタイミングで再描画できるようにするには一工夫が必要だ。
外部のThreadから、自分が決めた好きなタイミングでRuby/Tkに画像を表示するサンプルを作ってみた。
TkCanvasの上に載っているTkcImageを再描画するのと、TkLabelのimageを再描画するのとやり方が違うので、同じ画像を2箇所に表示するサンプルとした。
ImageFrameクラスがRuby/Tkのイベントループを実現し、Tk.mainloopを実行すると全力でイベントループを実行し、他のことをやる余裕はなくなる。
そのため、ImageFrameクラスに外部から呼び出せる draw_imageメソッドを用意し、その中から、2箇所に対して再描画するために必要な処理を呼び出す。
一方、メインでは、sleepしながら、ImageFrameクラスに対して draw_imageを呼び出す。このようにすることで自分が決めたタイミングで、再描画させることができるようになる。
同様のことをJavaでやってみた。
Javaの場合
[Java] ThreadからGUIに画像を表示する / 外部のThreadから指定されたタイミングでJava Swing JFrameに画像を表示する
http://saltheads.blog134.fc2.com/blog-entry-74.html
外部のThreadから、自分が決めた好きなタイミングでRuby/Tkに画像を表示するサンプルを作ってみた。
# coding: windows-31j # Ruby1.9.3版 # image_frame.rb # Tk,拡張Tkが必要。 require "tk" require "tkextlib/tkimg/png" require "tkextlib/tkimg/jpeg" class ImageFrame def start $image = TkPhotoImage.new("file" => "empty.gif") $name = self.class.name TkRoot.new{ |r| r.title($name) TkCanvas.new { |c| width 600 height 200 bg 'gray' $tkc_image = TkcImage.new(c, width/2, height/2, "image" => $image) pack } $tk_label = TkLabel.new(r) { width 600 height 200 bg 'white' image $image pack } } Tk.mainloop end def draw_image(image_file) image = TkPhotoImage.new("file" => image_file) $tkc_image.configure("image" => image) $tk_label.image = image printf "draw_image #{image_file}\n" end end if __FILE__ == $0 image_frame = ImageFrame.new t1 = Thread.new(image_frame) { |image_frame| image_frame.start } 2.times { sleep 1 image_frame.draw_image("ruby.gif") sleep 1 image_frame.draw_image("ruby.png") sleep 1 image_frame.draw_image("ruby.jpg") sleep 1 } printf "close #{image_frame.class.name}\n" t1.join printf "fine\n" end
TkCanvasの上に載っているTkcImageを再描画するのと、TkLabelのimageを再描画するのとやり方が違うので、同じ画像を2箇所に表示するサンプルとした。
ImageFrameクラスがRuby/Tkのイベントループを実現し、Tk.mainloopを実行すると全力でイベントループを実行し、他のことをやる余裕はなくなる。
そのため、ImageFrameクラスに外部から呼び出せる draw_imageメソッドを用意し、その中から、2箇所に対して再描画するために必要な処理を呼び出す。
一方、メインでは、sleepしながら、ImageFrameクラスに対して draw_imageを呼び出す。このようにすることで自分が決めたタイミングで、再描画させることができるようになる。
同様のことをJavaでやってみた。
Javaの場合
[Java] ThreadからGUIに画像を表示する / 外部のThreadから指定されたタイミングでJava Swing JFrameに画像を表示する
http://saltheads.blog134.fc2.com/blog-entry-74.html