Pull to refresh

Двунаправленный bind (bind with inverse) между JavaFX переменной и Java-переменной

Reading time 3 min
Views 1.2K
На этот раз хотелось бы расширить предыдущую статью про bind небольшим дополнением про двунаправленный bind (bind with inverse).

В отличие от обычного связывания переменной, bind with inverse позволяет не только связать одну переменную с другой, но и создать двунаправленное соотношеие между переменными.



Как и в предыдущем посте про bind начну с простого примера, который показывает, а что же такое bind with inverse на практике.

Расмотрим простой пример:
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.control.Slider;


var myVar : Number = 5;

Stage {
    title: "Bind"
    scene: Scene {
        width: 250
        height: 80
        content: [
            VBox {
                translateX: 10
                translateY: 10
                spacing: 5
                content: [
                    Slider {
                        max: 10
                        value: bind myVar with inverse
                    }
                    Slider {
                        max: 10
                        value: bind myVar with inverse
                    }
                ]
            }
        ]
    }
}


В самом начале мы определили переменную myVar, вокруг которой и будем «плясать». Зададим ей некое начальное значение (5).
В сцене создадим два компонента Slider и свяжем значения этим слайдеров с переменной myVar с помощью bind. Но не просто bind, а добавим выражение «with inverse».
Если мы запустим это приложение, то увидим окно с двумя ползунками. Стоит потянуть за один ползунок, как второй потянется тоже.
sliders
Это происходит за счёт двунаправленного связывания. Если мы тянем за ползунок, то изменяем значение его поля value, а за счёт inverse bind изменяется и значение переменной myVar. Со значением этой переменной также связано значение поля value второго ползунка, поэтому оно также будет обновлено после обновления myVar. Если потянуть за другой ползунок, то ситуация повторится.

После того, как суть двунаправленного связвыания переменных более меннее прояснена, перейдём к теме поста, а именно, попробуем создать двунаправленную связь JavaFX переменной с Java-переменной.

Воспользуемся кодом из предыдущего поста про bind, только усложним задачу.

Для начала снова создадим интерфейс слушателя (Listener.java):
public interface Listener {
        void notifyChanged( int newValue );
}


После чего опишем тот Java-код (беру без изменений из предыдущего поста), с которым будем осуществлять связь (JavaPart.java):

public class JavaPart {
        private int observerableValue;

        public void setObserverableValue(int newValue) {
                observerableValue = newValue;

                Listener l = listener;
                if(l != null)
                        l.notifyChanged(newValue);

        }

        public int getObserverableValue() {
                return observerableValue;
        }

        private Listener listener;

        public void setListener(Listener l) {
                listener = l;
        }

}


Далее опишем адептер, который и позволит нам сделать столь нужное нам связывание (JavaPartAdapter.fx):
public class JavaPartAdapter extends Listener {

        public-init var javaPart : JavaPart;

        init {
                javaPart.setListener(this);
        }

        public var currentValue : Integer on replace oldValue {
                if( currentValue != oldValue ) {
                        javaPart.setObserverableValue( currentValue );
                }
        }

        public override function notifyChanged( newValue : Integer ) : Void {
                currentValue = newValue;
        }

}


Здесь пришлось внести кое какое дополнение для того чтобы позволить делать двунаправленные связи, а именно, используется триггер на изменение значения переменной currentValue. Как только происходит обновление переменной, то вызывается метод, который обновляет значение переменной в объекте, описанном на Java.

Ну и последнее, JavaFX-код второй половинки, который использует наш адаптер чтобы связать свою переменную с переменной из класса JavaPart
Main.fx:
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.Group;

var myVar : Integer = 5;
def adapter : JavaPartAdapter = JavaPartAdapter {
        javaPart: new JavaPart()
        currentValue: bind myVar with inverse
};

Stage {
    width: 200
    height: 300
    scene: Scene {
        content: [
            Button {
                text: bind "Change {myVar}"
                action: function() {
                        adapter.javaPart.setObserverableValue(77);
                }
            }
            Button {
                translateY: 25
                text: bind "Change {adapter.currentValue}"
                action: function() {
                    myVar = 999;
                } 
            }
        ]
    }
}


Здесь мы определяем переменную myVar, после чего делаем двунаправленную связь между myVar и переменной currentValue адаптера.

Далее определяем две кнопки. Первая кнопка изменяет значение переменной Java-класса. Вторая же пытается изменить myVar.

Скомпилируем и запустим:
start first second

В первый момент времени значение myVar равно 5. Если нажать на первую кнопку, то это приведёт к тому, что будет вызыван метод set из Java-кода, который вызовет слушателя, который в свою очередь обновит значение currentValue, после чего, за счёт bind значение myVar также будет обновлено.
Если нажать на вторую кнопку, то изменится значение myVar. За счёт inverse bind будет изменено значение currentValue, после чего сработает триггер на эту переменную, который в свою очередь вызовет метод set Java-класс, так что значение переменной в Java-классе также будет обновлено.

Таким образом, получена двунаправленная связь между JavaFX переменной (myVar) и Java-переменной (JavaPart.observerableValue).

Надеюсь что это небольшое описание может быть полезно тем, что пишет сложную логику на Java, а JavaFX использует только для UI.

Удачных экспериментов и только хороший открытий!
Tags:
Hubs:
+4
Comments 0
Comments Leave a comment

Articles