CUBは子供の白熊

Java SE 8 実践プログラミングの練習問題を解く

第4章 JavaFX による GUI プログラミング : 問題 4 : バインディング

問題

本文のサンプルコード “常に中心に配置される円” を

常に中心に配置され、四辺の少なくとも二つに接する

に拡張せよ

解答

“常に中心に配置される円” のコードは以下のとおり

import static javafx.beans.binding.Bindings.*;

public void start(Stage stage) throws Exception {
    Circle circle = new Circle(100, 100, 100);
    circle.setFill(Color.RED);
    Pane pane = new Pane();
    pane.getChildren().add(circle);
    Scene scene = new Scene(pane);
    // 円と Scene のバインディング
    circle.centerXProperty().bind(divide(scene.widthProperty(),  2.0));
    circle.centerYProperty().bind(divide(scene.heightProperty(), 2.0));

    stage.setScene(scene);
    stage.show();
}

f:id:ClosedUnBounded:20150721203331p:plain

円の中心に加えて半径もバインディングすればよい

■ すなおな解

// 円と Scene のバインディング
circle.centerXProperty().bind(divide(scene.widthProperty(),  2.0));
circle.centerYProperty().bind(divide(scene.heightProperty(), 2.0));
circle.radiusProperty().bind(
    divide(min(scene.widthProperty(), scene.heightProperty()), 2.0)
);

■ 一捻りした解

// 円と Scene のバインディング
circle.centerXProperty().bind(divide(scene.widthProperty(),  2.0));
circle.centerYProperty().bind(divide(scene.heightProperty(), 2.0));
circle.radiusProperty().bind(
    createDoubleBinding(
        () -> Math.min(scene.getWidth(), scene.getHeight()) / 2.0,
        scene.widthProperty(), scene.heightProperty()
    )
);

Callable<?>を使うパターンは万能だけど、ここは “すなおな解” の方が分かりやすいかな

おまけ

JavaFX では、円という図形がオブジェクトになっていてPropertyまで持っている
これは AWT/Swing よりはるかに強力で分かりやすい

AWT/Swing にもEllipse2Dというクラスはあるが、これ自身GUIコンポーネントではないため、イベントに反応できない
また、楕円を描画するにはGraphics2Dオブジェクトが必要である