JavaFX 2.2 手动配置 Slider 刻度 [英] JavaFX 2.2 configuring Slider ticks manually

查看:35
本文介绍了JavaFX 2.2 手动配置 Slider 刻度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们可以通过修改 一个 FunctionalSlider 类,它采用 DoubleFunction 作为参数.DoubleFunction 的应用程序使用滑块 labelFormatter.DoubleFunction 还为 functionValue 属性提供值,该属性表示在给定刻度线处评估的函数的值.该代码使用 Java 8.

import javafx.application.Application;导入 javafx.beans.property.*;导入javafx.geometry.*;导入javafx.scene.Scene;导入javafx.scene.control.*;导入javafx.scene.layout.*;导入javafx.stage.Stage;导入 javafx.util.StringConverter;导入 java.util.function.DoubleFunction;类 FunctionalSlider 扩展 Slider {私有 ReadOnlyDoubleWrapper functionValue = new ReadOnlyDoubleWrapper();公共FunctionalSlider(DoubleFunction函数){valueProperty().addListener(observable ->函数值.set(function.apply(getValue())));setLabelFormatter(new StringConverter<Double>() {@覆盖公共字符串 toString(双 x){返回字符串.格式("%1$.0f",函数.apply(x));}@覆盖public Double fromString(String s) {返回空值;}});}公共双 getFunctionValue() {返回函数值.get();}公共 ReadOnlyDoubleProperty functionValueProperty() {返回函数Value.getReadOnlyProperty();}}公共类 FunctionalSliderSample 扩展应用程序 {私有最终列表视图<字符串>startLog = new ListView<>();私有最终列表视图<字符串>endLog = new ListView<>();@Override public void start(Stage stage) 抛出异常 {窗格 logsPane = createLogsPane();滑块滑块 = createMonitoredSlider();VBox 布局 = 新 VBox(10);layout.setAlignment(Pos.CENTER);layout.setPadding(新插图(10));layout.getChildren().setAll(滑块,日志窗格);VBox.setVgrow(logsPane, Priority.ALWAYS);stage.setTitle("滑块值更改记录器");stage.setScene(新场景(布局));舞台.show();}私人滑块 createMonitoredSlider() {最终功能滑块滑块 = 新功能滑块(x ->数学.pow(2, x));滑块.setMin(0);滑块.setValue(1);滑块.setMax(5);滑块.setMajorTickUnit(1);滑块.setMinorTickCount(0);滑块.setShowTickMarks(true);滑块.setShowTickLabels(true);滑块.setSnapToTicks(true);slider.setMinHeight(Slider.USE_PREF_SIZE);slider.valueChangingProperty().addListener(observable -> {slider.setValue(Math.round(slider.getValue()));字符串值String = String.format("%1$.2f",滑块.getFunctionValue());if (slider.valueChangingProperty().get()) {startLog.getItems().add(值字符串);} 别的 {endLog.getItems().add(值字符串);}});返回滑块;}私人 HBox createLogsPane() {HBox 日志 = 新 HBox(10);logs.getChildren().addAll(createLabeledLog("开始", startLog),createLabeledLog("结束", endLog));返回日志;}公共窗格 createLabeledLog(String logName, ListView log) {标签标签 = 新标签(日志名称);标签.setLabelFor(log);VBox logPane = new VBox(5);logPane.getChildren().setAll(标签,日志);logPane.setAlignment(Pos.TOP_LEFT);返回日志窗格;}公共静态无效主要(字符串[]参数){启动(参数);}}

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

解决方案

Here is an answer based on earlier sample code from: JavaFX 2.2: Hooking Slider Drag n Drop Events.

The sample extends Slider with a FunctionalSlider class that takes a DoubleFunction as an argument. Applications of the DoubleFunction create custom tick labels using a slider labelFormatter. The DoubleFunction also supplies values to a functionValue property which represents the value of the function evaluated at a given tick mark. The code uses Java 8.

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.StringConverter;

import java.util.function.DoubleFunction;

class FunctionalSlider extends Slider {
  private ReadOnlyDoubleWrapper functionValue = new ReadOnlyDoubleWrapper();

  public FunctionalSlider(DoubleFunction<Double> function) {
    valueProperty().addListener(observable ->
        functionValue.set(
            function.apply(getValue())
        )
    );

    setLabelFormatter(new StringConverter<Double>() {
      @Override
      public String toString(Double x) {
        return String.format(
            "%1$.0f",
            function.apply(x)
        );
      }

      @Override
      public Double fromString(String s) {
        return null;
      }
    });
  }

  public double getFunctionValue() {
    return functionValue.get();
  }

  public ReadOnlyDoubleProperty functionValueProperty() {
    return functionValue.getReadOnlyProperty();
  }
}

public class FunctionalSliderSample extends Application {
    private final ListView<String> startLog = new ListView<>();
    private final ListView<String> endLog   = new ListView<>();

    @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(
            x -> Math.pow(2, x)
        );

        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(observable -> {
            slider.setValue(Math.round(slider.getValue()));

            String valueString = String.format(
                "%1$.2f", 
                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); }
}

这篇关于JavaFX 2.2 手动配置 Slider 刻度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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