JRuby+swingでスレッドを実行
JRubyのThreadを使って並列実行させるプログラムを作ってみました。
正直正しく書けているか自信がありません。
ボタンを押すと、そのボタンが10秒間だけ無効となり、カウントダウンが終わると再び有効となります。2つのボタンは非同期で動作します。
サンプルコードです。
require 'java' %w( JFrame JPanel JButton ).each {|c| eval c+'=javax.swing.'+c} button1 = JButton.new "Run1" button1.add_action_listener do |event| button1.enabled = false Thread.start do 10.downto(1).each do |i| button1.text = "exec(#{i})" sleep(1) end button1.text = "Run1" button1.enabled = true end end button2 = JButton.new "Run2" button2.add_action_listener do |event| button2.enabled = false Thread.start do 10.downto(1).each do |i| button2.text = "exec(#{i})" sleep(1) end button2.text = "Run2" button2.enabled = true end end panel = JPanel.new panel.add button1 panel.add button2 frame = JFrame.new "sample" frame.default_close_operation = JFrame::EXIT_ON_CLOSE frame.content_pane.add panel frame.set_size 200,80 frame.location_relative_to = nil frame.visible = true
button1とbutton2の書き方が冗長ですけど、わかりやすいかなと思って分けました。
Thread.start do 〜 end
ここに重い処理を置けばプログラム全体はフリーズしなくて済みます。
逆にThreadを使わないとフリーズしてカウントダウンが終わるまで何もできなくなります。
感想
swingの非同期スレッドを調べてみると"invokeLater"やSwingWorker"という単語が引っ掛かるのですが、必要なのかいまいちわかりません。
Threadだけではダメなのでしょうか。
Javaのswingを触ってないのでよくわかっていません。(初心者ですみません)
ただ、ヒントとしては「Swingはスレッドセーフで作られていない」ということ、なんだと思います。
他のスレッドからbutton.textを呼ぶときとかが問題になる?のかなと。