如何在 属性 侦听器中设置另一个值?
How can I set another value in property listener?
我想加快 ScrollPane 的滚动速度。我需要这样的东西:
scrollPane.vvalueProperty().addListener((observable, oldValue, newValue) -> {
scrollPane.setVvalue(oldValue.doubleValue() + (newValue.doubleValue() - oldValue.doubleValue()) * 2);
});
但没有 stackowerflow 执行和工作..
可能有办法像事件一样使用它吗?
P.S。顺便说一句,为什么 setOnScroll() 仅在滚动达到最大(顶部)或最小(机器人)位置时触发?
您可以尝试这样的操作 -
private boolean scrolllChanging = false;
private void myScroll(ObservableDoubleValue observable, Double oldValue, Double newValue) {
if (!scrollChanging) {
try {
scrollChanging = true;
// Insert logic here. Any subsequent changes won't reach here until `scrollChanging` is set to false again.
} finally {
scrollChanging = false;
}
}
}
scrollPane.vvalueProperty().addListener(this::myScroll);
请原谅任何小的类型错误,我没有编译这个。
我真的不建议在 属性 已经发生变化时修改它,但如果你想这样做,你需要设置一个标志来抑制递归调用。这是一个例子:
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
public class ModifyScrollSpeed extends Application {
@Override
public void start(Stage primaryStage) {
ScrollPane scrollPane = new ScrollPane(createContent());
DoublingListener.register(scrollPane.vvalueProperty());
Scene scene = new Scene(scrollPane, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private static class DoublingListener implements ChangeListener<Number> {
private boolean doubling ;
private Property<Number> target ;
private DoublingListener(Property<Number> target) {
this.target = target ;
}
public static void register(Property<Number> target) {
target.addListener(new DoublingListener(target));
}
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (! doubling) {
doubling = true ;
target.setValue(oldValue.doubleValue() + 2 * (newValue.doubleValue() - oldValue.doubleValue()));
}
doubling = false ;
}
}
private Node createContent() {
TilePane tilePane = new TilePane();
Random rng = new Random();
for (int i = 0; i < 200; i++) {
Region region = new Region();
region.setMinSize(40, 40);
region.setPrefSize(40, 40);
region.setMaxSize(40, 40);
region.setStyle(String.format("-fx-background-color: #%02x%02x%02x;",
rng.nextInt(256), rng.nextInt(256), rng.nextInt(256)));
tilePane.getChildren().add(region);
}
return tilePane ;
}
public static void main(String[] args) {
launch(args);
}
}
我实际上没有看到任何其他方法来更改滚动窗格的增量。请注意,ScrollBar
具有 API 用于通过其 unitIncrement
and blockIncrement
属性更改增量,但是 ScrollPane
没有等效属性。
source code for ScrollPane
中有一条评论说
/*
* TODO The unit increment and block increment variables have been
* removed from the public API. These are intended to be mapped to
* the corresponding variables of the scrollbars. However, the problem
* is that they are specified in terms of the logical corrdinate space
* of the ScrollPane (that is, [hmin..hmax] by [vmin..vmax]. This is
* incorrect. Scrolling is a user action and should properly be based
* on how much of the content is visible, not on some abstract
* coordinate space. At some later date we may add a finer-grained
* API to allow applications to control this. Meanwhile, the skin should
* set unit and block increments for the scroll bars to do something
* reasonable based on the viewport size, e.g. the block increment
* should scroll 90% of the pixel size of the viewport, and the unit
* increment should scroll 10% of the pixel size of the viewport.
*/
滚动窗格的当前 skin 按照此评论中描述的方式硬编码其滚动条的单位和块增量(在 updateHorizontalSB
和 updateVerticalSB
方法中) (即可见量的 10% 和 90%),所以我看不出真正的方法来获得这些。在 Java 9 中,皮肤 class 将变成 public class,因此您至少可以子class 它并修改此行为。
我想加快 ScrollPane 的滚动速度。我需要这样的东西:
scrollPane.vvalueProperty().addListener((observable, oldValue, newValue) -> {
scrollPane.setVvalue(oldValue.doubleValue() + (newValue.doubleValue() - oldValue.doubleValue()) * 2);
});
但没有 stackowerflow 执行和工作..
可能有办法像事件一样使用它吗?
P.S。顺便说一句,为什么 setOnScroll() 仅在滚动达到最大(顶部)或最小(机器人)位置时触发?
您可以尝试这样的操作 -
private boolean scrolllChanging = false;
private void myScroll(ObservableDoubleValue observable, Double oldValue, Double newValue) {
if (!scrollChanging) {
try {
scrollChanging = true;
// Insert logic here. Any subsequent changes won't reach here until `scrollChanging` is set to false again.
} finally {
scrollChanging = false;
}
}
}
scrollPane.vvalueProperty().addListener(this::myScroll);
请原谅任何小的类型错误,我没有编译这个。
我真的不建议在 属性 已经发生变化时修改它,但如果你想这样做,你需要设置一个标志来抑制递归调用。这是一个例子:
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
public class ModifyScrollSpeed extends Application {
@Override
public void start(Stage primaryStage) {
ScrollPane scrollPane = new ScrollPane(createContent());
DoublingListener.register(scrollPane.vvalueProperty());
Scene scene = new Scene(scrollPane, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private static class DoublingListener implements ChangeListener<Number> {
private boolean doubling ;
private Property<Number> target ;
private DoublingListener(Property<Number> target) {
this.target = target ;
}
public static void register(Property<Number> target) {
target.addListener(new DoublingListener(target));
}
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (! doubling) {
doubling = true ;
target.setValue(oldValue.doubleValue() + 2 * (newValue.doubleValue() - oldValue.doubleValue()));
}
doubling = false ;
}
}
private Node createContent() {
TilePane tilePane = new TilePane();
Random rng = new Random();
for (int i = 0; i < 200; i++) {
Region region = new Region();
region.setMinSize(40, 40);
region.setPrefSize(40, 40);
region.setMaxSize(40, 40);
region.setStyle(String.format("-fx-background-color: #%02x%02x%02x;",
rng.nextInt(256), rng.nextInt(256), rng.nextInt(256)));
tilePane.getChildren().add(region);
}
return tilePane ;
}
public static void main(String[] args) {
launch(args);
}
}
我实际上没有看到任何其他方法来更改滚动窗格的增量。请注意,ScrollBar
具有 API 用于通过其 unitIncrement
and blockIncrement
属性更改增量,但是 ScrollPane
没有等效属性。
source code for ScrollPane
中有一条评论说
/*
* TODO The unit increment and block increment variables have been
* removed from the public API. These are intended to be mapped to
* the corresponding variables of the scrollbars. However, the problem
* is that they are specified in terms of the logical corrdinate space
* of the ScrollPane (that is, [hmin..hmax] by [vmin..vmax]. This is
* incorrect. Scrolling is a user action and should properly be based
* on how much of the content is visible, not on some abstract
* coordinate space. At some later date we may add a finer-grained
* API to allow applications to control this. Meanwhile, the skin should
* set unit and block increments for the scroll bars to do something
* reasonable based on the viewport size, e.g. the block increment
* should scroll 90% of the pixel size of the viewport, and the unit
* increment should scroll 10% of the pixel size of the viewport.
*/
滚动窗格的当前 skin 按照此评论中描述的方式硬编码其滚动条的单位和块增量(在 updateHorizontalSB
和 updateVerticalSB
方法中) (即可见量的 10% 和 90%),所以我看不出真正的方法来获得这些。在 Java 9 中,皮肤 class 将变成 public class,因此您至少可以子class 它并修改此行为。