滑块bindBidirectional

时间:2016-10-12 12:05:43

标签: javafx bind

您好我遇到了为2个滑块使用双向绑定的情况valueProperty

任务是:有2个滑块,每个滑块的最大值为100 但是这个值在这两个滑块之间分配,例如,如果将第一个滑块移动到值20,则第二个滑块值必须为80,反之亦然。

我知道这应该使用bind双向绑定,但是如何将表达式绑定到属性?

slider1.valueProperty().bindBidirectional(slider2.getMax() - slider2.valueProperty());  ???

任何帮助都会受到高度关注。

1 个答案:

答案 0 :(得分:2)

你不能用双向绑定做到这一点:你需要使用两个监听器:

slider1.valueProperty().addListener((obs, oldValue, newValue) -> 
    slider2.setValue(slider2.getMax() - newValue.doubleValue()));

slider2.valueProperty().addListener((obs, oldValue, newValue) -> 
    slider1.setValue(slider1.getMax() - newValue.doubleValue()));

SSCCE:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ConverselyBoundSliders extends Application {

    @Override
    public void start(Stage primaryStage) {
        Slider slider1 = new Slider(0, 100, 50);
        Slider slider2 = new Slider(0, 100, 50);

        slider1.valueProperty().addListener((obs, oldValue, newValue) -> 
            slider2.setValue(slider2.getMax() - newValue.doubleValue()));

        slider2.valueProperty().addListener((obs, oldValue, newValue) -> 
            slider1.setValue(slider1.getMax() - newValue.doubleValue()));

        VBox root = new VBox(5, slider1, slider2);
        root.setPadding(new Insets(12));

        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这似乎工作正常,没有任何无限递归发生;但是,由于它涉及浮点运算和比较,因此您可能希望确保slider.getMax() - newValue.doubleValue()计算中的舍入错误不会以每个侦听器调用另一个而不从递归中调用而结束。以下是一种防弹方式:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ConverselyBoundSliders extends Application {

    @Override
    public void start(Stage primaryStage) {
        Slider slider1 = new Slider(0, 100, 50);
        Slider slider2 = new Slider(0, 100, 50);

        new ConverseSliderBinding(slider1, slider2);

        VBox root = new VBox(5, slider1, slider2);
        root.setPadding(new Insets(12));

        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private static class ConverseSliderBinding {
        private ChangeListener<Number> listener1 ;
        private ChangeListener<Number> listener2 ;

        private final Slider slider1 ;
        private final Slider slider2 ;

        private boolean adjusting ;

        public ConverseSliderBinding(Slider slider1, Slider slider2) {
            this.slider1 = slider1 ;
            this.slider2 = slider2 ;

            listener1 = (obs, oldValue, newValue) -> {
                if (adjusting) return ;
                adjusting = true ;
                slider2.setValue(slider2.getMax() - newValue.doubleValue());
                adjusting = false ;
            };

            listener2 = (obs, oldValue, newValue) -> {
                if (adjusting) return ;
                adjusting = true ;
                slider1.setValue(slider1.getMax() - newValue.doubleValue());
                adjusting = false ;
            };

            slider1.valueProperty().addListener(listener1);
            slider2.valueProperty().addListener(listener2);
        }

        public void dispose() {
            slider1.valueProperty().removeListener(listener1);
            slider2.valueProperty().removeListener(listener2);
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}