我有一个简单的JFrame里面有几个jtextfields,每个jtextfield的text属性通过数据绑定绑定到一个对象的字段(我使用窗口构建器来设置绑定),当用户在JTextField上更改某些内容时,更改会自动反映出来对于绑定对象属性,我有需要当用户按下JButton(取消按钮)时,将丢弃用户完成的每个更改。
所以我希望当用户开始编辑字段时,将启动事务,并根据用户操作(确定或取消按钮),事务是Committed或RollBacked。
是否可以使用Swing Data Binding框架?怎么样 ?
这里初始化数据绑定的代码:
/**
* Data bindings initialization
*/
protected void initDataBindings() {
//Title field
BeanProperty<Script, String> scriptBeanProperty = BeanProperty.create("description");
BeanProperty<JTextField, String> jTextFieldBeanProperty = BeanProperty.create("text");
AutoBinding<Script, String, JTextField, String> autoBinding = Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, script, scriptBeanProperty, textFieldName, jTextFieldBeanProperty, "ScriptTitleBinding");
autoBinding.bind();
//Id field
BeanProperty<Script, Long> scriptBeanProperty_1 = BeanProperty.create("id");
BeanProperty<JLabel, String> jLabelBeanProperty = BeanProperty.create("text");
AutoBinding<Script, Long, JLabel, String> autoBinding_1 = Bindings.createAutoBinding(UpdateStrategy.READ, script, scriptBeanProperty_1, labelScriptNo, jLabelBeanProperty, "ScriptIdBinding");
autoBinding_1.bind();
}
没有任何开箱即用,你必须自己实现缓冲逻辑。一个example is in my swinglabs incubator部分,看看AlbumModel。基本上
下面是AlbumModel的摘录(几乎所有减去验证),可能会给你一个想法。请注意,BindingGroupBean是一个稍微修改过的BindingGroup,它将内部状态映射到bean属性“dirty”以允许绑定“缓冲”。您可以在孵化器中找到它以及完整的应用程序BAlbumBrowser(在BeansBinding方面实现Fowler的经典示例)
/**
* Buffered presentation model of Album.
*
*/
@SuppressWarnings("rawtypes")
public class AlbumModel extends Album {
@SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(AlbumModel.class
.getName());
private Album wrappee;
private BindingGroupBean context;
private boolean buffering;
public AlbumModel() {
super();
initBinding();
}
@Action (enabledProperty = "buffering")
public void apply() {
if ((wrappee == null))
return;
context.saveAndNotify();
}
@Action (enabledProperty = "buffering")
public void discard() {
if (wrappee == null) return;
context.unbind();
context.bind();
}
private void initBinding() {
initPropertyBindings();
initBufferingControl();
}
private void initBufferingControl() {
BindingGroup bufferingContext = new BindingGroup();
// needs change-on-type in main binding to be effective
bufferingContext.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ,
context, BeanProperty.create("dirty"),
this, BeanProperty.create("buffering")));
bufferingContext.bind();
}
/**
* Buffer wrappee's properties to this.
*/
private void initPropertyBindings() {
context = new BindingGroupBean(true);
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_ONCE,
wrappee, BeanProperty.create("artist"),
this, BeanProperty.create("artist")));
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_ONCE,
wrappee, BeanProperty.create("title"),
this, BeanProperty.create("title")));
// binding ... hmm .. was some problem with context cleanup
// still a problem in revised binding? Yes - because
// it has the side-effect of changing the composer property
// need to bind th composer later
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_ONCE,
wrappee, BeanProperty.create("classical"),
this, BeanProperty.create("classical")));
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_ONCE,
wrappee, BeanProperty.create("composer"),
this, BeanProperty.create("composer")));
context.bind();
}
public void setAlbum(Album wrappee) {
Object old = getAlbum();
boolean oldEditEnabled = isEditEnabled();
this.wrappee = wrappee;
context.setSourceObject(wrappee);
firePropertyChange("album", old, getAlbum());
firePropertyChange("editEnabled", oldEditEnabled, isEditEnabled());
}
public boolean isEditEnabled() {
return (wrappee != null); // && (wrappee != nullWrappee);
}
public boolean isComposerEnabled() {
return isClassical();
}
/**
* Overridden to fire a composerEnabled for the sake of the view.
*/
@Override
public void setClassical(boolean classical) {
boolean old = isComposerEnabled();
super.setClassical(classical);
firePropertyChange("composerEnabled", old, isComposerEnabled());
}
public boolean isBuffering() {
return buffering;
}
public void setBuffering(boolean buffering) {
boolean old = isBuffering();
this.buffering = buffering;
firePropertyChange("buffering", old, isBuffering());
}
/**
* Public as an implementation artefact - binding cannot handle
* write-only properrties? fixed in post-0.61
* @return
*/
public Album getAlbum() {
return wrappee;
}
}