I have a program that will have a 2D section on the right, and a 3D section on the left. I use a GridPane to have all of the buttons and other stuff laid out, and then the 3D SubScene takes up the entire first column of the GridPane.
However, I am only able to set the size of the SubScene using hard-coded values, but I would like the SubScene to take up the entire width and height of the GridPane cells that it is inside of. Is there a way to do this?
Note: The GridPane's first column (where the subscene is) changes size when the window is resized, hence why I cannot just hard code the values.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.SubScene?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Box?>
<?import javafx.scene.PerspectiveCamera?>
<BorderPane fx:controller="Controller"
xmlns:fx="http://javafx.com/fxml" styleClass="root">
<top>
<MenuBar>
<menus>
<Menu text="File">
<items>
<MenuItem text="New"
onAction="#handleNewSimulationAction" />
<MenuItem text="Save"
onAction="#handleSaveSimulationAction" />
<MenuItem text="Load"
onAction="#handleLoadSimulationAction" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<GridPane hgap="10" vgap="10">
<rowConstraints>
<RowConstraints vgrow="NEVER" />
<RowConstraints vgrow="ALWAYS" />
</rowConstraints>
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" />
</columnConstraints>
<gridLinesVisible>true</gridLinesVisible>
<SubScene fx:id="subscene" width="50" height="50"
GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.rowSpan="6">
<root>
<Region />
</root>
</SubScene>
<Button text="Add" GridPane.columnIndex="1"
GridPane.rowIndex="0" onAction="#handleAddAction" />
<Button text="Edit" GridPane.columnIndex="2"
GridPane.rowIndex="0" onAction="#handleEditAction" />
<Button text="Delete" GridPane.columnIndex="3"
GridPane.rowIndex="0" onAction="#handleDeleteAction" />
<ScrollPane GridPane.columnIndex="1" GridPane.rowIndex="1"
GridPane.columnSpan="3" />
<Label text="Speed" GridPane.columnIndex="1"
GridPane.rowIndex="2" />
<Slider GridPane.columnIndex="2" GridPane.rowIndex="2"
GridPane.columnSpan="2" />
<Label text="Gravity" GridPane.columnIndex="1"
GridPane.rowIndex="3" />
<TextField GridPane.columnIndex="2" GridPane.rowIndex="3"
GridPane.columnSpan="2" />
<HBox GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="<<" onAction="#handleQuickRewindAction" />
<Button text="<" onAction="#handleRewindAction" />
</HBox>
<Text text="0.00" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<HBox GridPane.columnIndex="3" GridPane.rowIndex="4">
<Button text=">" onAction="#handleFastForwardAction" />
<Button text=">>"
onAction="#handleQuickFastForwardAction" />
</HBox>
<Button text="Start" GridPane.columnIndex="2"
GridPane.rowIndex="5" onAction="#handlePauseAction" />
</GridPane>
</center>
<stylesheets>
<URL value="#style.css" />
</stylesheets>
</BorderPane>
The grey square in the image is the SubScene, with hard coded values so that it is visible. If values for the width and height are not hardcoded, it will simply not appear on the screen.
Firstly, there may be other ways as well, but this is my take on this issue :).
I would like to recommend you to rethink about the layout implementation. I think it would be better to keep the right side part in its own gridPane and you primarily deal with only 2 sections (center- subScene and right- form layout). That way you don't unneccesarily mess with layout by keeping too many eggs in one basket.
And regarding the SubScene, it does not fit in any of the standard layouts behavior (like no min/pref/max sizes). It pretty much has the same features as Shape, where you need to explicity set the width/height when required.
So for that, you need to do some explicit calculations to determine the width/height of the SubScene whenever the main scene size is changed.
Below is the quick demo for changes to your code: (If your window is a TRANSPARENT stage, then in the calculations, you may need to consider the window header size as well)
FXML Code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.SubScene?>
<?import javafx.scene.text.Text?>
<?import javafx.geometry.Insets?>
<BorderPane fx:id="mainLayout" fx:controller="Controller" xmlns:fx="http://javafx.com/fxml"
styleClass="root">
<top>
<MenuBar fx:id="menuBar">
<menus>
<Menu text="File">
<items>
<MenuItem text="New"
onAction="#handleNewSimulationAction"/>
<MenuItem text="Save"
onAction="#handleSaveSimulationAction"/>
<MenuItem text="Load"
onAction="#handleLoadSimulationAction"/>
</items>
</Menu>
</menus>
</MenuBar>
</top>
<right>
<GridPane fx:id="sideLayout" hgap="10" vgap="10">
<rowConstraints>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="ALWAYS"/>
</rowConstraints>
<gridLinesVisible>true</gridLinesVisible>
<padding>
<Insets left="10"/>
</padding>
<Button text="Add" GridPane.columnIndex="0" GridPane.rowIndex="0" onAction="#handleAddAction"
prefWidth="-1" minWidth="-Infinity"/>
<Button text="Edit" GridPane.columnIndex="1" GridPane.rowIndex="0"
onAction="#handleEditAction" prefWidth="-1" minWidth="-Infinity"/>
<Button text="Delete" GridPane.columnIndex="2" GridPane.rowIndex="0"
onAction="#handleDeleteAction" prefWidth="-1" minWidth="-Infinity"/>
<ScrollPane GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="3"/>
<Label text="Speed" GridPane.columnIndex="0" GridPane.rowIndex="2"/>
<StackPane GridPane.columnIndex="1" GridPane.rowIndex="2" GridPane.columnSpan="2"/>
<Label text="Gravity" GridPane.columnIndex="0" GridPane.rowIndex="3"/>
<StackPane GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.columnSpan="2"/>
<HBox GridPane.columnIndex="0" GridPane.rowIndex="4">
<Button text="<<" onAction="#handleQuickRewindAction" prefWidth="-1"
minWidth="-Infinity"/>
<Button text="<" onAction="#handleRewindAction" prefWidth="-1" minWidth="-Infinity"/>
</HBox>
<Text text="0.00" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<HBox GridPane.columnIndex="2" GridPane.rowIndex="4">
<Button text=">" onAction="#handleFastForwardAction" prefWidth="-1"
minWidth="-Infinity"/>
<Button text=">>"
onAction="#handleQuickFastForwardAction" prefWidth="-1" minWidth="-Infinity"/>
</HBox>
<Button text="Start" GridPane.columnIndex="1" GridPane.rowIndex="5"
onAction="#handlePauseAction" prefWidth="-1" minWidth="-Infinity"/>
</GridPane>
</right>
<center>
<SubScene fx:id="subscene">
<root>
<StackPane style="-fx-background-color:yellow;-fx-border-width:1px;-fx-border-color:red;">
<Label text="Sub Scene" style="-fx-font-size:16px;"/>
</StackPane>
</root>
</SubScene>
</center>
</BorderPane>
Controller code:
#FXML
private MenuBar menuBar;
#FXML
private SubScene subscene;
#FXML
private GridPane sideLayout;
#FXML
public void initialize() {
subscene.sceneProperty().addListener((ob, ol, scene) -> {
scene.heightProperty().addListener((obs, old, height) -> updateHeight());
scene.widthProperty().addListener((obs, old, width) -> updateWidth());
});
sideLayout.heightProperty().addListener((obs, old, height) -> updateHeight());
sideLayout.widthProperty().addListener((obs, old, width) -> updateWidth());
}
private void updateHeight() {
double sceneHeight = subscene.getScene().getHeight();
subscene.setHeight(sceneHeight - menuBar.getHeight());
}
private void updateWidth() {
double sceneWidth = subscene.getScene().getWidth();
subscene.setWidth(sceneWidth - sideLayout.getWidth());
}
I have a fxml dialog in SceneBuilder, which contains a Gridpane on the right side of a Splitpane contained in a BorderPane. I have two issues with this dialog that relate to each other.
Problem #1 is the width of the last column doesn't behave as
expected, given I set the max width to "USE_COMPUTED_SIZE", Hgrow = "Never" and Fill Width = false.
Problem #2, is that the preview in SceneBuilder differs
from the layout when I run the application.
The layout of the overall dialog is supposed to look like this (I highlighted where the different columns are located):
Regarding problem 1: In order to achieve this layout of the GridPane I have to constraint the max width of the last column to a value of ~60, despite that all of its Nodes, in the different rows, are limited in width. I would expect that this column stays narrow and that column 2 would take all the available space. But if I don't use this explicit max width value, the remaining space is not given to the Combobox but to the last column, which looks like this:
Regarding problem #2: In SceneBuilder the dialog looks like the images above. And if I resize the Splitpane the layout works such that I can continuesly see the buttons in the bottom and the exercise break and total duration information in the top right as long as possible. The Combobox and the table resize accordingly.Nice. However, if I run the application the right side of the Gridpane is cut off and I need to move the Splitpane to the left in order to see the missing nodes:
Here, the fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.media.MediaView?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="1000.0" stylesheets="#application.css" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ctrl.MainCtrl">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#exit" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Sessions">
<items>
<MenuItem mnemonicParsing="false" onAction="#openSessionEditor" text="Open..." />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<SplitPane fx:id="splitPane" dividerPositions="0.5" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" BorderPane.alignment="CENTER">
<items>
<StackPane fx:id="mediaPane" prefHeight="150.0" prefWidth="200.0">
<children>
<MediaView fx:id="mediaView" fitHeight="200.0" fitWidth="200.0" />
<ImageView fx:id="imageView" pickOnBounds="true" preserveRatio="true" StackPane.alignment="CENTER_RIGHT">
<StackPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</StackPane.margin></ImageView>
</children>
</StackPane>
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="0.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="0.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="1.7976931348623157E308" minWidth="0.0" />
<ColumnConstraints fillWidth="false" hgrow="NEVER" minWidth="0.0" />
<ColumnConstraints fillWidth="false" hgrow="NEVER" minWidth="0.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints fillHeight="false" vgrow="NEVER" />
<RowConstraints fillHeight="false" maxHeight="-Infinity" minHeight="10.0" vgrow="NEVER" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="-Infinity" vgrow="ALWAYS" />
<RowConstraints vgrow="NEVER" />
<RowConstraints minHeight="-Infinity" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ComboBox fx:id="sessionComboBox" maxWidth="1.7976931348623157E308" minWidth="0.0" onAction="#sessionSelected" promptText="Select session..." GridPane.columnSpan="3" GridPane.hgrow="ALWAYS">
<GridPane.margin>
<Insets bottom="12.0" left="12.0" right="24.0" top="12.0" />
</GridPane.margin>
</ComboBox>
<TableView fx:id="exerciseTable" editable="true" maxHeight="1.7976931348623157E308" minWidth="0.0" tableMenuButtonVisible="true" GridPane.columnSpan="2147483647" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="selectedColumn" maxWidth="-1.0" minWidth="30.0" prefWidth="30.0" text="Sel" />
<TableColumn fx:id="excerciseColumn" maxWidth="300.0" minWidth="80.0" prefWidth="160.0" sortable="false" text="Exercise" />
<TableColumn fx:id="setsColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Sets" />
<TableColumn fx:id="repsColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Reps" />
<TableColumn fx:id="repBreakColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Break" />
<TableColumn fx:id="introColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Intro" />
<TableColumn fx:id="startSpeedColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="Start Speed" />
<TableColumn fx:id="endSpeedColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="End Speed" />
<TableColumn fx:id="metronomColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="Metronom" />
<TableColumn fx:id="durationColumn" prefWidth="75.0" text="Duration" />
</columns>
<GridPane.margin>
<Insets bottom="6.0" left="12.0" right="24.0" />
</GridPane.margin>
</TableView>
<TextField fx:id="exerciseBreakTextField" maxWidth="40.0" minWidth="0.0" GridPane.columnIndex="4" GridPane.hgrow="NEVER">
<GridPane.margin>
<Insets bottom="12.0" right="30.0" top="12.0" />
</GridPane.margin>
</TextField>
<Label minWidth="0.0" text="Exercise break (sec)" GridPane.columnIndex="3" GridPane.hgrow="NEVER">
<GridPane.margin>
<Insets right="6.0" />
</GridPane.margin>
</Label>
<Label minWidth="0.0" text="Total duration (min)" GridPane.columnIndex="3" GridPane.rowIndex="1">
<GridPane.margin>
<Insets />
</GridPane.margin>
</Label>
<Label fx:id="durationLabel" maxWidth="40.0" text="0" GridPane.columnIndex="4" GridPane.hgrow="NEVER" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="6.0" right="30.0" />
</GridPane.margin>
</Label>
<Button fx:id="tableUpButton" maxHeight="-Infinity" mnemonicParsing="false" onAction="#exerciseUp" prefHeight="20.0" GridPane.hgrow="NEVER" GridPane.rowIndex="1" GridPane.vgrow="NEVER">
<GridPane.margin>
<Insets bottom="6.0" left="12.0" />
</GridPane.margin>
</Button>
<Button fx:id="tableDownButton" maxHeight="-Infinity" mnemonicParsing="false" onAction="#exerciseDown" prefHeight="20.0" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="6.0" left="6.0" />
</GridPane.margin>
</Button>
<HBox nodeOrientation="RIGHT_TO_LEFT" spacing="6.0" GridPane.columnSpan="2147483647" GridPane.hgrow="NEVER" GridPane.rowIndex="3">
<children>
<Button mnemonicParsing="false" onAction="#saveSession" text="Save">
<HBox.margin>
<Insets right="24.0" />
</HBox.margin>
</Button>
<Button minWidth="0.0" mnemonicParsing="false" onAction="#editExercise" prefWidth="50.0" text="Edit" />
<Button minWidth="0.0" mnemonicParsing="false" onAction="#deleteExercise" text="Delete" />
<Button minWidth="0.0" mnemonicParsing="false" onAction="#addNewExercise" prefWidth="50.0" text="Add" />
</children>
<GridPane.margin>
<Insets bottom="12.0" left="12.0" right="24.0" top="6.0" />
</GridPane.margin>
</HBox>
</children>
</GridPane>
</items>
</SplitPane>
</center>
<bottom>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label text="Set:" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="30.0" top="12.0" />
</GridPane.margin>
</Label>
<Label fx:id="setLabel" text="0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="12.0" top="12.0" />
</GridPane.margin>
</Label>
<Label text="Repetition:" GridPane.columnIndex="2" GridPane.rowIndex="1">
<GridPane.margin>
<Insets top="12.0" />
</GridPane.margin></Label>
<Label fx:id="repLabel" text="0" GridPane.columnIndex="3" GridPane.columnSpan="2" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="12.0" top="12.0" />
</GridPane.margin>
</Label>
<Label fx:id="exerciseLabel" styleClass="exercise-header" text="Exercise" GridPane.columnSpan="5">
<GridPane.margin>
<Insets left="24.0" top="12.0" />
</GridPane.margin>
</Label>
<Button fx:id="startStopContinueButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#startStopContinuePressed" styleClass="start-button" text="Start" GridPane.columnSpan="5" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.rowSpan="2" GridPane.vgrow="ALWAYS">
<GridPane.margin>
<Insets bottom="24.0" left="24.0" right="12.0" top="12.0" />
</GridPane.margin>
</Button>
<Slider fx:id="speedSlider" blockIncrement="0.5" majorTickUnit="1.0" max="8.0" showTickLabels="true" showTickMarks="true" GridPane.columnIndex="6" GridPane.hgrow="SOMETIMES" GridPane.rowIndex="2">
<GridPane.margin>
<Insets right="24.0" top="12.0" />
</GridPane.margin>
</Slider>
<Slider fx:id="volumeSlider" majorTickUnit="0.2" max="1.0" showTickMarks="true" value="1.0" GridPane.columnIndex="6" GridPane.hgrow="SOMETIMES" GridPane.rowIndex="3">
<GridPane.margin>
<Insets bottom="24.0" right="24.0" top="12.0" />
</GridPane.margin>
</Slider>
<Label text="Speed" GridPane.columnIndex="5" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="12.0" right="6.0" top="12.0" />
</GridPane.margin>
</Label>
<Label text="Volume" GridPane.columnIndex="5" GridPane.rowIndex="3">
<GridPane.margin>
<Insets bottom="24.0" left="12.0" right="6.0" top="12.0" />
</GridPane.margin>
</Label>
</children>
</GridPane>
</bottom>
</BorderPane>
There is no magic in loading the fxml:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
URL url = getClass().getClassLoader().getResource("ui/MainScene.fxml");
Parent root = FXMLLoader.load(url);
Scene scene = new Scene(root);
primaryStage.setTitle("Sifu says...");
// primaryStage.setFullScreen(true);
// primaryStage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
EDIT:
If I don't set the last column width manually, then the application version does not cut the right side but looks like the 2nd picture.
END_EDIT
What am I doing wrong? Thank you in advance.
Unfortunately, could not find a solution, just a minimal reproducible example for debugging/analysing: I think the behavior might be a bug.
The example below is part of the upper right gridpane in the question. The buttons in its second line are wired to increment/decrement the preferred width of the first column and log the table's pref width (along with its current width).
When run as-is, the initial layout is as expected, that is the last grid column the same as the restricted max of the upper left textField.
incr/dec the pref column width a bit and see that the the table's pref width is at its lower boundary (400 * golden-ratio), so doesn't change
increment further to see the misbehavior (the last grid column increasing): it starts as soon as the table's pref is increasing.
output (the numbers might depend on screen size/resolution):
pref: 247.2135948 actual: 315.3333333333333 // pref at lower boundary
pref: 247.2135948 actual: 315.3333333333333
pref: 247.66666666666669 actual: 315.3333333333333 // incr pref -> last grid column increasing
pref: 248.66666666666669 actual: 316.0
Example code
public class GridPaneTableExtract extends Application {
private Parent createContent() {
GridPane grid = new GridPane();
ObservableList<ColumnConstraints> columnConstraints = grid.getColumnConstraints();
for (int i = 0; i < 5; i++) {
if (i == 2) {
columnConstraints.add(createGrowingColumn());
} else {
columnConstraints.add(createFixedColumn());
}
}
ComboBox<String> combo = new ComboBox<>();
combo.setPromptText("some prompt");
combo.setMaxWidth(Double.MAX_VALUE);
GridPane.setHgrow(combo, Priority.ALWAYS);
GridPane.setFillWidth(combo, true);
Label fieldLabel = new Label("break in seconds: ");
TextField field = new TextField();
field.setPrefColumnCount(2);
field.setMaxWidth(Region.USE_PREF_SIZE);
// first row
grid.add(combo, 0, 0, 3, 1);
grid.add(fieldLabel, 3, 0);
grid.add(field, 4, 0);
Button up = new Button("+");
Button down = new Button("-");
Label durationLabel = new Label("Total Duration");
Label duration = new Label("000");
// second row
grid.add(up, 0, 1);
grid.add(down, 1, 1);
grid.add(durationLabel, 3, 1);
grid.add(duration, 4, 1);
// third row
TableView table = createTable(3);
grid.add(table, 0, 2, 5, 1);
GridPane.setHgrow(table, Priority.ALWAYS);
GridPane.setFillWidth(table, true);
up.setOnAction(e -> {
updateColumnPref(table, 1);
});
down.setOnAction(e -> {
updateColumnPref(table, -1);
});
grid.setGridLinesVisible(true);
BorderPane content = new BorderPane(grid);
return content;
}
private void updateColumnPref(TableView table, double delta) {
TableColumn last = (TableColumn) table.getColumns().get(0);
last.setPrefWidth(last.getPrefWidth() + delta);
System.out.println(" pref: " + table.prefWidth(-1) + " actual: " + table.getWidth());
}
private ColumnConstraints createFixedColumn() {
ColumnConstraints constraint = new ColumnConstraints();
constraint.setHgrow(Priority.NEVER);
constraint.setFillWidth(false);
return constraint;
}
private ColumnConstraints createGrowingColumn() {
ColumnConstraints constraint = new ColumnConstraints();
constraint.setHgrow(Priority.ALWAYS);
constraint.setFillWidth(true);
return constraint;
}
private TableView createTable(int colCount) {
TableView table = new TableView();
for (int i = 0; i < colCount; i++) {
TableColumn column = new TableColumn("column " + i);
table.getColumns().add(column);
}
if (colCount == 4) {
((TableColumn) table.getColumns().get(1)).setPrefWidth(40);
}
return table;
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setX(20);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is an opinionated answer.
I'd get rid of a lot of the hard coding of constraints and use the GridPane minimally, only where it makes sense to align things in a Grid. Otherwise, I would use other layout panes (e.g., VBox, HBox, ButtonBar) with appropriate padding, spacing and alignment values to get the layout required.
Don't use node orientation for layout purposes. The purpose of that setting is described in the documentation:
Node orientation describes the flow of visual data within a node. In the English speaking world, visual data normally flows from left-to-right. In an Arabic or Hebrew world, visual data flows from right-to-left. This is consistent with the reading order of text in both worlds. The default value is left-to-right.
But your app is in English, so you shouldn't change the default node orientation.
The sample below demonstrates the approach I advocate. It is not supposed to be a complete layout for your app, nor to be exactly the layout you want to create for the provided elements (you will need to make adjustments). Nor does it try to solve all issues you raise in your question. Hopefully, it will provide you with a start on how to fix some of your issues by applying the recommended approach.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<VBox spacing="10.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<children>
<GridPane hgap="10.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" />
<ColumnConstraints hgrow="SOMETIMES" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ComboBox fx:id="sessionComboBox" maxWidth="1.7976931348623157E308" promptText="Select session..." />
<Label text="Exercise break (sec)" GridPane.columnIndex="1" />
<TextField fx:id="exerciseBreakTextField" prefColumnCount="2" GridPane.columnIndex="2" />
<HBox spacing="10.0" GridPane.rowIndex="1">
<children>
<Button fx:id="tableUpButton" maxHeight="-Infinity" mnemonicParsing="false" prefHeight="20.0" />
<Button fx:id="tableDownButton" maxHeight="-Infinity" mnemonicParsing="false" prefHeight="20.0" />
</children>
</HBox>
<Label text="Total duration (min)" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label fx:id="durationLabel" text="0" GridPane.columnIndex="2" GridPane.rowIndex="1" />
</children>
</GridPane>
<TableView fx:id="exerciseTable" editable="true" prefWidth="690.0" tableMenuButtonVisible="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="selectedColumn" maxWidth="-1.0" minWidth="30.0" prefWidth="30.0" text="Sel" />
<TableColumn fx:id="excerciseColumn" maxWidth="300.0" minWidth="80.0" prefWidth="160.0" sortable="false" text="Exercise" />
<TableColumn fx:id="setsColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Sets" />
<TableColumn fx:id="repsColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Reps" />
<TableColumn fx:id="repBreakColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Break" />
<TableColumn fx:id="introColumn" maxWidth="-Infinity" minWidth="40.0" prefWidth="40.0" sortable="false" text="Intro" />
<TableColumn fx:id="startSpeedColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="Start Speed" />
<TableColumn fx:id="endSpeedColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="End Speed" />
<TableColumn fx:id="metronomColumn" maxWidth="-Infinity" minWidth="80.0" sortable="false" text="Metronom" />
<TableColumn fx:id="durationColumn" prefWidth="75.0" text="Duration" />
</columns>
</TableView>
<ButtonBar buttonOrder="+U_R">
<buttons>
<Button mnemonicParsing="false" text="Add" />
<Button mnemonicParsing="false" text="Edit" />
<Button mnemonicParsing="false" text="Delete" />
<Button mnemonicParsing="false" text="Save" ButtonBar.buttonData="RIGHT" />
</buttons>
</ButtonBar>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
This is a short two part question: 1. I have designed all the UI for my database in Javafx scene builder 2.0 on a scene size 1920 x 1080; however, I need it to resize based on the screen resolution of the system its operating on. How can this be done?. 2. Second problem which goes hand in hand with the first is all of the controls I have placed in the scene are not staying within the size or location constraints I set. When I preview the scene from the tool everything is correct, but when I run the program everything is out of whack. Any suggestions on what I can do to correct these issues without a complete redesign?
the FXML code:
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.effect.InnerShadow?>
<?import javafx.scene.input.KeyCodeCombination?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<Pane xmlns="http://javafx.com/javafx/8.0.65"xmlns:fx="http://javafx.com/fxml/1" fx:controller="MAAT.MainScreenController">
<children>
<Pane layoutY="-5.0" />
<TabPane fx:id="mainpane" layoutY="35.0" maxHeight="1047.0" maxWidth="1920.0" prefHeight="1047.0" prefWidth="1920.0" side="LEFT" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab fx:id="AHTAtab" text="All Hazard Threat Assessment">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="1009.0" prefWidth="1871.0">
<children>
<TableView fx:id="AHTATable" layoutX="23.0" layoutY="56.0" prefHeight="928.0" prefWidth="1840.0">
<columns>
<TableColumn editable="false" prefWidth="132.0" sortable="false" text="Classification" />
<TableColumn minWidth="0.0" prefWidth="95.0" text="T/H/C" />
<TableColumn editable="false" prefWidth="364.0" sortable="false" text="Category & Capability" />
<TableColumn editable="false" prefWidth="1122.0" sortable="false" text="Rating Definition" />
<TableColumn prefWidth="137.0" text="Rating Score" />
</columns>
<effect>
<InnerShadow />
</effect>
</TableView>
<Button fx:id="AHTAedit" layoutX="1718.0" layoutY="994.0" mnemonicParsing="false" text="Edit" />
<Button fx:id="AHTAdel" layoutX="1785.0" layoutY="994.0" mnemonicParsing="false" text="Delete" />
<AnchorPane layoutX="22.0" layoutY="11.0">
<children>
<Button fx:id="Tbtn" mnemonicParsing="false" text="Threat" />
</children>
</AnchorPane>
<AnchorPane layoutX="107.0" layoutY="11.0">
<children>
<Button fx:id="Hbtn" mnemonicParsing="false" text="Hazard" />
</children>
</AnchorPane>
<AnchorPane layoutX="199.0" layoutY="11.0">
<children>
<Button fx:id="Cbtn" mnemonicParsing="false" prefHeight="39.0" prefWidth="79.0" text="Cyber" />
</children>
</AnchorPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="AAtab" text="Asset Analysis">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TreeView fx:id="AAlist" layoutX="16.0" layoutY="105.0" prefHeight="845.0" prefWidth="583.0">
<effect>
<InnerShadow />
</effect>
</TreeView>
<Label layoutX="16.0" layoutY="14.0" prefHeight="33.0" prefWidth="88.0" text="Asset List: " underline="true" wrapText="true" />
<Button fx:id="Addassetbtn" layoutX="387.0" layoutY="966.0" mnemonicParsing="false" text="Add Assets" />
<Label layoutX="14.0" layoutY="38.0" prefHeight="60.0" prefWidth="587.0" text="Upon selecting the "Add Asset" button and completing the form each asset and its related dependencies will appear below." wrapText="true" />
<Button fx:id="AARemovebtn" layoutX="509.0" layoutY="966.0" mnemonicParsing="false" text="Remove" />
<AnchorPane layoutX="644.0" layoutY="105.0" prefHeight="845.0" prefWidth="1203.0" visible="false">
<children>
<ListView fx:id="Hpairlist" layoutY="645.0" prefHeight="200.0" prefWidth="1203.0">
<effect>
<InnerShadow />
</effect>
</ListView>
<ListView fx:id="Tpairlist" layoutY="402.0" prefHeight="200.0" prefWidth="1203.0">
<effect>
<InnerShadow />
</effect>
</ListView>
<Label layoutY="375.0" text="Paired Threats:" />
<Label layoutY="618.0" text="Paired Hazards:" />
<Separator layoutY="360.0" prefHeight="15.0" prefWidth="1202.0" />
<Label fx:id="AAclassification" alignment="CENTER" layoutX="466.0" layoutY="1.0" prefHeight="27.0" prefWidth="270.0" text="Classification placeholder" textAlignment="CENTER" AnchorPane.bottomAnchor="817.0" AnchorPane.leftAnchor="466.0" AnchorPane.rightAnchor="467.0" AnchorPane.topAnchor="1.0" />
<Label layoutY="70.0" text="Asset Name:" />
<Label layoutX="502.0" layoutY="70.0" text="Unclassified Asset Name:" />
<Label layoutX="999.0" layoutY="70.0" text="Criticality Score:" />
<Label layoutY="111.0" text="Mission:" />
<Label layoutX="1.0" layoutY="225.0" text="Impact Statement:" />
<TextArea fx:id="Amission" editable="false" layoutX="1.0" layoutY="138.0" prefHeight="87.0" prefWidth="1202.0" wrapText="true">
</TextArea>
<TextArea fx:id="Aimpact" layoutY="252.0" prefHeight="99.0" prefWidth="1202.0" />
<Label fx:id="Aname" layoutX="102.0" layoutY="70.0" prefHeight="27.0" prefWidth="393.0" />
<Label fx:id="UAname" layoutX="707.0" layoutY="70.0" prefHeight="27.0" prefWidth="283.0" />
<Label fx:id="Crit" layoutX="1132.0" layoutY="70.0" prefHeight="27.0" prefWidth="65.0" />
</children>
</AnchorPane>
<Separator layoutX="621.0" layoutY="105.0" orientation="VERTICAL" prefHeight="846.0" prefWidth="6.0" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="RATtab" text="Risk Analysis Tool">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="RATtable" layoutX="14.0" layoutY="83.0" prefHeight="902.0" prefWidth="1842.0">
<columns>
<TableColumn editable="false" prefWidth="216.0" text="Threat/Hazard" />
<TableColumn editable="false" minWidth="0.0" prefWidth="313.0" text="Critical Asset" />
<TableColumn editable="false" minWidth="0.0" prefWidth="480.0" sortable="false" text="Observation" />
<TableColumn editable="false" prefWidth="120.0" sortable="false" text="Vul. " />
<TableColumn editable="false" prefWidth="135.0" text="Int. Risk " />
<TableColumn editable="false" prefWidth="370.0" sortable="false" text="Recommendation" />
<TableColumn editable="false" prefWidth="112.0" sortable="false" text="R. Vul" />
<TableColumn editable="false" prefWidth="93.0" text="R. Risk" />
</columns>
<effect>
<InnerShadow />
</effect>
</TableView>
<Button fx:id="Obbtn" layoutX="14.0" layoutY="37.0" mnemonicParsing="false" text="Observation" />
<Button fx:id="RATed" layoutX="1713.0" layoutY="994.0" mnemonicParsing="false" text="Edit" />
<Button fx:id="RATdel" layoutX="1780.0" layoutY="994.0" mnemonicParsing="false" text="Delete" />
<Button fx:id="CRbtn" layoutX="148.0" layoutY="37.0" mnemonicParsing="false" text="Cumulative Risk" />
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
<MenuBar fx:id="MMBar" layoutX="-6.0" layoutY="-5.0" prefHeight="39.0" prefWidth="1927.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="New">
<accelerator>
<KeyCodeCombination alt="UP" code="N" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" text="Open" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Save">
<accelerator>
<KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" text="Save As...">
<accelerator>
<KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="DOWN" shortcut="UP" />
</accelerator>
</MenuItem>
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Import" />
<MenuItem mnemonicParsing="false" text="Export" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Close Window">
<accelerator>
<KeyCodeCombination alt="UP" code="W" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" text="Quit">
<accelerator>
<KeyCodeCombination alt="UP" code="Q" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</Pane>
I'm having this weird behavior when I run my JavaFx app:
As you can see the elements aren't properly aligned. I've created that view using SceneBuilder and there isn't that gap in the editor.
My view is composed of a GridPane. The right cells (on the pic) of the GridPane each contains an HBox, each containing elements (buttons / text fields). I haven't configured anything specific here and am not using any CSS.
Here's the full FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MyController">
<children>
<GridPane hgap="3.0" vgap="3.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" />
<ColumnConstraints hgrow="NEVER" />
<ColumnConstraints hgrow="ALWAYS" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="label1" />
<Label text="label2" GridPane.rowIndex="1" />
<Button defaultButton="true" mnemonicParsing="false" onAction="#handleGo" text="Go!" GridPane.rowIndex="2">
<graphic>
<TextField fx:id="iterations" alignment="CENTER" prefWidth="43.0" style="-fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em;" text="50000" />
</graphic></Button>
<Button fx:id="selectFileButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleFileSelection" text="Select file" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<HBox spacing="3.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="customValue" editable="false" HBox.hgrow="ALWAYS" />
<Button fx:id="deleteButton" mnemonicParsing="false" onAction="#handleDelete" text="Delete" visible="false" />
</children>
</HBox>
<HBox spacing="3.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
<children>
<Button fx:id="editButton" mnemonicParsing="false" text="Edit" />
<Button mnemonicParsing="false" text="New" />
</children>
</HBox>
<ComboBox fx:id="selection" maxWidth="1.7976931348623157E308" onAction="#handleSelection" GridPane.columnIndex="1" />
</children>
</GridPane>
</children>
</AnchorPane>
Am I missing something ?
The default alignment for controls in GridPane (Maybe for controls in general?) is CENTER_LEFT, while for HBox the default is TOP_LEFT. Adding
alignment="CENTER_LEFT"
to your HBox should align them properly.
In my UI, there is a webView and below that is a table to record some actions in the webView. They are placed one below the other. I want the table below to be resizable. The table is fixed to left, right and below borders. User should be able to drag it up. Just like the inspect element opens up a window below the browser and user can drag it up to view more content.
How can I do this in JavaFX? Please help.
Update:
I tried the below:
HBox.setHgrow(table, Priority.ALWAYS);
VBox.setVgrow(table, Priority.ALWAYS);
None of them had any effects. In scenebuilder, I'm binding the table to bottom, left and right borders.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="720.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.controller.RecordController">
<children>
<WebView fx:id="webView" layoutX="80.0" layoutY="48.0" prefHeight="204.0" prefWidth="720.0" AnchorPane.bottomAnchor="156.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="40.0" />
<TableView fx:id="table" editable="true" layoutY="244.0" prefHeight="156.0" prefWidth="626.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<columns>
<TableColumn fx:id="stepDescription" prefWidth="152.0" sortable="false" text="STEP DESCRIPTION" />
<TableColumn fx:id="stepType" prefWidth="85.0" sortable="false" text="STEP TYPE" />
<TableColumn fx:id="pageName" prefWidth="86.0" sortable="false" text="PAGE NAME" />
<TableColumn fx:id="objectName" prefWidth="102.0" sortable="false" text="OBJECT NAME" />
<TableColumn fx:id="actionName" prefWidth="108.0" sortable="false" text="ACTION NAME" />
<TableColumn fx:id="testData" prefWidth="109.0" sortable="false" text="TEST DATA" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<GridPane prefHeight="42.0" prefWidth="579.0">
<children>
<Button fx:id="go" layoutX="261.0" layoutY="20.0" mnemonicParsing="false" prefHeight="32.0" text="Go" AnchorPane.topAnchor="20.0" GridPane.columnIndex="2" />
<TextField fx:id="url" layoutX="97.0" layoutY="20.0" prefHeight="32.0" AnchorPane.topAnchor="20.0" GridPane.columnIndex="1" />
<Label layoutX="56.0" layoutY="24.0" prefHeight="32.0" text="URL" AnchorPane.topAnchor="24.0" GridPane.halignment="RIGHT">
<GridPane.margin>
<Insets right="5.0" />
</GridPane.margin>
</Label>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="101.0" minWidth="0.0" prefWidth="46.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="515.0" minWidth="10.0" prefWidth="483.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="177.0" minWidth="10.0" prefWidth="50.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
<Button fx:id="saveButton" layoutX="663.0" layoutY="5.0" mnemonicParsing="false" onAction="#save" prefHeight="32.0" prefWidth="32.0" AnchorPane.rightAnchor="15.0" />
<Button fx:id="clear" layoutX="634.0" layoutY="5.0" mnemonicParsing="false" onAction="#clear" prefHeight="32.0" prefWidth="32.0" AnchorPane.rightAnchor="55.0" />
<ProgressIndicator fx:id="progress" layoutX="565.0" layoutY="1.0" progress="0.0">
<padding>
<Insets top="10.0" />
</padding>
</ProgressIndicator>
</children>
</AnchorPane>