CUBは子供の白熊

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

第4章 JavaFX による GUI プログラミング : 問題 7 : CSS

問題

CSS を使用しないで、コントロールの境界を設定する方法を調べよ

境界について

“境界” というのは、下の図(CSS Box Model)の Border だよね
http://www.w3.org/TR/css3-background/box

CSSNodeクラスに適用できるが、Border プロパティを持っているのはNodeの派生クラスのRegionである

Border のプロパティは、基本的に四辺独立に指定できる

  • プロパティ値をひとつだけ書いたときは、全ての辺にセットされる
  • プロパティ値を四つ並べて書くと top, right, bottom, left の順にセットされる
  • プロパティ値を二個または三個並べたとき、値は循環し top, right, bottom, left の順にセットされる

Border は、直線の境界(Stroke Border)と画像境界(Image Border)に分かれる

■ 直線の境界(Stroke Border)

プロパティ キーワード 備考
-fx-border-color
線形グラデーション
円形グラデーション
画像
スタイル -fx-border-style ※ 下記参照
太さ -fx-border-width 絶対サイズ(point, cm など)
相対サイズ(pixel, em など)
ノード相対
角の半径 -fx-border-radius 同上 X/Y方向個別に指定可
マージン -fx-border-insets 同上

※ 直線スタイル

属性 必須 キーワード 備考
線種 solid(実線)
dotted(点線)
dashed(破線)
none(なし)
segments 数値...
segments はいわゆるユーザー定義
フェーズ × phase 数値 意味不明
線の位置 × centered(中央)
inside(内側)
outside(外側)
角の形状 × line-join miter 数値
bevel(直角)
round(丸め)
miter はある値を境に直角になる
端の形状 × line-cap square(突出)
butt
round(丸め)
butt は四角だが突出しない

■ 画像境界(Image Border)

プロパティ キーワード 備考
画像ファイル -fx-border-image-source URL Jar ファイル相対も可
画像の繰り返し -fx-border-image-repeat repeat(拡大なし)
space(整数倍、拡大なし)
round(整数倍、拡大)
no-repeat(拡大)
X/Y方向個別に指定可
repeat no-repeat は
repeat-x と
no-repeat repeat は
repeat-y と
記述できる
角のサイズ -fx-border-image-slice 絶対サイズ(point, cm など)
相対サイズ(pixel, em など)
ノード相対
太さ -fx-border-image-width 同上
マージン -fx-border-image-insets 同上

なんと、これだけのプロパティが指定できるんですな~

解答

RegionクラスのsetBorder(Border)メソッドを呼び出す

BorderクラスのコンストラクタにはBorderStrokeオブジェクトを引数にするものとBorderImageオブジェクトを引数にするものがあり、CSS の Stroke Border と Image Border に相当する
ただし、setBorder(Border)メソッドでは CSS と同等のスタイルは指定できない

では、実際に境界を描いてみよう
ちなみに画像境界で使用する画像はこれ
f:id:ClosedUnBounded:20150807100251p:plain

CSS バージョン

public void start(Stage stage) throws Exception {
    // デフォルトの外観のテキストフィールド
    TextField defaultField = new TextField("デフォルトの外観");
    // 直線の枠線を持つテキストフィールド
    TextField strokeField = new TextField("Stroke Border");
    // 画像枠線を持つテキストフィールド
    TextField imageField = new TextField("Image Border");

    strokeField.setStyle(
        "-fx-pref-height: 4.0em;"                          +
        "-fx-border-color: blue green red darkOliveGreen;" +
        "-fx-border-style: solid dotted dashed solid;"     +
        "-fx-border-radius: 0.5em 2.0em 0.5em 2.5em;"      +
        "-fx-border-width: 1.0px 2.0px 3.0px 4.0px;"       +
        "-fx-border-insets: 0.5em;"
    );
    imageField.setStyle(
        "-fx-pref-width: 12.0em;"                   +
        "-fx-pref-height: 5.0em;"                   +
        "-fx-border-image-source: url(border.png);" +
        "-fx-border-image-repeat: round no-repeat;" +
        "-fx-border-image-slice: 27.0px;"           +
        "-fx-border-image-width: 9.0px;"            +
        "-fx-border-image-insets: 0.5em;"
    );
    VBox root = new VBox();
    root.getChildren().addAll(defaultField, strokeField, imageField);
    stage.setScene(new Scene(root));
    stage.show();
}

setBorderバージョン

public void start(Stage stage) throws Exception {
    // デフォルトの外観のテキストフィールド
    TextField defaultField = new TextField("デフォルトの外観");
    // 直線の枠線を持つテキストフィールド
    TextField strokeField = new TextField("Stroke Border");
    // 画像枠線を持つテキストフィールド
    TextField imageField = new TextField("Image Border");

    final double em = new Text("").getLayoutBounds().getHeight();
    strokeField.setPrefHeight(4.0*em);
    strokeField.setBorder(
        new Border(
            new BorderStroke(  // top, right, bottom, left
                Color.BLUE, Color.GREEN, Color.RED, Color.DARKOLIVEGREEN,
                BorderStrokeStyle.SOLID, BorderStrokeStyle.DOTTED, BorderStrokeStyle.DASHED,
                    BorderStrokeStyle.SOLID,
                new CornerRadii(0.5*em, 2.0*em, 0.5*em, 2.5*em, false),
                new BorderWidths(1.0, 2.0, 3.0, 4.0),
                new Insets(0.5*em)
            )
        )
    );
    imageField.setPrefWidth(12.0*em);
    imageField.setPrefHeight(5.0*em);
    imageField.setBorder(
        new Border(
            new BorderImage(
                new Image("border.png"),
                new BorderWidths(9.0),
                new Insets(0.5*em),
                new BorderWidths(27.0),
                true,
                BorderRepeat.ROUND,
                BorderRepeat.STRETCH
            )
        )
    );
    VBox root = new VBox();
    root.getChildren().addAll(defaultField, strokeField, imageField);
    stage.setScene(new Scene(root));
    stage.show();
}

f:id:ClosedUnBounded:20150807131025p:plain