Mixing Swing/FX with binding - use custom property for mediating between threads?

前端 未结 1 1408
失恋的感觉
失恋的感觉 2021-01-19 07:43

This is a kind of follow-up of seeing thread-rule violations when mixing Swing/FX and bind both parts to the same model.

Meanwhile I experimented a bit: use a custo

相关标签:
1条回答
  • 2021-01-19 08:18

    A partial answer (why the misbehaviour of the bidi-bound textfield and what to do against it):

    Techically, the behaviour is due to internal flags which get confused when the "back-notification" of a bidi-bound property happens outside of the expected code blocks.

    • BidirectionalBinding guards - being the listener to two properties - itself against endless looping by isUpdating to not update the originating property again
    • the flag doNotAdjustCaret is used by TextInputControl to mark changes triggered by itself. The control has a custom TextProperty which uses that flag to either set the selection to the start (for external changes) or not (for internal changes)

    Now the thread-changing property falls outside the first block, triggers a re-set of the textProperty which in turn isn't recognized as self-triggered, thus resetting the selectin/caret. A work-around is to update the value and "back-fire" directly:

    /**
     * Implemented to set the value of this property, immediately 
     * fire a value change if needed and then update the delegate.
     * 
     * The sequence may be crucial if the value is changed by a bidirectionally
     * bound property (like f.i. a TextProperty): that property reacts to 
     * change notifications triggered by its own change in a different 
     * way as by those from the outside, detected by a flag (sigh ...)
     * set while firing.
     */
    @Override
    public void set(T value) {
        T oldValue = this.value;
        this.value = value;
        if (!areEqual(oldValue, value)) {
            fireValueChangedEvent();
        }
        updateToDelegate(value);
        // PENDING: think about uni-directional binding
    }
    
    /**
     * Updates the internal value and notifies its listeners, if needed.
     * Does nothing if the newValue equals the current value.<p>
     * 
     * It runs on the thread it is called from.
     * 
     * @param newValue the new value.
     */
    protected void doUpdateFromDelegate(T newValue) {
        if (areEqual(newValue, value)) return;
        value = newValue;
        fireValueChangedEvent();
    }
    
    0 讨论(0)
提交回复
热议问题