In what case is Groovy SwingBuilder superior?

1.2k views Asked by At

I know a little bit about Groovy:

  • Some of the ways syntax is more concise
  • How closures can be useful in replacing Java anonymous inner classes.
  • How builders can make tree construction easier

With all of this, I expected it to be apparent how Groovy SwingBuilder was miles above setting things up in Java. But the examples I've seen in book and web just don't look any more concise or readable than the Java version I would expect.

Could someone give a good example of Java vs. Groovy, real or contrived, where Groovy Swing shines?

2

There are 2 answers

2
Seagull On BEST ANSWER

It didn't shine. It simply saves you a lot of code. You can complain, but as I see, such table creation is better, than have a distinct model class, a lot of unnecessary lines, such as method declarations and annotations, and so on.

table = builder.table(constraints: BorderLayout.CENTER) {
  tableModel(list: data) {
    propertyColumn(header:'Name', propertyName: 'displayName', editable: false)
    closureColumn(header:'Value', read: IDENTITY,
    cellRenderer: cellRenderer, cellEditor: cellEditor,
    write: {row, newVal->});
} }

Besides simple table creation, and very powerful closureColumn, there is an easy readable simple example:

new SwingBuilder().frame(pack: true, show: true, defaultCloseOperation: JFrame.EXIT_ON_CLOSE) {
    panel(layout: new BorderLayout()) {
       label constraints: BorderLayout.PAGE_START, "Header"
       button constraints: BorderLayout.PAGE_END,
           action: action(name: "Footer", closure: { println "Footer pressed" }, accelerator: "Ctrl+K" )
       list listData: 1..10, BorderLayout.CENTER 
}   }

And now, please answer, how many lines of code will you write, to achieve such result?

EDIT: Added second example Groovy non-SwingBuilder code.

def panel = new JPanel(new BorderLayout())
panel.add(new JLabel("Header"), BorderLayout.PAGE_START)
panel.add(new JList(*(1..10)), BorderLayout.CENTER)

def button = new JButton(new AbstractAction("Footer") {
    {
        putValue(ACCELERATOR_KEY, "Ctrl+K");
    }
    @Override void actionPerformed(ActionEvent actionEvent) {
        println "Footer pressed"
    }
})
panel.add(button, BorderLayout.PAGE_END)

def frame = new JFrame()
frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
frame.contentPane = panel
frame.pack()
frame.visible = true
0
jocki On

SwingBuilder do offers implementation of beans binding in concise and readable than plain Swing. You can still use existing Swing layout or component in SwingBuilder. If there is something you need and SwingBuilder didn't provide it, you can always create a new reusable node for that feature.

For example, this is how I use SwingBuilder with MigLayout layout and several custom nodes in Griffon framework:

taskPane(id: "form", title: 'Date Entry', layout: new MigLayout('', '[right][left][left,grow]','')) {

    label('Invoice No:')
    textField(id: 'invoiceNo', columns: 15, text: bind('invoiceNo', target: model, mutual: true), errorPath: 'invoiceNo')
    errorLabel(path: 'invoiceNo', constraints: 'wrap')

    label('Date:')
    dateTimePicker(id: 'date', localDate: bind('date', target: model, mutual: true), errorPath: 'date', dateVisible: true, timeVisible: false)
    errorLabel(path: 'date', constraints: 'wrap')

    label('Customer:')
    comboBox(id: 'customer', model: model.customer, errorPath: 'customer')
    errorLabel(path: 'customer', constraints: 'wrap')

    label('Discount:', visible: bind {!model.isDiscAvailable})
    numberTextField(id: 'disc', columns: 20, bindTo: 'disc', visible: bind {!model.isDiscAvailable}, errorPath: 'disc')
    errorLabel(path: 'disc', visible: bind {!model.isDiscAvailable}, constraints: 'wrap')

}

I believe the code above is more concise than its pure Swing counterpart.