3

いくつかのjtextfieldが内部にある単純なJFrameがあり、各jtextfieldのtextプロパティは、データバインディング(ウィンドウビルダーを使用してバインディングを設定)を介してオブジェクトのフィールドにバインドされます。ユーザーがJTextFieldで何かを変更すると、変更が自動的に反映されます。バインドされたオブジェクトプロパティに対して、ユーザーがJButton(キャンセルボタン)を押すと、ユーザーが行ったすべての変更が破棄される必要があります。

したがって、ユーザーがトランザクションのようにフィールドの編集を開始すると、トランザクションが開始され、ユーザーのアクション([OK]または[キャンセル]ボタン)に応じて、トランザクションがコミットまたはロールバックされるようにします。

Swingデータバインディングフレームワークで可能ですか?どのように ?

ここにデータバインディングを初期化するコードがあります:

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

1 に答える 1

4

箱から出してすぐに使えるものは何もありません。バッファリングロジックを自分で実装する必要があります。例は私のswinglabsインキュベーターセクションにあります。AlbumModelを見てください。基本的に

  • 豆はアルバムです
  • AlbumModelは、ラップされたものと同じプロパティを持つBeanのラッパー(別名:バッファー)です。ビューはこのラッパーのプロパティにバインドされます
  • 内部的には、wrappeeプロパティへのread-onceバインディングを使用します
  • さらに、ラッパーには「buffering」プロパティがあります。これは、バッファリングされたプロパティのいずれかがwrappeeと異なる場合にtrueになります。この状態では、変更をコミットまたはキャンセルできます

以下は、あなたにアイデアを与えるかもしれないAlbumModel(ほぼすべてマイナス検証)の抜粋です。BindingGroupBeanは、内部状態をBeanプロパティ「dirty」にマップして「バッファリング」のバインドを可能にする、わずかに変更されたBindingGroupであることに注意してください。これは、インキュベーターと完全なアプリケーション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;
    }


}
于 2011-12-24T12:48:11.360 に答える