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.