setManagedの意味
setManagedというメソッドがなぜ存在するのか不思議だったのだが、その意味はこうだ。
- trueの場合、そこでの何らかの変更があった場合に、それをトップレベルにまで伝えてすべてのレイアウトをやり直す。
- デフォルトではtrueになっている。
レイアウト用のペイン、つまりBorderPaneやら何やらのみではなく、すべてのParentとNodeの関係においてこの仕組みが働く。
ということ。例えば、以下の例のようにAnimationTimerを使用してボールを転がすような場合、ボールが転がるたび、つまりAnimationTimerのtickごとにトップレベルからの再レイアウトがかかってしまう。
このような場合には、Group自体をunmanagedにする。すると、再レイアウトはかからない。もちろん、再レイアウトがされないので、自力でレイアウトする必要がある。
この例では問題は無いが、例えばAnimationTimerのtickごとにLabelに現在時刻を表示するような場合、Labelをunmanagedにしなければならないが、そうするとおそらくLabelはレイアウトの枠組みからはずれてしまい、自力で所定の位置に置かなければならなくなると思われる。
import static java.lang.Math.*; import java.util.*; import javafx.animation.*; import javafx.application.*; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.scene.paint.*; import javafx.scene.shape.*; import javafx.stage.*; public class GraphicsWithRegions extends Application { private Circle ball; private double direction; private Random random = new Random(); private double speed = 10; @Override public void start(final Stage primaryStage) { ball = new Circle(100, 100, 20); ball.setFill(Color.BLUE); direction = 2 * PI * random.nextDouble(); Group group = new Group(ball); Pane pane = new Pane(group); group.setManaged(false); // <------------- 無いとレイアウトがかかりすぎる。 BorderPane border = new BorderPane() { @Override public void layoutChildren() { System.out.println("layoutChildren"); super.layoutChildren(); } }; border.setCenter(pane); border.setTop(new TextArea("top area")); border.setBottom(new TextField("bottom field")); final Scene scene = new Scene(border, 800, 600, Color.BLACK); primaryStage.setScene(scene); primaryStage.show(); ball.setCenterX(pane.getWidth() / 2); ball.setCenterY(pane.getHeight() / 2); new AnimationTimer() { @Override public void handle(long now) { double x = ball.getCenterX(); double y = ball.getCenterY(); double newDirection = random.nextDouble() * PI; if (y < 0) { direction = newDirection; } else if (pane.getWidth() < x) { direction = newDirection + PI * 0.5; } else if (pane.getHeight() < y) { direction = newDirection + PI; } else if (x < 0) { direction = newDirection + PI * 1.5; } ball.setCenterX(x + speed * cos(direction)); ball.setCenterY(y + speed * sin(direction)); } }.start(); } public static void main(String[] args) { launch(args); } }