We can create pre-created Minor and Major Ticks by modifying the Minor and MajorTicks of the Slider in JavaFX. But I want to enable the user only to select pre-configured values by me like 2, 4, 8, 16, 32
. We have snapToTicks to solve one problem, but
How do I enable only specific tick marks or disable the others?
I could probably filter only the wanted values out from valueProperty but is there either a smarter solution or a way to do it natively?
Due to a bug in JavaFX 2.2 it is not possible to format the labels in the SliderClass, thus you need to use JavaFX 8. The values are still calculated probably and just displayed wrongly.
I add a modified version for JavaFX 2.2
FunctionalSlider.java
public class FunctionalSlider extends Slider { private ReadOnlyDoubleWrapper functionValue = new ReadOnlyDoubleWrapper();
public FunctionalSlider() {
this.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
functionValue.set(Math.pow(2, getValue()));
}
});
this.setLabelFormatter(new StringConverter<Double>() {
@Override
public Double fromString(String string) {
return 0.0;
}
@Override
public String toString(Double object) {
return String.format("%1$.0f", Math.pow(2, object));
}
});
}
public double getFunctionValue() {
return functionValue.get();
}
public ReadOnlyDoubleProperty functionValueProperty() {
return functionValue.getReadOnlyProperty();
}
}
FunctionalSliderSample
public class FunctionalSliderSample extends Application {
private final ListView<String> startLog = new ListView<String>();
private final ListView<String> endLog = new ListView<String>();
@Override public void start(Stage stage) throws Exception {
Pane logsPane = createLogsPane();
Slider slider = createMonitoredSlider();
VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.setPadding(new Insets(10));
layout.getChildren().setAll(
slider,
logsPane
);
VBox.setVgrow(logsPane, Priority.ALWAYS);
stage.setTitle("Slider Value Change Logger");
stage.setScene(new Scene(layout));
stage.show();
}
private Slider createMonitoredSlider() {
final FunctionalSlider slider = new FunctionalSlider();
slider.setMin(0);
slider.setValue(1);
slider.setMax(5);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setSnapToTicks(true);
slider.setMinHeight(Slider.USE_PREF_SIZE);
slider.valueChangingProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
slider.setValue(Math.round(slider.getValue()));
String valueString = String.format("%1$.0f", slider.getFunctionValue());
if (slider.valueChangingProperty().get()) {
startLog.getItems().add(valueString);
}
else {
endLog.getItems().add(valueString);
}
}
});
return slider;
}
private HBox createLogsPane() {
HBox logs = new HBox(10);
logs.getChildren().addAll(
createLabeledLog("Start", startLog),
createLabeledLog("End", endLog)
);
return logs;
}
public Pane createLabeledLog(String logName, ListView<String> log) {
Label label = new Label(logName);
label.setLabelFor(log);
VBox logPane = new VBox(5);
logPane.getChildren().setAll(
label,
log
);
logPane.setAlignment(Pos.TOP_LEFT);
return logPane;
}
public static void main(String[] args) { launch(args); }
}