1

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?

orbfish
  • 7,381
  • 14
  • 58
  • 75
  • I hate that good questions like this get closed--at least they are still around in some form. Anyway the main difference is the "adds". Without Swingbuilder you create an item then add it to a container, with swingbuilder you indicate that relationship by nesting levels. Also since everything is closure based it's easier to update the screen with the same code (something that can be a continual challenge in Swing). There are quite a few other advantages, enough to make it really annoying to go back to swing. – Bill K Oct 28 '14 at 16:34

2 Answers2

3

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
Seagull
  • 13,484
  • 2
  • 33
  • 45
  • I wasn't complaining - just looking for a good example. I can't see in this example that the Groovy version is more concise (same number of lines). I can see that it's more readable, if you know Groovy and especially SwingBuilder. But this doesn't look as revolutionary as, for example the XML builder examples I've seen. Thanks for providing both languages. – orbfish Dec 29 '13 at 20:16
  • @orbfish No,no! Soory, if I mislead you. There is two(now tree) __Groovy__ example, and no java. For second one I can add it simply, so I have done it. It's Groovy too, but I didn't use SwingBuilder. It's doing same as first one, in the same way. But it's more verbose, as you can see. And have an ugly inner Action class – Seagull Dec 30 '13 at 01:01
3

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.

jocki
  • 1,728
  • 16
  • 26