2

JavaFXでSliderのMinorおよびMajorTicksを変更することにより、事前に作成された Minor および Major Ticks を作成できます。しかし、ユーザーが自分で事前に構成された値を選択できるようにしたいのです。1 つの問題を解決するためにsnapToTicksがありますが、2, 4, 8, 16, 32

特定の目盛りのみを有効にしたり、他の目盛りを無効にしたりするにはどうすればよいですか?

おそらくvaluePropertyから必要な値のみをフィルター処理できますが、よりスマートなソリューションまたはネイティブで行う方法はありますか?


JavaFX 2.2 のバグにより、SliderClass でラベルをフォーマットすることができないため、JavaFX 8 を使用する必要があります。値はまだ計算されている可能性があり、正しく表示されません。

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

1 に答える 1

2

JavaFX 2.2: Hooking Slider Drag n Drop Eventsの以前のサンプル コードに基づく回答を次に示します。

スライダー値変更ロガー

サンプルは、 DoubleFunctionを引数として取るクラスでSliderを拡張します。スライダーlabelFormatterを使用してカスタム ティック ラベルを作成するアプリケーション。は、指定された目盛りで評価される関数の値を表すプロパティにも値を提供します。コードはJava 8を使用します。FunctionalSliderDoubleFunctionDoubleFunctionfunctionValue

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); }
}
于 2013-09-20T06:23:21.307 に答える