JRuby+swingでtextile風の表記法からレイアウトしてみる(実験)

swingのレイアウトをJRubyで書こうとすると結構手間です。
GUI設計を手書きで書くのは、Rubyスクリプト記述の手軽さがあると言えども、ベタ書きだとどうしても地味で冗長なコーディングになってしまいます。
なんというか、美しくないです。もやもやします。

どうにかこの手間を省きたいと考え、閃いたのがWikiの表記法からレイアウトできないか!ということです。
で、作ってみました。以下にサンプルを記載します。
(表記法をswingのコードに置き換えるコア部分は、拙いコードが恥ずかしく公開できず。。)

require 'java'
require 'my_layout_generator'

%w[
  JFrame JPanel JLabel JTextField JButton
  GroupLayout
].each {|c| eval c+"=javax.swing."+c}


frame = JFrame.new "Grouplayout Sample"
frame.default_close_operation = JFrame::EXIT_ON_CLOSE

label1 = JLabel.new "label_1"
label2 = JLabel.new "label_2"
label3 = JLabel.new "label_3"

field1 = JTextField.new "field_1", 10
field2 = JTextField.new "field_2", 10
field3 = JTextField.new "field_3", 10

button1 = JButton.new "button_1"
button2 = JButton.new "button_2"
button3 = JButton.new "button_3"

panel = JPanel.new

layout = GroupLayout.new panel
layout.auto_create_gaps = true
layout.auto_create_container_gaps = true
  
lgen = Zuku::MyLayoutGenerator.new
lgen.scan(<<EOS)
| label1 | field1 | button1 |
| label2 | field2 | button2 |
| label3 | field3 | button3 |
EOS
eval lgen.to_swing("layout")
#puts lgen.to_swing("layout")

panel.layout = layout
frame.content_pane = panel
frame.pack
frame.visible = true
  • 結果

いかがなものでしょう。
少しは美しく見えるんじゃないでしょうか。もやもやもちょっとすっきり。

to_swingを実行すると、以下の文字列を吐き出します。

layout.set_horizontal_group(
  layout.create_parallel_group
  .add_group(layout.create_sequential_group
    .add_group(layout.create_parallel_group
      .add_component(label1)
      .add_component(label2)
      .add_component(label3)
    )
    .add_group(layout.create_parallel_group
      .add_component(field1)
      .add_component(field2)
      .add_component(field3)
    )
    .add_group(layout.create_parallel_group
      .add_component(button1)
      .add_component(button2)
      .add_component(button3)
    )
  )
)
layout.set_vertical_group(
  layout.create_parallel_group
  .add_group(layout.create_sequential_group
    .add_group(layout.create_parallel_group
      .add_component(label1)
      .add_component(field1)
      .add_component(button1)
    )
    .add_group(layout.create_parallel_group
      .add_component(label2)
      .add_component(field2)
      .add_component(button2)
    )
    .add_group(layout.create_parallel_group
      .add_component(label3)
      .add_component(field3)
      .add_component(button3)
    )
  )
)

↑これをevalことで表記法からレイアウト実装を実現しています。

感想

今回はとりあえず、簡単なマトリックスに対応してみました。
表記法なので万能なレイアウトは望めないと思いますが表記法のお手軽感が実現できたのが感動です。

コーディング、以外に悩みました。
なんとかアイデア倒れにならずに済みました。
次はもう少し機能拡張できればと思います。