繁体   English   中英

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

[英]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执行和工作。

可能有办法像事件一样消耗它吗?

PS BTW,为什么setOnScroll()仅在滚动到达最大(顶部)或最小(机器人)位置时触发?

我真的不建议在属性已更改的情况下对其进行修改,但是如果要执行此操作,则需要设置一个标志以禁止递归调用。 这是一个例子:

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没有等效的属性。

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.
 */

滚动窗格的当前外观按照此注释中所述的方式(即可见量的10%和90%)对其滚动条的单位和块增量(在updateHorizontalSBupdateVerticalSB方法中)进行硬编码,因此我看不到获得这些的真正方法。 在Java 9中,皮肤类将成为公共类,因此至少您可以将其子类化并修改此行为。

您可以尝试这样的事情-

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

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

暂无
暂无

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

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