JavaFX 2.2: Drag n Drop Events slider binding

I am trying to catch events on the JavaFX Slider , especially one that indicates that the drag and drop has stopped and has been released. At first I used valueProperty with mock code like this

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

but with this it is updated too often. So I searched in SceneBuilder and the API and found some interesting options, like

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

but they never quit. There are only a few, such as setOnMouseReleased , I get some output, but this is, for example, counting for a whole Node, like labels, etc.

So my question is, is the right hook to know that the value does not change anymore (if possible after releasing the mouse, like a drag'n'drop gesture) and, perhaps with a small example, to see its interfaces work.

+7
events javafx-2 slider drag-and-drop
source share
2 answers

Add a change listener to the valueChangingProperty slider to find out when the slider value changes, and perform any action that you want to change the value.

The example below will record the value of the slider when it starts to change, and again when it finishes the change.

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); } } 
+9
source share
Answer to

jewelsea was very useful for setting me on the right track, however if “snapToTicks” is turned on, the results of unwanted behavior. The value "end" written by the jewelsea listener is before the binding, and the value after the binding will never be fixed.

My solution sets the listener to value , but uses valueChanging as a clock. Something like:

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

I found that checking the maximum and minimum values ​​was necessary to catch the corner case when the user drags the slider completely over the left or right border before releasing the mouse. For some reason this does not work as I expected, so it seems to work.

Note. Unlike jewelsea, I just ignore the initial meaning for simplicity.

Note 2: I actually use ScalaFX 2, so I'm not sure if this Java translation compiles as written.

0
source share

All Articles