valueChanging 属性指示滑块是否正在更改(通常这意味着用户正在拖动滑块拇指)。如果用户执行更改值的单个操作(因为值更改,但滑块从未处于值仍然更改的状态),则不会发生这种情况。
通常,您希望响应 value 本身的变化:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
// process newValue
});
valueChanging 属性的目的是避免在用户拖动拇指时执行大量更新。因此,您可以通过在侦听器中检查 value 的属性来限制仅在更改完成时更新:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
// process newValue
}
});
请注意,这不会通过用鼠标拖动拇指来触发(因为值会更改,但 valueChanging 直到在最终更改后才会设置为 false)。所以你需要包含第二个监听器(你原来的valueChanging监听器):
playRewindSlider.valueChangingProperty().addListener((obs, wasChanging, isNowChanging) -> {
if (! isNowChanging) {
double newValue = playRewindSlider.getValue();
// process newValue
}
});
您可以通过创建添加到两个属性的单个侦听器来减少代码:
ChangeListener<Object> sliderListener = (obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
double newValue = playRewindSlider.getValue();
// process newValue
}
};
playRewindSlider.valueProperty().addListener(sliderListener);
playRewindSlider.valueChangingProperty().addListener(sliderListener);
这是一个完整的例子:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) {
Slider slider = new Slider();
ChangeListener<Object> listener = (obs, oldValue, newValue) -> {
if (! slider.isValueChanging()) {
processSliderChange(slider.getValue());
}
};
slider.valueProperty().addListener(listener);
slider.valueChangingProperty().addListener(listener);
BorderPane root = new BorderPane(slider);
Scene scene = new Scene(root, 200, 200);
stage.setScene(scene);
stage.show();
}
private void processSliderChange(double value) {
System.out.printf("%.2f%n", value);
}
public static void main(String[] args) {
launch();
}
}
这里的另一个选择是使用绑定做一些巧妙的工作,如果滑块的valueProperty 或valueChangingProperty 更改,则该绑定无效,但前提是valueChangingProperty 为假:
DoubleBinding sliderValue = new DoubleBinding() {
{
InvalidationListener l = obs -> {
if (! playRewindSlider.isValueChanging()) invalidate();
};
playRewindSlider.valueProperty().addListener(l);
playRewindSlider.valueChangingProperty().addListener(l);
}
@Override
protected double computeValue() {
return playRewindSlider.getValue();
}
};
然后
sliderValue.addListener((obs, oldValue, newValue) -> {
// process newValue
});
在你需要的时候触发。
以下是使用此技术的相同示例:
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.DoubleBinding;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) {
Slider slider = new Slider();
DoubleBinding sliderValue = new DoubleBinding() {
{
InvalidationListener l = obs -> {
if (! slider.isValueChanging()) invalidate();
};
slider.valueProperty().addListener(l);
slider.valueChangingProperty().addListener(l);
}
@Override
protected double computeValue() {
return slider.getValue();
}
};
sliderValue.addListener((obs, oldValue, newValue) ->
processSliderChange(newValue.doubleValue()));
BorderPane root = new BorderPane(slider);
Scene scene = new Scene(root, 200, 200);
stage.setScene(scene);
stage.show();
}
private void processSliderChange(double value) {
System.out.printf("%.2f%n", value);
}
public static void main(String[] args) {
launch();
}
}