我有以下 JavaFX 场景(注意 snapToTicks
的设置):
package com.example.javafx;
import javafx.application.Application;
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); }
@Override
public void start(Stage primaryStage) {
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); // !!!!!!!!!!
Scene scene = new Scene(slider, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
呈现如下 slider :
由于 snapToTicks
设置为 true
,一旦松开鼠标按钮, slider 最终将移动到最近的值。
如何检索最终值?
我试过了
slider.valueProperty().addListener( n -> {
if (!slider.isValueChanging()) {
System.err.println(n);
}
});
除了最小值和最大值之外效果很好 - 如果鼠标已经位于 slider 左侧或右侧的位置,则根本不会再调用监听器,因为最终值已经已设置。
我也尝试过使用 valueChangingProperty
:
slider.valueChangingProperty().addListener( (prop, oldVal, newVal) -> {
// NOT the final value when newVal == false!!!!!!!
System.err.println(prop + "/" + oldVal + "/" + newVal);
});
但问题是 JavaFX 仍会将值更改为捕捉值 after 用 newVal
等于 false
调用监听器(我什至会认为这是一个错误,但可能我错过了一些东西)。因此无法在该方法中访问最终的捕捉值。
最佳答案
根据@ItachiUchiha 的建议,我最终想出了以下解决方案。本质上,该解决方案同时使用了 valueProperty
和 valueChangingProperty
监听器,并使用一些标志来跟踪当前状态。最后,当 slider 移动完成且最终值可用时,perform()
方法只被调用一次。这在使用鼠标或通过键盘移动 slider 时有效。
作为 Slider
的子类实现的可重用类可在 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);
}
}
关于java - 如何在 snapToTicks==true 时检索最终的 Slider 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35129670/