JavaFX 2.2: закрепление слайдера перетаскивания N событий

Я пытаюсь поймать события на JavaFX бегунок особенно тот, который указывает, что перетаскивание остановилось и было выпущено. Сначала я использовал valueProperty с макетом кода, как это

slider.valueProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) {
        log.fine(newValue.toString());
    }
});

но с этим он обновляется слишком часто. Поэтому я искал в SceneBuilder и API и нашел некоторые интересные, как

slider.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
    @Override
    public void handle(MouseDragEvent event) {
        System.out.println("setOnMouseDragReleased");
    }
});

но их никогда не увольняют. Там только некоторые любят setOnMouseReleased Я получаю некоторый вывод, но это, например, подсчет для весь узел, как метки и т. д.

Итак, мой вопрос, который является правильным крючком, чтобы знать, что значение больше не меняется (если это возможно после выпуска мыши, как жест drag'n'Drop) и, возможно, с небольшим примером, чтобы увидеть его интерфейсы работают.

2 ответов


добавьте прослушиватель изменений в valueChangingProperty чтобы узнать, когда значение ползунка меняется, и принять любые меры, которые вы хотите по изменению значения.

в приведенном ниже примере будет регистрироваться значение ползунка, когда он начнет меняться и снова, когда он завершит изменение.

slidervaluechangelogger

import javafx.application.Application;
import javafx.beans.value.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class SliderChangeLog 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 Slider slider = new Slider(0, 1, 0.5);
        slider.setMajorTickUnit(0.5);
        slider.setMinorTickCount(0);
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);
        slider.setMinHeight(Slider.USE_PREF_SIZE);

        slider.valueChangingProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(
                    ObservableValue<? extends Boolean> observableValue,
                    Boolean wasChanging,
                    Boolean changing) {
                String valueString = String.format("%1$.3f", slider.getValue());

                if (changing) {
                    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); }
}

ответ jewelsea был очень полезен для установки меня на правильный путь, однако, если "snapToTicks" включен, нежелательные результаты поведения. "Конечное" значение, захваченное слушателем jewelsea, -до привязка происходит, и значение после привязки никогда не захватывается.

мое решение устанавливает слушателя на value но использует valueChanging как страж. Что-то вроде:

slider.valueProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(
                ObservableValue<? extends Number> observableValue,
                Number previous,
                Number now) {
            if (!slider.isValueChanging()
                  || now.doubleValue() == slider.getMax()
                  || now.doubleValue() == slider.getMin()) {
                // This only fires when we're done
                // or when the slider is dragged to its max/min.
            }
        }
    });

я обнаружил, что проверка значения max и min была необходима, чтобы поймать угол случай, когда пользователь перетаскивает ползунок полностью за его левую или правую границы, прежде чем отпустить мышь. По какой-то причине это не запускает событие, как я ожидал, так что это похоже на нормальную работу.

Примечание: В отличие от jewelsea, я игнорирую начальное значение ради простоты.

примечание 2: я фактически использую ScalaFX 2, поэтому я не уверен, что этот перевод Java компилируется как написанный.