Откат Swing DataBinding изменяется при нажатии кнопки отмены
У меня есть простой 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 ответ
Ничего из коробки, вы должны реализовать логику буферизации самостоятельно. Пример - в моем инкубаторе в разделе качелей, посмотрите на AlbumModel. В принципе
- боб Альбом
- AlbumModel - это оболочка (aka: buffer) вокруг bean-компонента с теми же свойствами, что и в оболочке: представление связано со свойствами этой оболочки.
- внутри он использует однократное чтение для свойств wrappee
- Кроме того, оболочка имеет свойство "буферизация", которое имеет значение 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;
}
}