连接具有StringConverter的Slider和Spinner [英] Connecting a Slider and Spinner that has a StringConverter

查看:44
本文介绍了连接具有StringConverter的Slider和Spinner的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于数字输入,将模拟控件同步到文本显示有时会很方便.在此Swing 示例中,一个JSpinnerJSlider分别监听更改事件,并分别更新对方的模型匹配.如下所示,一个类似的JavaFX程序将 Spinner Slider ,并且这些侦听器可以使控件保持协调一致:

For numeric input, it's sometimes convenient to synchronize an analog control to a text display. In this Swing example, a JSpinner and a JSlider each listen for change events, and each updates the other's model to match. A similar JavaFX program, shown below, connects a Spinner and a Slider, and these listeners keep the controls coordinated:

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

不幸的是,当我在微调器的SpinnerValueFactory中添加StringConverter时,初始值是未格式化的,直到更改了任何一个控件为止-即使在再次明确设置初始值的情况下,之后添加了转换器:

Unfortunately, when I added a StringConverter to the spinner's SpinnerValueFactory, the initial value was unformatted until either control was changed—even when setting the initial value explicitly again, after adding the converter:

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

我要去哪里错了?

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);
    }

}

推荐答案

您的INITIAL_VALUE首先用作微调器的构造函数的initialValue参数.在内部,微调器的具体 SpinnerValueFactory 是在其value属性中添加ChangeListenerDoubleSpinnerValueFactory;当再次设置初始值时,该值实际上并没有更改.有两种方法可以说明自己:

Your INITIAL_VALUE is first used as the initialValue parameter to the spinner's constructor. Internally, the spinner's concrete SpinnerValueFactory is a DoubleSpinnerValueFactory that adds a ChangeListener to its value property; when the initial value is set again, the value hasn't really changed. Two approaches suggest themselves:

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

  1. Specify a different value to the constructor and set the desired one after adding the converter:

Spinner spinner = new Spinner(MIN, MAX, -42, STEP_INCREMENT);
spinner.getValueFactory().setConverter(…);
spinner.getValueFactory().setValue(INITIAL_VALUE);

  • 构造具有所需初始值的SpinnerValueFactory并将其用于构造微调器:

  • Construct a SpinnerValueFactory with the desired initial value and use it to construct the spinner:

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

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

    In addition, the example below replaces the two listeners with a bidirectional binding, which uses weak listeners to allow garbage collection of properties:

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

    微调器和滑块可以相互控制.更常见的是,每个人在控制其他模型拥有的财产的过程中都可以保持同步:

    Trivially, the spinner and slider can control each other. More commonly, each can stay synchronized in the course of controlling a property held by another model:

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

    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);
        }
    
    }
    

    这篇关于连接具有StringConverter的Slider和Spinner的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆