简体   繁体   English

如何在属性侦听器中设置另一个值?

[英]How can I set another value in property listener?

I want to speed-up my ScrollPane scrolling. 我想加快ScrollPane的滚动速度。 I need something like: 我需要类似的东西:

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

but without stackowerflow exections and working.. 但是没有stackowerflow执行和工作。

May be there is a way to consume this like an event? 可能有办法像事件一样消耗它吗?

PS BTW, why does setOnScroll() fire only when scrolling reaches max (top) or min (bot) position? PS BTW,为什么setOnScroll()仅在滚动到达最大(顶部)或最小(机器人)位置时触发?

I don't really recommend modifying a property while it is already changing, but if you want to do it you need to set a flag to suppress recursive calls. 我真的不建议在属性已更改的情况下对其进行修改,但是如果要执行此操作,则需要设置一个标志以禁止递归调用。 Here's an example: 这是一个例子:

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

I don't actually see any other way to change the increment amounts for a scroll pane. 我实际上没有看到任何其他方法来更改滚动窗格的增量。 Note that ScrollBar has API for changing the increment amounts via its unitIncrement and blockIncrement properties, however ScrollPane does not have equivalent properties. 请注意, ScrollBar具有用于通过其unitIncrementblockIncrement属性更改增量量的API,但是ScrollPane没有等效的属性。

There is a comment in the source code for ScrollPane which says 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.
 */

The current skin for the scroll pane hard codes the unit and block increments for its scroll bars (in the updateHorizontalSB and updateVerticalSB methods) in the manner described in this comment (ie 10% and 90% of the visible amount), so I see no real way to get at these. 滚动窗格的当前外观按照此注释中所述的方式(即可见量的10%和90%)对其滚动条的单位和块增量(在updateHorizontalSBupdateVerticalSB方法中)进行硬编码,因此我看不到获得这些的真正方法。 In Java 9 the skin class will become a public class, and so at a minimum you could subclass it and modify this behavior. 在Java 9中,皮肤类将成为公共类,因此至少您可以将其子类化并修改此行为。

You can try something like this - 您可以尝试这样的事情-

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

Forgive any minor type errors, I have not compiled this. 原谅任何轻微的类型错误,我还没有编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM