Javafx 自定义滑块值
Javafx custom slider values
我正在尝试使用 JavaFX 滑块来选择一些时间点来可视化我的应用程序中的相关图形。
所以我应该在滑块范围内放置一个双精度值列表,它们总是会改变,因为我从外部文件中获取它们。
例如:我有瞬间:0.0、1.9、2.5、50.1、98.7 等等。
我不想使用默认刻度,但我只想显示我真正拥有的值。
我在网上没有找到任何东西。
我能想到的一个选项是让滑块的实际值成为您想要的实际值的 index。使用格式化程序来显示实际值。处理时,您需要将滑块值(索引)转换为实际值。
这是一个简单的例子:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
double[] timepoints = {0.0, 1.9, 2.5, 50.1, 98.7};
Slider slider = new Slider();
slider.setMin(0);
slider.setMax(timepoints.length - 1);
slider.setSnapToTicks(true);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setLabelFormatter(new StringConverter<Double>() {
@Override
public String toString(Double object) {
int index = object.intValue();
return String.valueOf(timepoints[index]);
}
@Override
public Double fromString(String string) {
// Not used
return null;
}
});
Label label = new Label();
slider.valueProperty().addListener((obs, oldValue, newValue) -> {
label.setText(String.valueOf(timepoints[newValue.intValue()]));
});
VBox root = new VBox(10, label, slider);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
如果你需要很多这样的东西,你可以把它分解成一个单独的 class(这不是生产质量,但会给你想法):
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.Control;
import javafx.scene.control.Slider;
import javafx.util.StringConverter;
public class DiscreteSlider<T> {
private final ObservableList<T> values ;
private final ObjectProperty<T> discreteValue = new SimpleObjectProperty<>();
private final Slider slider ;
public DiscreteSlider(ObservableList<T> values) {
this.values = values ;
this.slider = new Slider() ;
slider.setMin(0);
slider.maxProperty().bind(Bindings.size(this.values).subtract(1));
slider.setShowTickLabels(true);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setSnapToTicks(true);
slider.labelFormatterProperty().bind(Bindings.createObjectBinding(() -> new StringConverter<Double>() {
@Override
public String toString(Double object) {
int index = object.intValue();
return DiscreteSlider.this.values.get(index).toString();
}
@Override
public Double fromString(String string) {
// Not used
return null;
}
}, this.values));
discreteValue.addListener((obs, oldValue, newValue) -> {
slider.setValue(this.values.indexOf(newValue));
});
slider.valueProperty().addListener((obs, oldValue, newValue) -> {
int index = newValue.intValue();
setDiscreteValue(values.get(index));
});
if (values.size() > 0) setDiscreteValue(values.get(0));
}
@SafeVarargs
public DiscreteSlider(T... values) {
this(FXCollections.observableArrayList(values));
}
public ObjectProperty<T> discreteValueProperty() {
return discreteValue ;
}
public final T getDiscreteValue() {
return discreteValueProperty().get();
}
public final void setDiscreteValue(T value) {
discreteValueProperty().set(value);
}
public Control asControl() {
return slider ;
}
}
然后
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class App extends Application {
@Override
public void start(Stage stage) {
Double[] timepoints = {0.0, 1.9, 2.5, 50.1, 98.7} ;
DiscreteSlider<Double> slider = new DiscreteSlider<>(timepoints);
Label label = new Label();
label.textProperty().bind(slider.discreteValueProperty().asString());
VBox root = new VBox(10, label, slider.asControl());
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
我正在尝试使用 JavaFX 滑块来选择一些时间点来可视化我的应用程序中的相关图形。 所以我应该在滑块范围内放置一个双精度值列表,它们总是会改变,因为我从外部文件中获取它们。 例如:我有瞬间:0.0、1.9、2.5、50.1、98.7 等等。 我不想使用默认刻度,但我只想显示我真正拥有的值。 我在网上没有找到任何东西。
我能想到的一个选项是让滑块的实际值成为您想要的实际值的 index。使用格式化程序来显示实际值。处理时,您需要将滑块值(索引)转换为实际值。
这是一个简单的例子:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
double[] timepoints = {0.0, 1.9, 2.5, 50.1, 98.7};
Slider slider = new Slider();
slider.setMin(0);
slider.setMax(timepoints.length - 1);
slider.setSnapToTicks(true);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setLabelFormatter(new StringConverter<Double>() {
@Override
public String toString(Double object) {
int index = object.intValue();
return String.valueOf(timepoints[index]);
}
@Override
public Double fromString(String string) {
// Not used
return null;
}
});
Label label = new Label();
slider.valueProperty().addListener((obs, oldValue, newValue) -> {
label.setText(String.valueOf(timepoints[newValue.intValue()]));
});
VBox root = new VBox(10, label, slider);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
如果你需要很多这样的东西,你可以把它分解成一个单独的 class(这不是生产质量,但会给你想法):
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.Control;
import javafx.scene.control.Slider;
import javafx.util.StringConverter;
public class DiscreteSlider<T> {
private final ObservableList<T> values ;
private final ObjectProperty<T> discreteValue = new SimpleObjectProperty<>();
private final Slider slider ;
public DiscreteSlider(ObservableList<T> values) {
this.values = values ;
this.slider = new Slider() ;
slider.setMin(0);
slider.maxProperty().bind(Bindings.size(this.values).subtract(1));
slider.setShowTickLabels(true);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setSnapToTicks(true);
slider.labelFormatterProperty().bind(Bindings.createObjectBinding(() -> new StringConverter<Double>() {
@Override
public String toString(Double object) {
int index = object.intValue();
return DiscreteSlider.this.values.get(index).toString();
}
@Override
public Double fromString(String string) {
// Not used
return null;
}
}, this.values));
discreteValue.addListener((obs, oldValue, newValue) -> {
slider.setValue(this.values.indexOf(newValue));
});
slider.valueProperty().addListener((obs, oldValue, newValue) -> {
int index = newValue.intValue();
setDiscreteValue(values.get(index));
});
if (values.size() > 0) setDiscreteValue(values.get(0));
}
@SafeVarargs
public DiscreteSlider(T... values) {
this(FXCollections.observableArrayList(values));
}
public ObjectProperty<T> discreteValueProperty() {
return discreteValue ;
}
public final T getDiscreteValue() {
return discreteValueProperty().get();
}
public final void setDiscreteValue(T value) {
discreteValueProperty().set(value);
}
public Control asControl() {
return slider ;
}
}
然后
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class App extends Application {
@Override
public void start(Stage stage) {
Double[] timepoints = {0.0, 1.9, 2.5, 50.1, 98.7} ;
DiscreteSlider<Double> slider = new DiscreteSlider<>(timepoints);
Label label = new Label();
label.textProperty().bind(slider.discreteValueProperty().asString());
VBox root = new VBox(10, label, slider.asControl());
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}