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 值?
基础教程推荐
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01