JRubyのSwingサンプル swing2.rb

今までJRubyの中身自体について、ほとんど見てこなかったので、昨日のエントリで最後に動作確認として実行した、swing2.rbについて少し見てみます。シンプルですが、いくつかのJRubyの基本が学べるので、現時点ではちょうどいい教材です。

# Import Java packages
include Java

import javax.swing.JFrame

frame = JFrame.new("Hello Swing")
button = javax.swing.JButton.new("Klick Me!")

class ClickAction
  include java.awt.event.ActionListener
  def actionPerformed(evt)
    javax.swing.JOptionPane.showMessageDialog(nil, <<EOS)
<html>Hello from <b><u>JRuby</u></b>.<br>
Button '#{evt.getActionCommand()}' clicked.
EOS
  end
end
button.add_action_listener(ClickAction.new)

# Add the button to the frame
frame.get_content_pane.add(button)

# Show frame
frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
frame.pack
frame.visible = true

さて、では最初の要素から順番に見ていきましょう。

# Import Java packages
include Java

まず、JRubyを使うときは、Javaパッケージをincludeします。

import javax.swing.JFrame

Javaのパッケージは、Java言語と同様にimportで行います。(ただ、Ruby文法的には少し違和感がありますね。シンタックス・シュガーとなっているようです。jirbで調べられそうです。)

frame = JFrame.new("Hello Swing")
button = javax.swing.JButton.new("Klick Me!")

Javaオブジェクトを生成し、Rubyの変数として代入しています。

class ClickAction
  include java.awt.event.ActionListener
  def actionPerformed(evt)
    javax.swing.JOptionPane.showMessageDialog(nil, <<EOS)
<html>Hello from <b><u>JRuby</u></b>.<br>
Button '#{evt.getActionCommand()}' clicked.
EOS
  end
end
button.add_action_listener(ClickAction.new)

Javaで言うところの内部クラスですね。JRubyでは、Javaのインターフェースを宣言するときに、Rubyのincludeを利用します。これは、Javaが多重継承を許可しないため、言語間の差異を調整するものだと思います。

showMessageDialogメソッドは、Javaのものですが、メッセージ部分にヒアドキュメントと埋め込み評価式が使われているのがRubyっぽいですね。Javaに慣れている自分から見ると、不思議な感じがします。

# Add the button to the frame
frame.get_content_pane.add(button)

# Show frame
frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
frame.pack
frame.visible = true

あとは、Swingでお決まりの流れになっています。set_default_close_operationの引数にJFrameの定数を取っていますが、Rubyの文法に従いダブルコロンで表現されています。

このサンプルでは、JRubyのメリットが感じられるのはヒアドキュメントの部分くらいですが、このサンプルの最大の意味は「Javaとこれだけ親和性があるよ」ということが簡単に理解できる、というところでしょう。基本的に、JavaでできることをJRubyでやっても、あまり意味はないですから。
それよりも、おそらくJavaアプリケーションでも複雑なものを構築していくと、どうしてもメタプログラミング的なことをやらないといけなくなりますが、そのような場合までいって初めて、JRubyRuby部分の柔軟性がメリットとして見えてくると思います。