この質問はかなり単純です。たとえ次のような場合でも、一度だけトリガーされるサイズ変更イベントを受け取ることは可能ですか? width
そして height
同時に変更しますか?
1ピクセルあたりウィンドウピクセルのサイズで画像を計算するアプリケーションがあります。ウィンドウのサイズが変更されると、画像は再び計算されます。問題は、聞いているとき widthProperty()
そして heightProperty()
たとえあったとしても、いつでも2つのイベントが発生します。 width
そして height
同じループサイクルで変更されました。これは1つの冗長な計算になります。更新ごとに1回サイズ変更を監視する方法はありますか?
簡単な例:
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);
}
}
これは印刷します:
old: (800.0, 800.0); new: (400.0, 800.0)
old: (400.0, 800.0); new: (400.0, 400.0)
しかし、私はこれを出力としてだけ欲しいのです。
old: (800.0, 800.0); new: (400.0, 400.0)
回答:
回答№1の場合は3これを行うための良い方法はありません。ちょっとしたハックを使って似たようなことをすることができます。 Platform.runLater()
。これは、両方の変更(幅と高さ)が同じイベントからトリガーされるために機能します。 Platform.runLater(...)
引き起こすことができます。変数をnullに設定し、それがnullでない場合は変更を無視することで、同じイベントからの複数の変更が1回の呼び出しにまとめられます。 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);
}
}
これはおそらくちょっとしたハックですが、保留中の他の変更がない場合にのみ変更を処理することは、実際にこのユースケースで探しているものとまったく同じかもしれません。
回答№2の場合は1
リスナーとは違います。
リスナーを追加する layoutBounds
プロパティは "tの助けを得ていない。
私が知っている唯一の回避策は、 layoutChildren
ルートノードのメソッド。レイアウトにサイズを割り当てた後に呼び出されます。 Parent
:
Region root = new Region() {
@Override
protected void layoutChildren() {
super.layoutChildren();
System.out.println("new: (" + getWidth() + ", " + getHeight() + ");");
}
};
注:JavaFX 9 あなたが追加することができます postLayoutPulseListener
シーンには影響しますが、サイズが変わらない場合でもこれが発生する可能性があります。
scene.addPostLayoutPulseListener(() -> {
System.out.println("new: (" + primaryStage.getWidth() + ", " + primaryStage.getHeight() + ")");
});