按下取消按钮时,Swing DataBinding Rollback会更改

问题描述 投票:3回答:1

我有一个简单的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();
    }
java swing windowbuilder beans-binding
1个回答
4
投票

没有任何开箱即用,你必须自己实现缓冲逻辑。一个example is in my swinglabs incubator部分,看看AlbumModel。基本上

  • 豆是专辑
  • AlbumModel是bean周围的包装器(aka:buffer),具有与包装相同的属性:视图绑定到此包装器的属性
  • 在内部,它使用对wrappee属性的read-once绑定
  • 此外,包装器具有“缓冲”属性,一旦其任何缓冲属性与包装不同,该属性就成立。在此状态下,可以提交或取消更改

下面是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;
    }


}
© www.soinside.com 2019 - 2024. All rights reserved.