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());
});
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);
Where am I going wrong?
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);
}
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…