How to retrieve the final Slider value when snapToTicks==true?(snapToTicks==true 时如何检索最终的 Slider 值?)
问题描述
我有以下JavaFX场景(注意snapToTicks
的设置):
I have the following JavaFX scene (note the setting of 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();
}
}
呈现这样的滑块:
由于 snapToTicks
设置为 true
,一旦松开鼠标按钮,滑块最终会移动到最接近的值.
Since snapToTicks
is set to true
the slider will finally move to the nearest value once the mouse button is released.
如何检索最终值?
我试过了
slider.valueProperty().addListener( n -> {
if (!slider.isValueChanging()) {
System.err.println(n);
}
});
除了最小值和最大值之外效果很好 - 如果鼠标已经位于滑块左侧或滑块右侧的位置,则根本不会再调用侦听器,因为最终值已经已设置.
which works well except for the minimum and maximum values - if the mouse is already at a position left to the slider or at a position right to the slider, the listener will not be called at all anymore since the final value has already been set.
我也尝试过使用valueChangingProperty
:
slider.valueChangingProperty().addListener( (prop, oldVal, newVal) -> {
// NOT the final value when newVal == false!!!!!!!
System.err.println(prop + "/" + oldVal + "/" + newVal);
});
但问题是JavaFX仍会将值更改为捕捉值之后该侦听器已被调用 newVal
等于 false
(我什至认为这是一个错误,但可能我错过了一些东西).因此,它无法访问该方法中的最终捕捉值.
but the problem is that JavaFX will still change the value to the snapped value after that listener has been called with newVal
equal to false
(which I would even consider a bug, but probably I missed something). So its not possible to access the final, snapped value in that method.
推荐答案
根据@ItachiUchiha 的建议,我终于想出了下面的解决方案.本质上,该解决方案同时使用 valueProperty
和 valueChangingProperty
侦听器,并使用一些标志来跟踪当前状态.最后,当滑块移动完成并且最终值可用时,perform()
方法只被调用一次.这在使用鼠标或通过键盘移动滑块时有效.
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.
作为 Slider
子类实现的可重用类可在 https://github.com/afester/FranzXaver/blob/master/FranzXaver/src/main/java/afester/javafx/components/SnapSlider.java.
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
", value);
}
}
这篇关于snapToTicks==true 时如何检索最终的 Slider 值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:snapToTicks==true 时如何检索最终的 Slider 值?


基础教程推荐
- 大摇大摆的枚举 2022-01-01
- 多个组件的复杂布局 2022-01-01
- 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
- 验证是否调用了所有 getter 方法 2022-01-01
- 在 Java 中创建日期的正确方法是什么? 2022-01-01
- 从 python 访问 JVM 2022-01-01
- Java Swing计时器未清除 2022-01-01
- 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
- 不推荐使用 Api 注释的描述 2022-01-01
- Java 实例变量在两个语句中声明和初始化 2022-01-01