2011-12-24 80 views
3

我有一个简单的JFrame,里面有几个jtextfields,每个jtextfield的text属性通过数据绑定绑定到一个对象的字段(我使用窗口生成器来设置绑定),当用户更改JTextField上的某些内容,这些更改会自动反映到绑定的对象属性中,我有需要在用户按下JButton(取消按钮)时,用户所做的每个更改都将被丢弃。Swing DataBinding当取消按钮被按下时回滚改变

所以我想当用户开始编辑字段就像一个事务将被启动,并取决于用户的行为(确定或取消按钮)的事务正在提交或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(); 
    } 

回答

4

没有出关箱子,你必须自己实现缓冲逻辑。一个example is in my swinglabs incubator部分,看看AlbumModel。基本上

  • 豆是相册
  • AlbumModel是一个包装(又名:缓冲液)周围的豆与相同属性的缠绕:视图绑定到该包装物的性质
  • 内部,它另外,包装器具有“缓冲”属性,只要其缓冲属性的任何一个与wrappee不同,该属性就为真。在这种状态下,更改可以被提交或取消

下面是一个可以给你一个想法的AlbumModel(几乎所有的减号验证)的摘录。请注意,BindingGroupBean是稍微修改的BindingGroup,它将内部状态映射到bean属性“dirty”以允许绑定“缓冲”。你可以找到它在孵化器,以及一个完整的应用程序BAlbumBrowser(Fowler的经典的例子在BeansBinding方面实现)

/** 
* 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; 
    } 


} 
+0

这似乎是一个奇妙的解决方案,我在哪里可以找到BindingGroupBean源文件?是可用的么 ? – aleroot 2011-12-24 13:13:41

+0

@aleroot相同的地方,为确切的包看看进口:-) – kleopatra 2011-12-24 15:56:57