2011-12-24 79 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