JavaFX 获取单个调整大小事件

Jho*_*007 5 java javafx javafx-2 javafx-8

这个问题相当简单:是否可以接收仅触发一次的调整大小事件,即使width同时height更改?

我有一个应用程序,它计算每像素窗口像素大小的图像。当窗口调整大小时,将再次计算图像。问题是,在侦听widthProperty()和 时heightProperty(),总会有两个事件触发,即使widthheight在同一个循环周期中更改。这导致了一次冗余计算。有没有办法在每次更新时监听一次调整大小?

一个简单的例子:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        primaryStage.setWidth(800);
        primaryStage.setHeight(800);

        primaryStage.widthProperty().addListener((observable, oldValue, newValue) ->
                System.out.println("old: (" + oldValue + ", " + primaryStage.getHeight() + "); " 
                                 + "new: (" + newValue + ", " + primaryStage.getHeight() + ")")
        );

        primaryStage.heightProperty().addListener((observable, oldValue, newValue) ->
                System.out.println("old: (" + primaryStage.getWidth() + ", " + oldValue + "); " 
                                 + "new: (" + primaryStage.getWidth() + ", " + newValue + ")")
        );

        primaryStage.setWidth(400);
        primaryStage.setHeight(400);
    }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

old: (800.0, 800.0); new: (400.0, 800.0)
old: (400.0, 800.0); new: (400.0, 400.0)
Run Code Online (Sandbox Code Playgroud)

但我只想将其作为输出:

old: (800.0, 800.0); new: (400.0, 400.0)
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 6

没有什么好的方法可以做到这一点。您可以使用一些 hack 来实现类似的效果Platform.runLater()。这是有效的,因为两个更改(宽度和高度)都是由同一事件触发的,该事件在Platform.runLater(...)触发之前会被完整处理。将变量设置为 null 并忽略更改(如果它不为 null)可确保将同一事件的多个更改合并到对 的单个调用中Platform.runLater()

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        primaryStage.setWidth(800);
        primaryStage.setHeight(800);

        ChangeListener<Number> listener = new ChangeListener<Number>() {
            private Point2D stageSize = null ;
            private Point2D previousStageSize = new Point2D(primaryStage.getWidth(), primaryStage.getHeight());
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
                if (stageSize == null) {
                    Platform.runLater(() -> {
                        System.out.printf("Old: (%.1f, %.1f); new: (%.1f, %.1f)%n", 
                                previousStageSize.getX(), previousStageSize.getY(), 
                                stageSize.getX(), stageSize.getY());
                        previousStageSize = stageSize;
                        stageSize = null;
                    });
                }
                stageSize = new Point2D(primaryStage.getWidth(), primaryStage.getHeight());                
            }


        };

        primaryStage.widthProperty().addListener(listener);
        primaryStage.heightProperty().addListener(listener);


        primaryStage.setWidth(400);
        primaryStage.setHeight(400);
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然这可以说是有点黑客行为,但仅当没有其他待处理的更改时才处理更改实际上可能正是您在此用例中所寻找的。