JavaFX滑块-箭头按钮(->;)移动滑块时未触发changeListener
My valueChangingProperty Listener仅捕获由鼠标引起的事件(用鼠标拖动滑块或在滑块内的某个位置单击鼠标)。当我按下箭头按钮(->)时,它不会对滑块移动做出响应(因此其值会发生变化),尽管我看到它会导致滑块移动JavaFX滑块-箭头按钮(->;)移动滑块时未触发changeListener,javafx,slider,Javafx,Slider,My valueChangingProperty Listener仅捕获由鼠标引起的事件(用鼠标拖动滑块或在滑块内的某个位置单击鼠标)。当我按下箭头按钮(->)时,它不会对滑块移动做出响应(因此其值会发生变化),尽管我看到它会导致滑块移动 MyController.java private Slider playRewindSlider; playRewindSlider.valueChangingProperty().addListener(new ChangeListener() {
MyController.java
private Slider playRewindSlider;
playRewindSlider.valueChangingProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
boolean finishedDragging = !(Boolean) observable.getValue();
if (finishedDragging) {
// logic triggered ONCE after slider moving finished
}
}
});
如何使用箭头(->)捕捉正在更改的滑块
另外,我在SO上看到了许多关于滑块的帖子,但没有一篇有效。属性
valueChanging
指示滑块是否正在更改(通常这意味着用户正在拖动滑块拇指)。如果用户执行更改值的单个操作,则不会发生这种情况(因为值会更改,但滑块永远不会处于值仍在更改的状态)
通常,您希望响应值本身的更改:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
// process newValue
});
valueChanging
属性的目的是避免在用户拖动拇指时执行大量更新。因此,您可以通过在侦听器中检查值的属性来限制仅在更改完成时更新:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
// process newValue
}
});
请注意,用鼠标拖动拇指不会触发此操作(因为值会发生更改,但在最终更改之前,valueChanging
不会设置为false)。因此,您需要包含第二个侦听器(您原来的valueChanging
listener):
您可以通过创建单个侦听器来减少代码,并将其添加到两个属性中:
ChangeListener<Object> sliderListener = (obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
double newValue = playRewindSlider.getValue();
// process newValue
}
};
playRewindSlider.valueProperty().addListener(sliderListener);
playRewindSlider.valueChangingProperty().addListener(sliderListener);
然后
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();
}
}
valueChanging
属性指示滑块是否正在更改(通常这意味着用户正在拖动滑块拇指)。如果用户执行更改值的单个操作,则不会发生这种情况(因为值会更改,但滑块永远不会处于值仍在更改的状态)
通常,您希望响应值本身的更改:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
// process newValue
});
valueChanging
属性的目的是避免在用户拖动拇指时执行大量更新。因此,您可以通过在侦听器中检查值的属性来限制仅在更改完成时更新:
playRewindSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
// process newValue
}
});
请注意,用鼠标拖动拇指不会触发此操作(因为值会发生更改,但在最终更改之前,valueChanging
不会设置为false)。因此,您需要包含第二个侦听器(您原来的valueChanging
listener):
您可以通过创建单个侦听器来减少代码,并将其添加到两个属性中:
ChangeListener<Object> sliderListener = (obs, oldValue, newValue) -> {
if (! playRewindSlider.isValueChanging()) {
double newValue = playRewindSlider.getValue();
// process newValue
}
};
playRewindSlider.valueProperty().addListener(sliderListener);
playRewindSlider.valueChangingProperty().addListener(sliderListener);
然后
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();
}
}
如何使用箭头(->)捕捉正在更改的滑块
如果要捕获特定事件,可以添加如下事件筛选器:
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(event.getCode() == KeyCode.RIGHT && slider.isFocused()) {
System.out.println("Value changed because of key right pressed on slider").
}
});
如何使用箭头(->)捕捉正在更改的滑块
如果要捕获特定事件,可以添加如下事件筛选器:
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(event.getCode() == KeyCode.RIGHT && slider.isFocused()) {
System.out.println("Value changed because of key right pressed on slider").
}
});
但是OP想要这个代码禁用的功能:“如何用箭头额外捕捉变化的滑块?”以防他想要特定的事件(->)。他们确实希望捕捉到这一事件。您的代码完全禁用该事件。另外,在其他情况下,滑块的值可以在不更改valueChangingProperty()
的情况下更改(向左箭头或鼠标单击轨迹等),因此,这并不能解决根本问题。我只是在你的答案之后发布了一个附加答案,以防他想知道如何在滑块上跟踪特定的右键按下事件。但OP想要此代码禁用的功能:“如何使用箭头额外捕捉变化的滑块?”以防他想要特定的事件(->)确切地他们确实希望捕捉到这一事件。您的代码完全禁用该事件。另外,在其他情况下,滑块的值可以在不更改valueChangingProperty()
的情况下更改(向左箭头或鼠标单击轨迹等),所以这并不能解决根本的问题。我只是在你的答案后面加上了我的答案,以防他想知道如何在滑块上跟踪特定的右键按下事件。