Bernhard's Weblog - Groovy SwingBuilder FormLayout
いちいちGroovy起動すんのにコマンドプロンプト開くのもアレだし,どうせならGUIでも作ろうかなぁと思ってみれば,Swingってよく知らないやという罠が。:-P
そんな自分のスキルを棚に上げ,今さらSwing(というかMetal L&F)ってのも味気ないし,どうせGroovyだし(?)なんて意味があるんだか無いんだかわからん理由をこねてJGoodiesに手を出してみた。
#実際,FormLayout使いやすいし。
そこで見つけたのが,このエントリのリンク先。まんまFormLayoutの使い方を載せてくれているのがありがたい。
この人,intの二次元配列で苦労していたようだけど,Groovy1.5で試してみたら,こんなコードですんなり動いたよ。
layout.columnGroups = [[1, 5], [3, 7]] as int[][];
EDTまわりは,そもそもSwingのEDT(Event Dispatch Thread)をよくわかってないんで,なんとも言えない。ただ,内部クラスや無名クラスが使えないかわりにクロージャ使うってのは分かった。
#今のSwingBuilderみると,.edt(Closure)とか.doLater(Closure)とかあるね。
#→Groovy 1.5の新機能
あと気になったのが,イベントリスナの張り方。これは,InfoQの記事にサンプルが書いてあった(これもまたクロージャ)。
「GroovyMarkupは,なんちゃってメソッドとクロージャのかたまりなんだ」って念仏唱えて挑まないと,GroovyMarkupのコードはギョっとするね。
def textlabel def frame = swing.frame(title:'Frame', size:[300,300]) { borderLayout() textlabel = label(text:"Clicked ${count} time(s).", constraints: BL.NORTH) button(text:'Click Me', actionPerformed: { count++ textlabel.text = "Clicked ${count} time(s)." }, constraints:BorderLayout.SOUTH) }
ちなみに,元のリンク先のちょこちょこ弄ったコードがこれ。
import groovy.swing.SwingBuilder import javax.swing.WindowConstants import javax.swing.JFrame import javax.swing.UIManager import com.jgoodies.forms.factories.Borders import com.jgoodies.forms.layout.CellConstraints import com.jgoodies.forms.layout.FormLayout import com.jgoodies.forms.factories.DefaultComponentFactory import com.jgoodies.looks.plastic.* class SampleMainSwing3 { JFrame frame def value1, value2 static void main( String[] args ) { // UIManager.lookAndFeel = UIManager.systemLookAndFeelClassName UIManager.lookAndFeel = Plastic3DLookAndFeel.class.name SampleMainSwing3 sms = new SampleMainSwing3() sms.frame.show() } public SampleMainSwing3() { initComponents() frame.pack() } private void initComponents() { FormLayout layout = new FormLayout( "right:pref, 3dlu, pref:grow, 7dlu, right:pref, 3dlu, pref:grow", // columns "p, 3dlu, p, 3dlu, p, 9dlu, p, 3dlu, p, 3dlu, p") // rows // Specify that columns 1 & 5 as well as 3 & 7 have equal widths. layout.columnGroups = [[1, 5], [3, 7]] as int[][] // Obtain a reusable constraints object to place components in the grid. final CellConstraints cc = new CellConstraints() // create instance of DefaultComponentFactory for creating separators final def dcf = DefaultComponentFactory.instance def swingB = new SwingBuilder() frame = swingB.frame(title: 'Groovy FormLayout Swing GUI', defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE) { panel(layout: layout, border: Borders.DIALOG_BORDER) { // widget(widget: dcf.createSeparator('General'), constraints: cc.xyw(1, 1, 7)) label("Company", constraints: cc.xy(1, 3)) textField("companyField",constraints: cc.xyw(3, 3, 5)) label("Contact", constraints: cc.xy (1, 5)) textField("contactField", constraints: cc.xyw(3, 5, 5)) widget(widget: dcf.createSeparator('Propeller'), constraints: cc.xyw(1, 7, 7)) label("value1", constraints: cc.xy (1, 9)) value1 = textField("value1",constraints: cc.xy(3, 9)) label("JButton ->", constraints: cc.xy(5, 9)) button("Button", constraints: cc.xy(7, 9), actionPerformed:{actionButton()}) label("value2", constraints: cc.xy(1, 11)) value2 = textField("value2",constraints: cc.xy(3, 11)) label("GButton ->",constraints: cc.xy(5, 11)) textField("diameterField",constraints: cc.xy(7, 11)) } } } void actionButton() { value2.text = value1.text.toUpperCase() } }