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">
Related
When I am loading TabContent.fxml as root scene, and I am running the application, I see on maximizing the window, the textfield size is regrowing as expected, but when I am creating new tab with Tab() and loading TabContent.fxml, on maximising window textfield size not resizing and it is fixed.
LearnFXML.java
package learnfxml;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class LearnFXML extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.input.KeyCodeCombination?>
<?import javafx.scene.layout.VBox?>
<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="learnfxml.FXMLDocumentController">
<children>
<MenuBar VBox.vgrow="NEVER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<Menu mnemonicParsing="false" text="New">
<items>
<MenuItem mnemonicParsing="false" text="Generic" />
<MenuItem fx:id="menuItemNewMSDE" onAction="#openNewMSDETab" text="MSDE">
<accelerator>
<KeyCodeCombination alt="UP" code="N" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
</items>
</Menu>
<MenuItem mnemonicParsing="false" text="Open…" />
<Menu mnemonicParsing="false" text="Open Recent" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Close" />
<MenuItem mnemonicParsing="false" text="Save" />
<MenuItem mnemonicParsing="false" text="Save As…" />
<MenuItem mnemonicParsing="false" text="Revert" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Preferences…" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Quit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Undo" />
<MenuItem mnemonicParsing="false" text="Redo" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Cut" />
<MenuItem mnemonicParsing="false" text="Copy" />
<MenuItem mnemonicParsing="false" text="Paste" />
<MenuItem mnemonicParsing="false" text="Delete" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" text="Select All" />
<MenuItem mnemonicParsing="false" text="Unselect All" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About MyHelloApp" />
</items>
</Menu>
</menus>
</MenuBar>
<TabPane fx:id="tabPane" prefHeight="377.0" prefWidth="640.0" tabClosingPolicy="ALL_TABS" />
</children>
</VBox>
FXMLDocumentController.java
package learnfxml;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.Initializable;
import javafx.scene.control.MenuItem;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
public class FXMLDocumentController implements Initializable {
#FXML private MenuItem menuItemNewMSDE;
#FXML private TabPane tabPane ;
final KeyCombination keyShiftTab = new KeyCodeCombination(KeyCode.TAB, KeyCombination.SHIFT_ANY);
#Override
public void initialize(URL url, ResourceBundle rb) {
}
public void openNewMSDETab() throws IOException
{
int numTabs = tabPane.getTabs().size();
Tab tab = new Tab("Tab "+(numTabs+1));
tabPane.getTabs().add(tab);
tab.setContent((Node) FXMLLoader.load(this.getClass().getResource("TabContent.fxml")));
}
public void initialize(ActionEvent event) {
}
}
TabContent.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="429.0" prefWidth="694.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<VBox layoutX="39.0" layoutY="14.0" prefHeight="30.0" prefWidth="584.0" AnchorPane.leftAnchor="39.0" AnchorPane.rightAnchor="71.0">
<children>
<TextField prefHeight="25.0" prefWidth="641.0" />
</children>
</VBox>
<Label layoutX="14.0" layoutY="20.0" text="URL" />
<Button layoutX="628.0" layoutY="11.0" mnemonicParsing="false" prefHeight="30.0" prefWidth="59.0" text="POST" AnchorPane.rightAnchor="7.0" />
</children>
</AnchorPane>
There are 2 issues here:
The VBox does not grow the TabPane vertically. To fix this you need to set the VBox.vgrow property to ALWAYS
<TabPane fx:id="tabPane" VBox.vgrow="ALWAYS" prefHeight="377.0" prefWidth="640.0" tabClosingPolicy="ALL_TABS" />
You restrict your AnchorPane in TabContent.fxml to the preferred size (USE_PREF_SIZE). Set the max sizes to MAX_VALUE to allow the pane to grow:
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="429.0" prefWidth="694.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
I have created a Layout with FXML which consists of a BorderPane with a sideMenu and an innerBorderPane for other stuff...
But since I'm barely starting with FXML in JavaFX I just need to know how to do the next thing...
Custom.fxml (This is the main FXML layout)
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<VBox fx:controller="Transcoro.Controllers.TabManager" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox prefHeight="59.0" prefWidth="124.0">
<children>
<VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
<VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
<children>
<Label text="Bienvenido, Rodolfo">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Label text="Administrador" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets />
</HBox.margin>
<padding>
<Insets left="10.0" />
</padding>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" />
</VBox.margin>
</HBox>
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
</children>
<padding>
<Insets top="20.0" />
</padding>
</VBox>
sideMenu.fxml (This is the sideMenu FXML layout)
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<fx:root type="javafx.scene.layout.VBox" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox prefHeight="59.0" prefWidth="124.0">
<children>
<VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
<VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
<children>
<Label text="Bienvenido, Rodolfo">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Label text="Administrador" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets />
</HBox.margin>
<padding>
<Insets left="10.0" />
</padding>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" />
</VBox.margin>
</HBox>
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
</children>
<padding>
<Insets top="20.0" />
</padding>
</fx:root>
TabManager.java (This is the sideMenu JavaFX controller)
package Transcoro.Controllers;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;
import java.io.IOException;
public class TabManager extends VBox {
public TabManager(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/sideMenu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
MainLayout.java (This is the mainLayout JavaFX Controller)
package Transcoro.Core;
import Transcoro.Controllers.TabManager;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import java.io.IOException;
public class MainLayout extends BorderPane {
#FXML
private VBox sideMenu;
#FXML
private BorderPane innerContent;
#FXML
private HBox upperMenu;
#FXML
private ScrollPane contentScroll;
#FXML
private VBox otherPane;
public MainLayout(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/Custom.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
TabManager _tabs = new TabManager();
this.setSideMenu(_tabs);
}
What I want to do is the following:
I have two layouts, the base which is the main Layout and sideMenu layout in another FXML
When I instantiate the mainLayout in my root that works fine, then when I want to insert the TabManager (VBox) into sideMenu (VBox from FXML) it doesn't work... I'm doing this:
TabManager _tabs = new TabManager();
this.setSideMenu(_tabs);
The only way I have made it work is by adding:
this.setLeft(this.sideMenu);
OR
this.setLeft(_tabs);
Which I think it shouldn't work that why, because I'm already stating that sideMenu goes on the Left BorderPane side, any idea on how should I approach this?
Firstly, remove fx:controller="Transcoro.Controllers.TabManager" from Custom.fxml. The controller is MainLayout, which you will set via FXMLLoader.
Secondly, don't call fxmlLoader.setRoot(this); in MainLayout. You should instead retrieve the root node out from Custom.fxml, then add it to MainLayout, which itself is a BorderPane.
Parent root = fxmlLoader.getRoot();
this.setCenter(root);
This will put everything from Custom.fxml as the center child of MainLayout.
Thirdly, setLeft() is working because you are setting the TabManager instance (which is a VBox) as the left child of MainLayout. setSideMenu() (which is assumed as the setter of #FXML private VBox sideMenu does not work because sideMenu is just a reference injected into the controller. When you change this reference, it does not change the original layout.
as the title says:
I have a TextField in a CustomMenuItem and the TextField always lost the focus on minimal mouse movement because of the onHover from the MenuItem. In the Source Code from the API i see a protected setHover Method in MenuBarSkin :(
Example:
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
sample.fxml
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</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" />
<CustomMenuItem mnemonicParsing="false" text="Unspecified Action">
<content>
<HBox>
<children>
<Label text="Label" />
<TextField text="Test" />
</children>
</HBox>
</content>
</CustomMenuItem>
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
Ok, i got it:
Its a bit dirty...
Controller.java
public class Controller implements Initializable{
#FXML
TextField txtField;
#Override
public void initialize(URL location, ResourceBundle resources) {
txtField.setOnMouseMoved(event -> {
txtField.requestFocus();
});
}
}
sample.fxml
<BorderPane fx:controller="Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</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" />
<CustomMenuItem mnemonicParsing="false" text="Unspecified Action">
<content>
<HBox>
<children>
<Label text="Label" />
<TextField fx:id="txtField" text="Test" />
</children>
</HBox>
</content>
</CustomMenuItem>
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
This is my Main Class:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("mainmenu.fxml"));
primaryStage.setTitle("Horse Manager");
primaryStage.setScene(new Scene(root,400,600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And I am getting this error:
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException:
/C:/Users/nikit/IdeaProjects/SEPM/out/production/SEPM/sepm/ss17/e1526589/GUI/XMLs/mainmenu.fxml:42
and this is the fxml made with SceneBuilder:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="500" minWidth="500" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sepm.ss17.e1526589.GUI.XMLs.Controllers.MainMenuController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</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>
</top>
<left>
<Accordion BorderPane.alignment="CENTER">
<panes>
<TitledPane prefHeight="200.0" prefWidth="200.0" text="Boxes">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="boxSearch" mnemonicParsing="false" prefWidth="250.0" text="Search" />
<Button fx:id="boxCD" mnemonicParsing="false" prefWidth="250.0" text="Create/Delete Box" />
<Button fx:id="boxUpdate" mnemonicParsing="false" prefWidth="250.0" text="Update Box" />
</children>
</VBox>
</content>
</TitledPane>
<TitledPane animated="false" text="Customers">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="customerSearch" mnemonicParsing="false" prefWidth="250.0" text="Search" />
<Button fx:id="customerCD" mnemonicParsing="false" prefWidth="250.0" text="Customer New/Old" />
<Button fx:id="customerUpdate" mnemonicParsing="false" prefWidth="250.0" text="Update Cutomer" />
</children>
</VBox>
</content>
</TitledPane>
<TitledPane animated="false" text="Reservations">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="reservationsSearch" mnemonicParsing="false" prefWidth="250.0" text="Search" />
<Button fx:id="reservationsCD" mnemonicParsing="false" prefWidth="250.0" text="Create/Delete Reservations" />
<Button fx:id="reservationsUpdate" mnemonicParsing="false" prefWidth="250.0" text="Update Reservations" />
</children>
</VBox>
</content>
</TitledPane>
<TitledPane prefHeight="200.0" prefWidth="200.0" text="Bills">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="billsSearch" mnemonicParsing="false" prefWidth="250.0" text="Search" />
<Button fx:id="billsCD" mnemonicParsing="false" prefWidth="250.0" text="Create/Delete Bills" />
<Button fx:id="billsUpdate" mnemonicParsing="false" prefWidth="250.0" text="Update Bills" />
</children>
</VBox>
</content>
</TitledPane>
<TitledPane prefHeight="200.0" prefWidth="200.0" text="Statistics">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button mnemonicParsing="false" prefWidth="250.0" text="Search" />
<Button mnemonicParsing="false" prefWidth="250.0" text="Create/Delete Box" />
<Button mnemonicParsing="false" prefWidth="250.0" text="Update Box" />
</children>
</VBox>
</content>
</TitledPane>
</panes>
</Accordion>
</left>
<center>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Welcome to Horse Manager" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
my path works and I dont know what else could be wrong the error happens because of the .load function from what I can tell. Please Help
I recently found the google-material-icons and now i want to make my application more good looking using icons. Right now i want to add an image to the application close MenuItem. With SceneBuilder you can just add items, but what i now wanna do is at least still use fxml. I have two questions:
Can I edit the fxml without it being overwritten by scenebuilder again?
how can i add the icon to MenuItems?
Thank you very much. In case you need it, here my FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?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.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<BorderPane fx:id="borderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="#../styles/Styles.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.freakyonline.ucone.FXMLController">
<center>
<TabPane prefHeight="167.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
<tabs>
<Tab closable="false" text="Players">
<content>
<TableView fx:id="playerTable" editable="true" onContextMenuRequested="#handlePTContextMenuRequest" onInputMethodTextChanged="#handleTextChanged" prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn fx:id="nickColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="75.0" text="Nickname" />
<TableColumn fx:id="groupColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="75.0" text="Group" />
<TableColumn fx:id="yearOfBirthColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="94.0" text="Year of Birth" />
<TableColumn fx:id="ageColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="72.0" text="Age" />
<TableColumn fx:id="genderColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="59.0" text="Gender" />
<TableColumn fx:id="lastQuitColumn" onEditCommit="#handlePlayerEditCommit" prefWidth="75.0" text="Last Quit" />
</columns>
<padding>
<Insets bottom="3.0" left="5.0" right="5.0" top="3.0" />
</padding>
</TableView>
</content>
</Tab>
<Tab fx:id="consoleOneTab" closable="false" onSelectionChanged="#handleConsoleOneTabSelected" text="ConsoleOne">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<TextArea fx:id="consoleOneTextArea" editable="false" wrapText="true" VBox.vgrow="ALWAYS" />
<TextField fx:id="consoleOneTextField" alignment="TOP_LEFT" onAction="#handleConsoleOneAction" promptText="type here ..." />
</children>
</VBox>
</content></Tab>
</tabs>
</TabPane>
</center>
<top>
<MenuBar fx:id="mainMenuBar" BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleFileClose" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleHelpAbout" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
Yes, you can add an Image in your MenuItem without affect on fxml.
First, add FX:ID to your menu-item.
<MenuItem fx:id="close_item" mnemonicParsing="false" onAction="#handleFileClose" text="Close" />
Now use setGraphic() method to add an ImageView in your menu-item.
#FXML MenuItem close_item;
#Override
public void initialize(URL url, ResourceBundle rb) {
ImageView menuIcon = new ImageView(new Image("/path/image.png"));
menuIcon.setFitHeight(20);
menuIcon.setFitWidth(20);
close_item.setGraphic(menuIcon);
//...
//...
}