How to retrieve the final Slider value when snapToTicks==true?

做~自己de王妃 提交于 2019-12-06 09:33:00

I finally came up with the below solution, based on the proposal from @ItachiUchiha. Essentially, the solution uses both, a valueProperty and a valueChangingProperty listener, and uses some flags to track the current state. At the end, the perform() method is called exactly once when the slider movement is done and the final value is available. This works when the slider is moved either with the mouse or through the keyboard.

A reusable class implemented as subclass of Slider is available at https://github.com/afester/FranzXaver/blob/master/FranzXaver/src/main/java/afester/javafx/components/SnapSlider.java.

package com.example.javafx;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.stage.Stage;

public class SliderExample extends Application {

    public static void main(String[] args) { launch(args); }

    private boolean isFinal = true;     // assumption: no dragging - clicked value is the final one.
                                        // variable changes to "false" once dragging starts.

    private Double finalValue = null;

    @Override
    public void start(Stage primaryStage) {
        final Slider slider = new Slider(0.25, 2.0, 1.0);
        slider.setShowTickLabels(true);
        slider.setShowTickMarks(true);
        slider.setMajorTickUnit(0.25);
        slider.setMinorTickCount(0);
        slider.setSnapToTicks(true);

        slider.valueProperty().addListener(new ChangeListener<Number>() {

            final double minCompare = slider.getMin() + Math.ulp(slider.getMin());
            final double maxCompare = slider.getMax() - Math.ulp(slider.getMax());

            @Override
            public void changed(ObservableValue<? extends Number> observable,
                    Number oldValue, Number newValue) {

                if (isFinal) {  // either dragging of knob has stopped or
                                // no dragging was done at all (direct click or 
                                // keyboard navigation)
                    perform((Double) newValue);
                    finalValue = null;
                } else {        // dragging in progress

                    double val = (double) newValue;
                    if (val > maxCompare || val < minCompare) {
                        isFinal = true;                 // current value will be treated as final value
                                                        // once the valueChangingProperty goes to false
                        finalValue = (Double) newValue; // remember current value
                    } else {
                        isFinal = false;    // no final value anymore - slider 
                        finalValue = null;  // has been dragged to a position within 
                                            // minimum and maximum
                    }

                }
            }
        });

        slider.valueChangingProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> observable,
                                Boolean oldValue, Boolean newValue) {

                if (newValue == true) { // dragging of knob started.
                    isFinal = false;    // captured values are not the final ones.

                } else {                // dragging of knob stopped.

                    if (isFinal) {      // captured value is already the final one
                                        // since it is either the minimum or the maximum value
                        perform(finalValue);
                        finalValue = null;
                    } else {
                        isFinal = true; // next captured value will be the final one
                    }
                }
            }
        });

        Scene scene = new Scene(slider, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void perform(double value) {
        System.err.printf("FINAL: %s\n", value);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!