JavaFx:ObjectProperty <Integer>与ObjectProperty <Unit>的绑定

Gio*_*gio 4 binding combobox javafx-8

我有一个带NumberSpinner元素和ComboBox元素的场景,我想minValueNumberSpinner元素的valueProperty 绑定元素的属性ComboBox.一些代码:

@FXML
private NumberSpinner aNumberSpinner;
@FXML
private ComboBox<Unit> aComboBox;
Run Code Online (Sandbox Code Playgroud)

这里Unit是一个enum:

public enum Unit {

    mm,
    degree
}
Run Code Online (Sandbox Code Playgroud)

我想的是,当我选择degree UnitaComboBoxminValueProperty()aNumberSpinner成为10.我怎样才能实现它?

jew*_*sea 5

正如Kleopatra在评论中所建议的那样,最好是该单位知道自己的最低要求.

首选解决方案 - 无约束力

我对此的首选解决方案根本不使用绑定.

通过查询组合框中新选择的单位的最小值,组合框值上的侦听器可以轻松地将微调器对象的最小值直接设置为适当的值.

有时绑定可能有点太棘手......

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class UnitMinimums extends Application {
    private enum Unit {
        mm(0), degree(10);

        private final int minValue;

        private Unit(int minValue) {
            this.minValue = minValue;
        }

        public int getMinValue() {
            return minValue;
        }
    }

    private Slider slider = new Slider(0, 20, 0);

    private ComboBox<Unit> combo = new ComboBox<>(
            FXCollections.observableArrayList(
                    Unit.values()
            )
    );

    @Override
    public void start(Stage stage) throws Exception {
        combo.valueProperty().addListener((observable, oldValue, newValue) ->
                slider.setMin(newValue.getMinValue())
        );
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);

        VBox layout = new VBox(5, slider, combo);
        layout.setPadding(new Insets(10));
        VBox.setVgrow(combo, Priority.ALWAYS);
        combo.setMaxWidth(Double.MAX_VALUE);
        combo.getSelectionModel().select(0);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

纯粘合剂

如果您确实需要一个纯粹的绑定解决方案,您可以执行类似下面的操作,但如果您开始编写代码,它的缺点是在代码周围散布特定于单元最小值的信息(这是枚举所固有的)像这样很多.

使用Bindings.when:

Bindings.when(
        combo.valueProperty().isEqualTo(Unit.degree)
    ).then(10)
     .otherwise(0)
Run Code Online (Sandbox Code Playgroud)

可执行样本

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class BoundMinimums extends Application {
    private enum Unit { mm, degree }

    private Slider slider = new Slider(0, 20, 0);

    private ComboBox<Unit> combo = new ComboBox<>(
            FXCollections.observableArrayList(
                    Unit.values()
            )
    );

    @Override
    public void start(Stage stage) throws Exception {
        slider.minProperty().bind(
                Bindings.when(
                        combo.valueProperty().isEqualTo(Unit.degree)
                ).then(10)
                 .otherwise(0)
        );
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);

        VBox layout = new VBox(5, slider, combo);
        layout.setPadding(new Insets(10));
        VBox.setVgrow(combo, Priority.ALWAYS);
        combo.setMaxWidth(Double.MAX_VALUE);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

在数据类型转换上

这对我来说有点复杂和不明显(这是有时候更喜欢听众和直接设置者而不是绑定的另一个原因),但我认为你可以做类似下面的事情,它DoubleProperty slider.minProperty()转换为ObjectProperty<Integer>:

ObjectProperty<Integer> op = new SimpleObjectProperty<>(5);
op.bind(
    IntegerExpression.integerExpression(
        slider.minProperty()
    ).asObject()
);
Run Code Online (Sandbox Code Playgroud)

将它与单位转换结合在一起,您可以获得以下内容,甚至可以满足您的需求:

ObjectProperty<Integer> op = new SimpleObjectProperty<>(5);
op.bind(
    IntegerExpression.integerExpression(
        Bindings.when(
            combo.valueProperty().isEqualTo(Unit.degree)
        ).then(10)
         .otherwise(0)
    ).asObject()
);
Run Code Online (Sandbox Code Playgroud)