2 ノードのサイズ指定と位置合せに関するヒント
このトピックでは、JavaFXレイアウト・ペインに配置されるノードのサイズと位置合せを制御する手法について説明します。
組込みのJavaFXレイアウト・ペインを使用する主な利点は、ノードのサイズと位置合せをペインごとに設定できることです。ペインがサイズ変更されると、推奨サイズ範囲の設定に従ってノードがサイズ変更されます。すべてのノード・クラスがサイズ変更されるわけではありません。UIコントロールとレイアウト・ペインはサイズ変更できますが、図形、Text
オブジェクトおよびGroup
オブジェクトはサイズ変更できず、レイアウト内の固定オブジェクトとして扱われます。
UIでのコントロールのサイズを綿密に制御する必要がある場合は、コントロールの推奨サイズ範囲を直接設定できます。これにより、レイアウト・ペインでその設定が使用され、コントロールのサイズが決定されます。コントロールの位置を管理するには、レイアウト・ペインの位置合せプロパティを使用します。
このトピックでは、ペイン内のノードのサイズ指定と位置合せを行う単純な例を示します。LayoutSizingAligning.java
ファイルには、このトピックで説明するサンプルのソース・コードが含まれています。LayoutSizingAligning.zip
ファイルには、サンプルのNetBeans IDEプロジェクトが含まれています。
ノードのサイズ指定
レイアウトでは、prefWidth(height)
メソッドとprefHeight(width)
メソッドを呼び出すことによって、そのノードの推奨サイズを問い合せます。デフォルトでは、UIコントロールではコントロールのコンテンツに基づいて、その推奨サイズのデフォルト値が計算されます。たとえば、ボタン・オブジェクトの計算されたサイズは、テキストの長さとラベルに使用されるフォントのサイズ、およびイメージのサイズによって決定されます。一般的に、計算されるサイズは、コントロールとラベルを完全に表示できる一番小さい大きさです。
UIコントロールでは、そのコントロールの一般的な用途に基づいたデフォルトの最小および最大サイズも提供されます。たとえば、通常ではボタンを大幅に大きくすることは望まれないため、Button
オブジェクトの最大サイズはデフォルトでその推奨サイズに設定されます。ただし、ScrollPane
オブジェクトの場合、通常ではスペース全体を埋める大きさにすることが望まれるため、その最大サイズは無制限です。
ノードのデフォルトのサイズ制約を使用するか、希望どおりの外観になるようにサイズを設定できます。たとえば、図2-1は、枠線付きペイン内のいくつかのボタンと1つのリスト・ビューのデフォルト・サイズを示しています。
希望する外観が、図2-2に示すように、目的の制約に従ってUIコントロールのサイズが設定された画面であるとします。
アプリケーションでは、多くの場合、コントロールの最小、推奨および最大サイズ制約を直接設定する必要があります。後続の項では、希望する外観にするために、計算されたサイズをオーバーライドするためのヒントを提供します。
ボタンのサイズの同一化
各ボタンの高さと幅を決定してから、各ボタンの推奨サイズをセット内のボタンの最も大きい高さと幅に設定するという手間を省くことができます。より簡単な方法は、レイアウト・ペインでこの作業を行うことです。使用するレイアウト・ペインは、どのような効果を実現するかによって決まります。
VBoxの使用
図2-1のシーンでは、右側のボタンにVBox
レイアウト・ペインが使用され、ボタンの計算されたサイズが使用されています。ボタンの高さはすでに同じであるため、幅のみを変更する必要があります。
図2-2のシーンでは、VBox
ペインを使用して、VBox
ペインの幅を最も幅広い要素の推奨幅と同じにするというデフォルト動作を利用しています。すべてのボタンのサイズをVBox
ペインの幅に変更するには、各ボタンの最大幅をDouble.MAX_VALUE
定数に設定して、コントロールを制限なしで大きくできるようにします。最大値制約の使用にかわる方法は、最大幅を80.0などの特定の値に設定することです。
例2-1は、VBox
ペインを使用して一列のボタンを同じ幅にする方法を示しています。
例2-1 一列のボタンの幅の同一化
BorderPane border = new BorderPane(); border.setPadding(new Insets(20, 0, 20, 20)); Button btnAdd = new Button("Add"); Button btnDelete = new Button("Delete"); Button btnMoveUp = new Button("Move Up"); Button btnMoveDown = new Button("Move Down"); btnAdd.setMaxWidth(Double.MAX_VALUE); btnDelete.setMaxWidth(Double.MAX_VALUE); btnMoveUp.setMaxWidth(Double.MAX_VALUE); btnMoveDown.setMaxWidth(Double.MAX_VALUE); VBox vbButtons = new VBox(); vbButtons.setSpacing(10); vbButtons.setPadding(new Insets(0, 20, 10, 20)); vbButtons.getChildren().addAll(btnAdd, btnDelete, btnMoveUp, btnMoveDown);
レイアウトのサイズ指定と位置合せのサンプルでは、枠線付きペインを使用してUIの要素がレイアウトされています。ボタンの列は枠線付きペインの右側のリージョンに配置され、ボタンのサイズは最も幅の広いボタンの推奨幅に制限されています。枠線付きペインの中央のリージョンは使用可能なスペースをすべて埋めるように拡大されるため、中央のリージョンにVBox
ペインを配置すると、VBox
ペインとボタンも拡大されます。
TilePaneの使用
図2-1のシーンでは、下部のボタンにHBox
レイアウト・ペインが使用され、ボタンの計算されたサイズが使用されています。各ボタンの幅と高さは、それぞれ異なっています。
図2-2のシーンでは、水平方向のTilePane
レイアウト・ペインを使用して、各セル(タイル)を同じサイズにするというデフォルト動作を利用しています。各タイルのサイズは、タイル・ペイン内の最も大きいノードの推奨サイズを確保するために必要なサイズになります。
ボタンをタイルのサイズにサイズ変更するには、最大幅と最大の高さをDouble.MAX_VALUE
定数に設定します。例2-2は、タイル・ペインを使用して一行のボタンの幅と高さを同一にする方法を示しています。
例2-2 一行のボタンのサイズの同一化
Button btnApply = new Button("Apply"); Button btnContinue = new Button("Continue"); Button btnExit = new Button("Exit"); btnExit.setStyle("-fx-font-size: 15pt;"); btnApply.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); btnContinue.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); btnExit.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); TilePane tileButtons = new TilePane(Orientation.HORIZONTAL); tileButtons.setPadding(new Insets(20, 10, 20, 0)); tileButtons.setHgap(10.0); tileButtons.setVgap(8.0); tileButtons.getChildren().addAll(btnApply, btnContinue, btnExit);
ウィンドウがサイズ変更されてもタイルはサイズ変更されないため、ボタンをタイル・ペインに設定した場合、ボタンはサイズ変更されません。ウィンドウの幅が小さくなると、タイル・ペイン内のボタンの位置は変更されますが、サイズは小さくなりません。
推奨サイズでのノードの維持
ステージがサイズ変更されると、そのステージ内のレイアウト・ペインでは、そのペイン内のコントロールに割り当てられるスペースが増減します。各レイアウト・ペインには、コントロールの最小、推奨および最大サイズに従ってスペースを割り当てるための独自のルールがあります。一般的に、デフォルト最大サイズがDouble.MAX_VALUE
であるコントロールはスペース全体に拡大されますが、最大サイズに制約のあるコントロールは拡大されません。たとえば、ListView
オブジェクトの最大値は無制限です。高さを推奨サイズに制限するには、例2-3に示すように、最大サイズをControl.USE_PREF_SIZE
定数に設定します。
例2-3 最大の高さを推奨される高さに設定する
ListView<String> lvList = new ListView<>(); ObservableList<String> items = FXCollections.observableArrayList ( "Hot dog", "Hamburger", "French fries", "Carrot sticks", "Chicken salad"); lvList.setItems(items); lvList.setMaxHeight(Control.USE_PREF_SIZE);
デフォルトでは、ボタンはその推奨サイズまでしか大きくなりません。ただし、最小幅がオーバーライドされていない場合、ボタンはラベルが3つのドット(...)として表示されるまで縮小します。ボタンが推奨幅よりも小さくなることを回避するには、例2-4に示すように、その最小幅をその推奨サイズに設定します。
例2-4 最小幅を推奨幅に設定する
Button btnMoveDown = new Button("Move Down"); btnMoveDown.setMinWidth(Control.USE_PREF_SIZE);
コントロールの推奨サイズは、最初は計算されたサイズに基づいています。推奨サイズ制約を任意のサイズに設定することにより、デフォルト推奨サイズをオーバーライドできます。次の文は、リスト・ビューの推奨幅をオーバーライドします。
lvList.setPrefWidth(150.0);
サイズ変更の回避
ノードがサイズ変更されることを回避する必要がある場合、最小、最大および推奨サイズを同じサイズに設定します。幅または高さのみの変更を回避するには、幅または高さの制約を同じ値に設定します。例2-5では、ウィンドウがサイズ変更されてもリストがサイズ変更されないように、すべてのサイズ制約を同じ幅および高さの値に設定してリストが作成されます。すべての幅の制約が同じ値に設定されて、ボタンが作成されます。
例2-5 サイズ変更を回避するためのサイズ制約の設定
ListView<String> lvList = new ListView<String>(); lvList.setMinSize(150.0, Control.USE_PREF_SIZE); lvList.setMaxSize(150.0, Control.USE_PREF_SIZE); Button btnDelete = new Button("Delete"); btnDelete.setMinWidth(80.0); btnDelete.setPrefWidth(80.0); btnDelete.setMaxWidth(80.0);
コンテンツの位置合せ
各レイアウト・ペインには、ペイン内でノードの位置合せをするデフォルトの方法があります。たとえば、HBox
およびVBox
レイアウト・ペインでは、ノードは上揃えおよび左揃えになります。TilePane
およびFlowPane
レイアウト・ペインでは、ノードは中央揃えになります。デフォルトでは、ペイン自体は通常、上揃えおよび左揃えです。
ペインに対してsetAlignment()
メソッドを使用することにより、ノードとペインの位置合せを管理できます。位置合せの定数は、javafx.geometry
パッケージ内の次のenum
タイプで使用できます。
-
HPos
- 水平方向の位置合せを指定する値。 -
Pos
- 垂直方向および水平方向の位置合せを指定する値。アンダースコアの左側の値は垂直方向の位置合せを指定し、アンダースコアの右側の値は水平方向の位置合せを指定します。たとえば、Pos.BOTTOM_LEFT
は、ノードをスペースの下部に垂直に位置合せし、スペースの左端に水平に位置合せします。 -
VPos
-垂直方向の位置合せを指定する値。
図2-3は、例2-6に示されているコードを使用して作成されます。位置合せの制約を指定しないと、レイアウト・ペインは左上隅に配置されます。
例2-6 デフォルトの位置合せによるUIの作成
GridPane grid = new GridPane(); grid.setHgap(10); grid.setVgap(12); HBox hbButtons = new HBox(); hbButtons.setSpacing(10.0); Button btnSubmit = new Button("Submit"); Button btnClear = new Button("Clear"); Button btnExit = new Button("Exit"); btnSubmit.setStyle("-fx-font-size: 15pt;"); Label lblName = new Label("User name:"); TextField tfName = new TextField(); Label lblPwd = new Label("Password:"); PasswordField pfPwd = new PasswordField(); hbButtons.getChildren().addAll(btnSubmit, btnClear, btnExit); grid.add(lblName, 0, 0); grid.add(tfName, 1, 0); grid.add(lblPwd, 0, 1); grid.add(pfPwd, 1, 1); grid.add(hbButtons, 0, 2, 2, 1); }
希望する外観が、図2-4に示すように、レイアウト・ペインが画面の中央に配置され、コントロールのデフォルトの位置合せが変更された画面であるとします。
後続の項では、デフォルトの位置をオーバーライドするためのヒントを提供します。
列でのコントロールの位置合せ
目的のレイアウトでは、ラベルは右揃えで、フィールドは左揃えです。グリッドでこれを実現するには、ColumnConstraints
クラスを使用して各列を定義し、水平方向の位置合せの制約を設定します。例2-7では、例2-6のグリッドに対する列を定義します。
例2-7 グリッド内の列の定義
GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setHgap(10); grid.setVgap(12); ColumnConstraints column1 = new ColumnConstraints(); column1.setHalignment(HPos.RIGHT); grid.getColumnConstraints().add(column1); ColumnConstraints column2 = new ColumnConstraints(); column2.setHalignment(HPos.LEFT); grid.getColumnConstraints().add(column2);
列でコントロールを右揃えにするかわりの方法は、VBox
レイアウト・ペインを使用することです。次の文に示すように、setAlignment()
メソッドを使用します。
VBox vbox = new VBox; vbox.setAlignment(Pos.CENTER_RIGHT);
ボタンの中央揃え
ボタンは、グリッド内の両方の列にまたがるHBox
レイアウト・ペインにレイアウトされます。次の文は、例2-6のグリッド内のボタンを中央揃えにします。
hbButtons.setAlignment(Pos.CENTER);
HBox
ペインに対するsetAlignment()
メソッドは、レイアウト領域内でHBox
ペインを中央揃えにして、さらにHBox
ペイン内のノードを中央揃えにします。図2-5に示すように、HBox
ペインを行内で中央揃えにしますが、HBox
ペイン内のボタンは下揃えにする必要がある場合があります。
この配置では、単一セルを含む内側のグリッドにHBox
ペインを配置し、そのグリッドを外側のグリッドの3番目の行に配置しています。例2-8に示すように、内側のグリッドに対してグリッドを中央揃えにする位置合せの制約を設定し、HBox
ペインに対してコンテンツを下揃えにする位置合せの制約を設定します。