【问题标题】:How can I set another value in property listener?如何在属性侦听器中设置另一个值?
【发布时间】:2016-04-22 03:49:29
【问题描述】:

我想加快 ScrollPane 的滚动速度。我需要类似的东西:

scrollPane.vvalueProperty().addListener((observable, oldValue, newValue) -> {
            scrollPane.setVvalue(oldValue.doubleValue() + (newValue.doubleValue() - oldValue.doubleValue()) * 2);
        });

但没有 stackowerflow 执行和工作..

有没有办法像事件一样消费它?

附:顺便说一句,为什么 setOnScroll() 仅在滚动达到最大(顶部)或最小(底部)位置时触发?

【问题讨论】:

    标签: scroll javafx listener


    【解决方案1】:

    我真的不建议在属性已经更改时修改它,但如果你想这样做,你需要设置一个标志来抑制递归调用。这是一个例子:

    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 具有通过其 unitIncrementblockIncrement 属性更改增量金额的 API,但 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 以本注释中描述的方式(即 10% 和 90% 的可见量),所以我看不到真正的方法来获得这些。在 Java 9 中,外观类将成为公共类,因此您至少可以对其进行子类化并修改此行为。

    【讨论】:

    • 所以在 Java 9 中我可以简单地提高鼠标滚轮的滚动速度吗?如果是这样,我可以接受。
    • “简单”?不会。在 Java 9 中,您将能够创建一个 ScrollPaneSkin 的子类来实现缺少的功能,并将其安装在您的 ScrollPane 中。在未来的版本中,它们可能会提供该功能,但据我所知,它并未计划用于 Java 9。
    • 现在我开始怀念我用 JS 写东西的时候了。谢谢@James_D
    【解决方案2】:

    你可以试试这样的 -

    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);
    

    请原谅任何轻微的类型错误,我没有编译这个。

    【讨论】:

      猜你喜欢
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多