今回はノードの配置を決定するレイアウトについて確認する。シーングラフに登録可能なオブジェクトはすべてレイアウト上に配置となっている。
■ シーングラフにグループを設定する
レイアウトを指定せず、シーングラフ内の複数のノードをまとめたい場合にはGroupクラスを利用する。Groupクラスは子要素を持つ透明なシーングラフであり、getChildren().add関数で子要素を追加できる。
■ 利用可能なレイアウト一覧
JavaFXで利用可能なレイアウトは以下の通り。レイアウトへのセル追加には、一部レイアウトを除いてgetChildren().add関数を利用する。
クラス |
内容 |
主な設定可能プロパティなど |
VBox |
垂直方向にセルを配置するレイアウト |
spacing
fillWidth
margin
alignment
詳細はJavaDoc参照 |
HBox |
水平方向にセルを配置するレイアウト |
spacing
fillHeight
margin
alignment
詳細はJavaDoc参照 |
FlowPane |
ペインの境界で折り返すフローにセルを配置するレイアウト。
セルを並べる方向(縦・横)は指定可能 |
hgap
vgap
orientation
columnHalignment
rowValignment
margin
alignment
詳細はJavaDoc参照 |
TextFlow |
ペインの境界で折り返すフローにテキストを配置するレイアウト。テキスト・ノードの途中でも折り返しが可能。 |
lineSpacing
textAlignment
詳細はJavaDoc参照 |
TilePane |
ペインの境界で折りかえすフローにタイル(セル)を配置するレイアウト。各タイルは同一サイズ |
hgap
vgap
orientation
tileAlignment
margin
alignment
詳細はJavaDoc参照 |
AnchorPane |
ペインの左上をアンカーとし、アンカーからの位置(x,y)を指定して配置するレイアウト |
詳細はJavaDoc参照 |
BorderPane |
ペインを上・左・中央・右・下の5領域に分割し、領域を指定して配置するレイアウト。セルの追加は以下の関数を利用する
- setTop( セル )
- setLeft( セル )
- setCenter( セル )
- setRight( セル )
- setBotton( セル )
|
margin
alignment
詳細はJavaDoc参照 |
GridPane |
ペインを表に見立て、行番号・列番号・セルの行数・セルの列数などを指定して配置するレイアウト。セルの追加は以下の関数を利用する
- add( セル , 列番号, 行番号, セルの列数, セルの行数 )
|
hgap
vgap
margin
alignment
詳細はJavaDoc参照 |
StackPane |
セルを重ねて配置するレイアウト |
alignment
詳細はJavaDoc参照 |
■ サンプルプログラム
以下にレイアウトを利用するサンプルコードを示す。サンプルでは、各行にレイアウト名とレイアウトのイメージを表示している。
◇サンプルコード
package application_fx;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class TestLayout extends Application {
public static void main(String[] args)
{
launch( args );
}
@Override
public void start(Stage primaryStage) throws Exception
{
// シーングラフの作成
// ルートノードを作成
VBox root = new VBox( 2 );
// VBoxを追加
VBox vbox = new VBox();
Text vboxNode1 = new Text("【その1】");
Text vboxNode2 = new Text("【その2】");
vbox.getChildren().addAll( vboxNode1 , vboxNode2 );
root.getChildren().add( createNameAndPane( "VBox\t\t\t" , vbox ) );
// HBoxを追加
HBox hbox = new HBox();
Text hboxNode1 = new Text("【その1abc】");
Text hboxNode2 = new Text("【その2】");
hbox.getChildren().addAll( hboxNode1 , hboxNode2 );
root.getChildren().add( createNameAndPane( "HBox\t\t" , hbox ) );
// FlowPane(横)を追加
// ノード間の幅を設定
FlowPane hflow = new FlowPane();
Text hflowNode1 = new Text("【その1123456789012345678901234567890】") ;
Text hflowNode2 = new Text("【その2】") ;
Text hflowNode3 = new Text("【その3】") ;
hflow.setOrientation( Orientation.HORIZONTAL );
hflow.setHgap( 5 );
hflow.getChildren().addAll( hflowNode1 , hflowNode2 , hflowNode3 );
root.getChildren().add( createNameAndPane( "FlowPane\t\t" , hflow ) );
// FlowPane(縦)を追加
// ノード間の幅を設定
FlowPane vflow = new FlowPane();
Text vflowNode1 = new Text("【その1123456789012345678901234567890】") ;
Text vflowNode2 = new Text("【その2】") ;
Text vflowNode3 = new Text("【その3】") ;
vflow.setOrientation( Orientation.VERTICAL );
vflow.setVgap( 5 );
vflow.getChildren().addAll( vflowNode1 , vflowNode2 , vflowNode3 );
root.getChildren().add( createNameAndPane( "\t\t\t" , vflow ) );
// TextFlowを追加
TextFlow text = new TextFlow();
Text textNode1 = new Text("【その1123456789012345678901234567890】") ;
Text textNode2 = new Text("【その2】") ;
Text textNode3 = new Text("【その3】") ;
text.getChildren().addAll( textNode1 , textNode2 , textNode3 );
root.getChildren().add( createNameAndPane( "TextFlow\t\t" , text ) );
// AnchorPaneを追加
AnchorPane anchor = new AnchorPane();
Text anchorNode1 = new Text("【その1abc】") ;
Text anchorNode2 = new Text("【その2】") ;
anchorNode1.setLayoutX( 20 );
anchorNode1.setLayoutY( 50 );
anchorNode2.setLayoutX( 50 );
anchorNode2.setLayoutY( 20 );
anchor.getChildren().addAll( anchorNode1 , anchorNode2 );
root.getChildren().add( createNameAndPane( "AnchorPane\t" , anchor ) );
// BorderPaneを追加
// Alignの設定
// マージンの設定
BorderPane border = new BorderPane();
Text borderNode1 = new Text("【その1abc】") ;
Text borderNode2 = new Text("【その2】") ;
Text borderNode3 = new Text("【その3】") ;
Text borderNode4 = new Text("【その4】") ;
Text borderNode5 = new Text("【その5】") ;
BorderPane.setAlignment( borderNode1 , Pos.TOP_CENTER );
BorderPane.setAlignment( borderNode2 , Pos.TOP_CENTER );
BorderPane.setAlignment( borderNode3 , Pos.TOP_CENTER );
BorderPane.setAlignment( borderNode4 , Pos.TOP_CENTER );
BorderPane.setAlignment( borderNode5 , Pos.TOP_CENTER );
BorderPane.setMargin( borderNode1 , new Insets( 10,10,10,10 ) );
BorderPane.setMargin( borderNode2 , new Insets( 10,10,10,10 ) );
BorderPane.setMargin( borderNode3 , new Insets( 10,10,10,10 ) );
BorderPane.setMargin( borderNode4 , new Insets( 10,10,10,10 ) );
BorderPane.setMargin( borderNode5 , new Insets( 10,10,10,10 ) );
border.setTop( borderNode1 );
border.setLeft( borderNode2 );
border.setCenter( borderNode3 );
border.setRight( borderNode4 );
border.setBottom( borderNode5 );
root.getChildren().add( createNameAndPane( "BorderPane\t" , border ) );
// GridPaneを追加
GridPane grid = new GridPane();
Text gridNode1 = new Text("【その1abc】") ;
Text gridNode2 = new Text("【その2】") ;
Text gridNode3 = new Text("【その3】") ;
Text gridNode4 = new Text("【その4】") ;
Text gridNode5 = new Text("【その5】") ;
grid.add( gridNode1 , 0 , 0 , 1 , 1 );
grid.add( gridNode2 , 1 , 0 , 1 , 1 );
grid.add( gridNode3 , 0 , 1 , 2 , 1 );
grid.add( gridNode4 , 2 , 1 , 1 , 2 );
grid.add( gridNode5 , 0 , 2 , 2 , 1 );
root.getChildren().add( createNameAndPane( "GridPane\t\t" , grid ) );
// StackPaneを追加
StackPane stack = new StackPane();
Text stackNode1 = new Text("【その1abc】") ;
Text stackNode2 = new Text("【その2】") ;
Text stackNode3 = new Text("【その3】") ;
stack.getChildren().addAll( stackNode1 , stackNode2 , stackNode3 );
root.getChildren().add( createNameAndPane( "StackPane\t\t" , stack ) );
// シーンの作成(文字列で指定)
Scene scene = new Scene( root , 300 , 450 , Color.web( "9FCC7F" ) );
// ウィンドウ表示
primaryStage.setScene( scene );
primaryStage.show();
}
/**
* レイアウトと、レイアウトの名前を出力するイメージを作成する
* @param name
* @param pane
* @return
*/
public Node createNameAndPane( String name , Pane pane )
{
// ルートノードを作成
HBox root = new HBox( 5.0 );
// 名前を追加
Text text = new Text( name );
// レイアウトの位置をそろえ、
// 背景色を白、境界線を黒で出力
Background back = new Background( new BackgroundFill( Color.WHITE , null , null ) );
Border border = new Border( new BorderStroke( Color.BLACK ,
BorderStrokeStyle.SOLID,
CornerRadii.EMPTY,
null
) );
pane.setLayoutX( 200 );
pane.setBackground( back );
pane.setBorder( border );
// ノードを追加
root.getChildren().addAll( text , pane );
return root;
}
}
◇実行結果
◇解説
プログラムの流れはmain関数(37行目~153行目)にまとめられている。main関数では各レイアウトの使用イメージを作成し、createNameAndPane関数を呼び出している。createNameAndPane関数(161行目~185行目)では、引数にレイアウト名とレイアウト・イメージを受け取り、フォーマット出力したノードを返す。返されたノードはmain関数内でルートノードに追加するという処理を各レイアウトについて行っている。
実行結果画像で特筆すべき箇所は2つある。1つはFlowPaneとTextFlowの違いである。FlowPaneではテキストの途中で折り返しは発生しないが、TextFlowはペインの折り返し位置でテキストが折り変えされていることが確認できる。
2つめはHboxとTilePaneの違いである。Hboxでは各セルの大きさは不揃いであってもよいが、TilePaneのセルは全て同じ大きさに変更されることが確認できる。
■ 参照
- JavaFX: JavaFXでのレイアウトの操作
- JavaDoc - クラスPane