代码之家  ›  专栏  ›  技术社区  ›  trashgod

连接具有StringConverter的滑块和微调器

  •  3
  • trashgod  · 技术社区  · 7 年前

    对于数字输入,有时将模拟控件同步到文本显示很方便。在这个秋千上 example A JSpinner 和A JSlider 每一个都侦听更改事件,并且每一个都更新另一个的模型以进行匹配。类似的javafx程序,如下所示,连接 Spinner 和A Slider ,并且这些侦听器使控件保持协调:

    slider.valueProperty().addListener((Observable o) -> {
        spinner.getValueFactory().setValue(slider.getValue());
    });
    spinner.valueProperty().addListener((Observable o) -> {
        slider.setValue((double) spinner.getValue());
    });
    

    不幸的是,当我添加 StringConverter 到旋转器的 SpinnerValueFactory ,重新显式设置初始值时,初始值未格式化,直到其中一个控件更改为deven, 之后 添加转换器:

    spinner.getValueFactory().setConverter(…);
    spinner.getValueFactory().setValue(INITIAL_VALUE);
    

    我哪里做错了?

    image

    import java.text.NumberFormat;
    import javafx.application.Application;
    import javafx.beans.Observable;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.Slider;
    import javafx.scene.control.Spinner;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;
    import javafx.util.converter.PercentageStringConverter;
    
    /**
     * @see https://stackoverflow.com/a/6067986/230513
     */
    public class SpinSlider extends Application {
    
        private static final double MIN = 0;
        private static final double MAX = 1;
        private static final double INITIAL_VALUE = 0.5;
        private static final double STEP_INCREMENT = 0.1;
    
        @Override
        public void start(Stage primaryStage) {
            primaryStage.setTitle("SpinSlider");
            Slider slider = new Slider(MIN, MAX, INITIAL_VALUE);
            slider.setBlockIncrement(STEP_INCREMENT);
            Spinner spinner = new Spinner(MIN, MAX, INITIAL_VALUE, STEP_INCREMENT);
            spinner.getValueFactory().setConverter(
                new PercentageStringConverter(NumberFormat.getPercentInstance()));
            spinner.getValueFactory().setValue(INITIAL_VALUE);
            slider.valueProperty().addListener((Observable o) -> {
                spinner.getValueFactory().setValue(slider.getValue());
            });
            spinner.valueProperty().addListener((Observable o) -> {
                slider.setValue((double) spinner.getValue());
            });
            GridPane root = new GridPane();
            root.addRow(0, slider, spinner);
            root.setPadding(new Insets(8, 8, 8, 8));
            root.setHgap(8);
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    
    1 回复  |  直到 7 年前
        1
  •  6
  •   trashgod    7 年前

    你的 INITIAL_VALUE 首先用作 initialValue 微调器构造函数的参数。在内部,旋转器的混凝土 SpinnerValueFactory 是一个 DoubleSpinnerValueFactory 增加了 ChangeListener 对其 value 属性;当重新设置初始值时,该值实际上没有 改变 . 有两种方法:

    1. 为构造函数指定不同的值,并在添加转换器后设置所需的值:

      Spinner spinner = new Spinner(MIN, MAX, -42, STEP_INCREMENT);
      spinner.getValueFactory().setConverter(…);
      spinner.getValueFactory().setValue(INITIAL_VALUE);
      
    2. 构建一个 旋神经值工厂 使用所需的初始值并使用它构造微调器:

      SpinnerValueFactory factory = new SpinnerValueFactory
          .DoubleSpinnerValueFactory(MIN, MAX, INITIAL_VALUE, STEP_INCREMENT);
      factory.setConverter(…);
      Spinner spinner = new Spinner(factory);
      

    此外,下面的示例将两个侦听器替换为双向绑定,该绑定使用弱侦听器来允许对属性进行垃圾收集:

    slider.valueProperty().bindBidirectional(
        spinner.getValueFactory().valueProperty());
    

    简单地说,微调器和滑块可以相互控制。更常见的是,在控制由另一个模型持有的属性的过程中,每个模型都可以保持同步:

    model.xProperty().bindBidirectional(slider.valueProperty());
    model.xProperty().bindBidirectional(spinner.getValueFactory().valueProperty());
    

    image

    import java.text.NumberFormat;
    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.Slider;
    import javafx.scene.control.Spinner;
    import javafx.scene.control.SpinnerValueFactory;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;
    import javafx.util.converter.PercentageStringConverter;
    
    /**
     * @see https://stackoverflow.com/a/55427307/230513
     * @see https://stackoverflow.com/a/6067986/230513
     */
    public class SpinSlider extends Application {
    
        private static final double MIN = 0;
        private static final double MAX = 1;
        private static final double INITIAL_VALUE = 0.5;
        private static final double STEP_INCREMENT = 0.1;
    
        @Override
        public void start(Stage primaryStage) {
            primaryStage.setTitle("SpinSlider");
            Slider slider = new Slider(MIN, MAX, INITIAL_VALUE);
            slider.setBlockIncrement(STEP_INCREMENT);
            SpinnerValueFactory factory = new SpinnerValueFactory
                .DoubleSpinnerValueFactory(MIN, MAX, INITIAL_VALUE, STEP_INCREMENT);
            factory.setConverter(new PercentageStringConverter(
                NumberFormat.getPercentInstance()));
            Spinner spinner = new Spinner(factory);
            slider.valueProperty().bindBidirectional(spinner.getValueFactory().valueProperty());
            GridPane root = new GridPane();
            root.addRow(0, slider, spinner);
            root.setPadding(new Insets(8, 8, 8, 8));
            root.setHgap(8);
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }