Javafx 自定义 slider 值

标签 java javafx slider

我正在尝试使用 JavaFX slider 来选择一些时间点来可视化我的应用程序中的相关图形。 所以我应该在 slider 范围内放置一个 double 值列表,它们总是会改变,因为我从外部文件中获取它们。 例如:我有瞬间:0.0、1.9、2.5、50.1、98.7 等等。 我不想使用默认刻度,但我只想显示我真正拥有的值。 我还没有在网上找到任何东西。

最佳答案

我能想到的一个选项是让 slider 的实际值成为您想要的实际值的索引。使用格式化程序来显示实际值。在处理 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;


/**
 * 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();
    }

}

如果你需要很多这样的东西,你可以把它分解成一个单独的类(这不是生产质量,但会给你想法):

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 自定义 slider 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69827663/

相关文章:

java - Gson 反序列化 :Json Field Name Different from Java Object Field Name

java - StAX 从 Java NIO channel 解析

java - Hadoop 身份验证与 Kerberos 错误

javafx - 使用 FXML 在用户控件中创建并绑定(bind) DoubleProperty

javafx - 使用 slider 更改文本颜色

java - 如何设计美观的Web应用程序

javascript - JavaFX 容器内的 Java、JavaFx : Inserting a HTML&JS(static, 无互联网)项目

java - 如何使用 SceneBuilder 查看 fxml?

javascript - 如何让 slider 的拇指一直移动到最后?

javascript - 我自己的 JavaScript 库存在错误。看不到它在哪里