I have a borderpane in my application. In the bottom part i wanted to set a Label to display the current status of the program for example: "ready", "reading data" and so on.
When I start the application the bottom section does not get displayed. Only after I changed the height of the window manually with my mouse it suddenly pops up. Does anyone know why this happens? I suppose it has something to do with my listener.
main
package Sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("View/MainWindow.fxml"));
primaryStage.setTitle("Tool-Name");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?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.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:id="root" prefHeight="453.0" prefWidth="604.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.MainWindow_Controller">
<center>
<TabPane fx:id="tpTabs" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="402.0" prefWidth="604.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab fx:id="tDatabase" text="XXXXXXX">
<content>
<AnchorPane fx:id="apDatabase" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="bSetDBPath" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="XXXXXXX..." />
<Button fx:id="bSetHeadFilePath" layoutX="14.0" layoutY="66.0" mnemonicParsing="false" text="XXXXXXX..." />
<TextField fx:id="tfDBPath" layoutX="138.0" layoutY="14.0" prefHeight="25.0" prefWidth="255.0" promptText="XXXXXXX" />
<TextField fx:id="tfHeadFilePath" layoutX="138.0" layoutY="66.0" prefHeight="25.0" prefWidth="255.0" promptText="XXXXXXX" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="XXXXXXX">
<content>
<Accordion>
<panes>
<TitledPane text="XXXXXXX">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="bGetNewMembers" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="XXXXXXX" />
<Button fx:id="bGetStatusChange" layoutX="14.0" layoutY="58.0" mnemonicParsing="false" text="XXXXXXX" />
<Button fx:id="bRegulation" layoutX="14.0" layoutY="101.0" mnemonicParsing="false" text="XXXXXXX" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane text="XXXXXXX">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="bAdministrationData" layoutX="14.0" layoutY="57.0" mnemonicParsing="false" text="XXXXXXX" />
<Button fx:id="bCompareStatus" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="XXXXXXX" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane text="XXXXXXX">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="bOrganisation" layoutX="14.0" layoutY="103.0" mnemonicParsing="false" text="XXXXXXX" />
<Button fx:id="bDeferredCompensation" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="XXXXXXX" />
<Button fx:id="bCompanyMatching" layoutX="14.0" layoutY="60.0" mnemonicParsing="false" text="XXXXXXX" />
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</content>
</Tab>
<Tab fx:id="tTestCases" text="XXXXXXX">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="tvTestCases" prefHeight="310.0" prefWidth="600.0">
<columns>
<TableColumn fx:id="tcTestCaseId" prefWidth="132.0" text="XXXXXXX">
<cellValueFactory><PropertyValueFactory property="testCaseId" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="tcPaymentId" prefWidth="150.0" text="XXXXXXX">
<cellValueFactory><PropertyValueFactory property="paymentId" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</children>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="tReports" text="XXXXXXX">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="tvReports" prefHeight="310.0" prefWidth="604.0">
<columns>
<TableColumn fx:id="tcReportId" editable="false" prefWidth="75.0" text="XXXXXXX" />
<TableColumn fx:id="tcReportType" editable="false" prefWidth="75.0" text="XXXXXXX" />
<TableColumn fx:id="tcCreationDate" editable="false" prefWidth="75.0" text="XXXXXXX" />
</columns>
</TableView>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</center>
<top>
<MenuBar fx:id="mbMenuBar" prefHeight="30.0" prefWidth="604.0" BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="XXXXXXX">
<items>
<MenuItem mnemonicParsing="false" text="XXXXXXX" />
<MenuItem mnemonicParsing="false" text="XXXXXXX" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="XXXXXXX" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="XXXXXXX">
<items>
<Menu mnemonicParsing="false" text="XXXXXXX">
<items>
<MenuItem fx:id="miNewVoucher" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miNewAssociation" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miNewPensioner" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miNewRegulation" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miNewAdministrationCosts" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miNewPayment" mnemonicParsing="false" text="XXXXXXX" />
</items>
</Menu>
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="miOpenDB" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem fx:id="miImportDatasets" mnemonicParsing="false" text="XXXXXXX" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="miSetDBPath" mnemonicParsing="false" text="XXXXXXX" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="XXXXXXX">
<items>
<MenuItem fx:id="miOpenManual" mnemonicParsing="false" text="XXXXXXX" />
<MenuItem mnemonicParsing="false" text="XXXXXXX" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="miSetManualPath" mnemonicParsing="false" text="XXXXXXX" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<bottom>
<Label fx:id="lInfo" prefHeight="21.0" prefWidth="604.0" text="Bereit" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
Controller
package Controller;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
public class MainWindow_Controller {
@FXML
private BorderPane root;
@FXML
private TableView tvTestCases;
@FXML
private TableView<?> tvReports;
@FXML
MenuBar mbMenuBar;
@FXML
private TabPane tpTabs;
@FXML
private Label lInfo;
/**
* Initialize method to read filepaths and set listeners.
*/
public void initialize() {
tpTabs.setBackground(new Background(new BackgroundFill(Color.BISQUE, null, null)));
loadListener();
lInfo.setText("Bereit");
}
public void loadListener() {
root.widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
tpTabs.setPrefWidth(root.getWidth());
tvTestCases.setPrefWidth(root.getWidth());
tvReports.setPrefWidth(root.getWidth());
}
});
root.heightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
tpTabs.setPrefHeight(root.getHeight() - mbMenuBar.getHeight()-lInfo.getHeight());
tvTestCases.setPrefHeight(root.getHeight() - mbMenuBar.getHeight()-lInfo.getHeight());
tvReports.setPrefHeight(root.getHeight()-mbMenuBar.getHeight()-lInfo.getHeight());
}
});
}
}
Thank you for any help
You shouldn't adjust the preferred sizes of the nodes during layout. What happens here is that the scene size is determined by calculating the preferred/min/max size before the root size is set. When the root size is set the listeners added in loadListener
change the preferred sizes which no longer leaves enough room for all of the nodes. Since the Scene
enforces it's size to be smaller than the actual min size of it's root now, the layouts accomodate to this in a some way, in this case by moving the Label
out of view.
Do not add those listeners and leave the resizing to the BorderPane
. For this to work you need to set the max sizes to sizes other than Region.USE_PREF_SIZE
(= -1d/0d = Double.NEGATIVE_INFINITY
).
The following opening tag for <TabPane>
simply uses the default value (Region.USE_COMPUTED_SIZE
). This way the TabPane
can grow arbitrary large:
<TabPane fx:id="tpTabs" minHeight="-Infinity" minWidth="-Infinity" prefHeight="402.0" prefWidth="604.0" tabClosingPolicy="UNAVAILABLE">