Groovy Bindable default value?
I would like to have a text field whose value always reflects that of a certain field in a given object. I thought Bindable might be the way to do this. However, using the following example:
#!/usr/bin/env groovy
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
import static javax.swing.JFrame.EXIT_ON_CLOSE
class TextModel {
@Bindable String text
}
def textModel = new TextModel()
def builder=new SwingBuilder()
builder.build {
frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
gridLayout cols: 1, rows: 2
textField id: 'textField'
bean textModel, text: bind{ textField.text }
label text: bind{ textModel.text }
}
}
textModel.text="AAAA"
modified from:
http://groovy.codehaus.org/Bindable+and+Vetoable+transformation
only the label text is set to that of textModel, but not that of the textField.
Any ideas???
Thank you Misha
p.s. I seem to be able to get the opposite behavior, where the TextField reflects that state of the variable, but its value is not updated, if I do:
#!/usr/bin/env groovy
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
import static javax.swing.JFrame.EXIT_ON_CLOSE
class TextModel {
@Bindable String text
}
def textModel = new TextModel()
def builder=new SwingBuilder()
builder.build {
frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
gridLayout cols: 1, rows: 2
textField id: 'textField',text:bind{ textModel.text }
label text: bind{ textModel.text }
}
}
textModel.text="AAAA"
p.p.s. If I add both:
#!/usr/bin/env groovy
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
import static javax.swing.JFrame.EXIT_ON_CLOSE
class TextModel {
@Bindable String text
}
def textModel = new TextModel()
def builder=new SwingBuilder()
builder.build {
frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
gridLayout cols: 1, rows: 2
textField id: 'textField',text:bind{ textModel.text }
bean textModel, text: bind{ textField.text } label text: bind{ textModel.text } } }
textModel.text="AAAA"
I get
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
p.p.p.s. This is my best solution:
#!/usr/bin/en开发者_JS百科v groovy
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
import static javax.swing.JFrame.EXIT_ON_CLOSE
class TextModel {
@Bindable String text
}
def textModel = new TextModel()
textModel.text="AAAA"
def builder=new SwingBuilder()
builder.build {
frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
gridLayout cols: 1, rows: 2
textField id: 'textField',text:textModel.text
bean textModel, text: bind{ textField.text } label text: bind{ textModel.text } } }
The Griffon guide on binding, describes the mutual
property as being what you want. Even though you're not using Griffon in this case, bind
seems to be a standard Groovy feature. If you create textField
like this:
textField id: 'textField', text: bind('text', source: textModel, mutual: true)
textField
will get its initial value from textModel.text
, write updates to it when the user types in the field, and display the updated value when changes to textModel.text
occur (from some background thread, say). When I tried to bind two text inputs like this, I started getting the IllegalStateExceptions you described, but it seems one input and multiple labels are fine.
精彩评论