Откат Swing DataBinding изменяется при нажатии кнопки отмены - PullRequest
3 голосов
/ 24 декабря 2011

У меня есть простой JFrame с несколькими jtextfields внутри, свойство text каждого jtextfield связано с полем объекта через привязку данных (я использовал конструктор окон для настройки привязки), когда пользователь изменяет что-то в JTextField, изменения автоматически отражаются в свойстве связанного объекта, мне нужно, чтобы при нажатии пользователем кнопки JButton (кнопка «Отмена») все сделанные пользователем изменения игнорировались.

Поэтому я хочу, чтобы, когда пользователь начал редактировать поле, как транзакция, была запущена, и в зависимости от действия пользователя (кнопка «ОК» или «Отмена») транзакция была зафиксирована или откатана.

Возможно ли это с платформой 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();
    }

1 Ответ

4 голосов
/ 24 декабря 2011

ничего из коробки, вы должны реализовать логику буферизации самостоятельно.Пример находится в моем разделе в инкубаторе swinglabs, посмотрите на AlbumModel.В основном

  • bean-компонент Album
  • AlbumModel - это оболочка (aka: buffer) вокруг bean-компонента с теми же свойствами, что и оболочка: представление привязано к свойствам этой оболочки
  • внутренне, он использует привязку однократного чтения к свойствам wrappee
  • Кроме того, оболочка имеет свойство "buffering", которое имеет значение true, если любое из его буферизованных свойств отличается от wrappee,В этом состоянии изменения могут быть либо зафиксированы, либо отменены

Ниже приведена выдержка из AlbumModel (почти все без проверки), которая может дать вам представление.Обратите внимание, что BindingGroupBean является слегка измененной BindingGroup, которая отображает внутреннее состояние в свойство bean-компонента «dirty», чтобы разрешить привязку «buffering».Вы можете найти его в инкубаторе, а также в полном приложении BAlbumBrowser (реализация классического примера Фаулера в терминах 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;
    }


}
...