Under_stand
Under_stand

Reputation: 69

How to align HBox by using BorderPane alignment in FXML?

What am i trying is to align HBox Buttons to center in the Bottom in dialog box. I want to do this in fxml.However,BorderPane alignment is working in label. Here is code from my side.I think BorderPane.alignment="BOTTOM_CENTER" must work even if the tag is Bottom.

Class file:

package application;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class HBoxDialog extends Application {

@Override
public void start(Stage primaryStage) {
    try {
        Parent root = FXMLLoader.load(getClass().getResource("HBoxDialog.fxml"));
        primaryStage.setScene(new Scene(root, 500, 100));
        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    launch(args);
}
}

FXML file:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1">

<top>
    <Label text="this is dialogbox" BorderPane.alignment="TOP_CENTER"/>
    <font>
        <Font size="35"/>
    </font>
</top>

<bottom>
    <HBox spacing="10">
        <Button text="Okay" prefWidth="90" BorderPane.alignment="BOTTOM_CENTER"/>
        <Button text="Cancel" prefWidth="90" BorderPane.alignment="BOTTOM_CENTER"/>
        <Button text="Help" prefWidth="90" BorderPane.alignment="BASELINE_RIGHT"/>
    </HBox>
</bottom>
</BorderPane>

Upvotes: 4

Views: 5394

Answers (1)

James_D
James_D

Reputation: 209330

The BorderPane.alignment static property only makes sense for nodes whose parent is a BorderPane. The Buttons defined in your FXML file have an HBox as a parent, so setting the BorderPane.alignment property on the buttons will have no effect.

You can achieve the desired effect by centering the buttons within the HBox, simply by using the alignment property of the HBox (which positions the HBox's child nodes within its bounds):

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1">

    <top>
        <Label text="this is dialogbox"
            BorderPane.alignment="TOP_CENTER" />
        <font>
            <Font size="35" />
        </font>
    </top>

    <bottom>
        <HBox spacing="10" alignment="CENTER">
            <Button text="Okay" prefWidth="90" />
            <Button text="Cancel" prefWidth="90" />
            <Button text="Help" prefWidth="90" />
        </HBox>
    </bottom>
</BorderPane>

This gives

enter image description here

The reason that the Label needs BorderPane.alignment="CENTER" but the HBox needs alignment="CENTER" is because they have different resizable ranges, and in particular their max widths are different. The max width of a label, by default, is its preferred width, whereas the max width of an HBox is infinite. You can see this by setting background colors on them both:

    <Label text="this is dialogbox"
        BorderPane.alignment="TOP_CENTER" 
        style="-fx-background-color: aquamarine;"/>

    <!-- ... -->

    <HBox spacing="10" alignment="CENTER"
      style="-fx-background-color: lightskyblue;">

enter image description here

The alignment property positions the content of a node within its bounds. Since the label has no extra space within its bounds for the text to be positioned, with the default settings the alignment property will have no effect. On the other hand, the label is less wide than the top region of the border pane, so there is room to position it within that region. The BorderPane.alignment="CENTER" attribute centers the entire label within the top region of the border pane.

By contrast, the HBox itself already fills the entire width of the bottom region of the border pane. So there is no additional space to align it within that region, and so for the HBox, setting BorderPane.alignment="CENTER" will have no effect. On the other hand, there is more space in the HBox itself than is needed for the buttons, so the buttons (the content of the HBox) can be aligned within the HBox itself using the alignment="CENTER" property of the HBox.

If you want, you can change the max widths to achieve the same effect. For example:

<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.Double?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1">

    <top>
        <Label text="this is dialogbox"
            alignment="CENTER" 
            style="-fx-background-color: aquamarine;">

            <maxWidth>
             <Double fx:constant="MAX_VALUE"/>
            </maxWidth>

        </Label>
        <font>
            <Font size="35" />
        </font>
    </top>

    <bottom>
        <HBox spacing="10" alignment="CENTER"
          style="-fx-background-color: lightskyblue;">
            <Button text="Okay" prefWidth="90" />
            <Button text="Cancel" prefWidth="90" />
            <Button text="Help" prefWidth="90" />
        </HBox>
    </bottom>
</BorderPane>

allows the label to grow (like the default for the HBox), so now its alignment property has the desired effect:

enter image description here

or

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Region?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1">

    <top>
        <Label text="this is dialogbox"
            BorderPane.alignment="CENTER" 
            style="-fx-background-color: aquamarine;" />
        <font>
            <Font size="35" />
        </font>
    </top>

    <bottom>
        <HBox spacing="10" BorderPane.alignment="CENTER"
          style="-fx-background-color: lightskyblue;">

          <maxWidth>
              <Region fx:constant="USE_PREF_SIZE" />
          </maxWidth>

            <Button text="Okay" prefWidth="90" />
            <Button text="Cancel" prefWidth="90" />
            <Button text="Help" prefWidth="90" />
        </HBox>
    </bottom>
</BorderPane>

makes the HBox behave like the button, so now its BorderPane.alignment gives the desired effect:

enter image description here

Upvotes: 7

Related Questions