Making an AnchorPane scrollable - javafx

Following is the fxml I am using for one of the Javafx forms:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="CustomerAddLabel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="683.0" prefWidth="824.0" style="-fx-background-color: aliceblue; -fx-border-color: black; -fx-border-radius: 5;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="c195.View_Controller.CustomerScreenController">
<children>
<Label alignment="TOP_CENTER" layoutX="300.0" layoutY="14.0" prefHeight="38.0" prefWidth="226.0" style="-fx-border-color: gray; -fx-border-radius: 5;" text="Customer" textAlignment="CENTER">
<font>
<Font name="System Bold Italic" size="25.0" />
</font>
</Label>
<AnchorPane layoutX="16.0" layoutY="102.0" prefHeight="404.0" prefWidth="363.0" style="-fx-background-color: white;">
<children>
<TableView fx:id="CustomerTable" layoutY="1.0" style="-fx-border-color: black; -fx-border-radius: 5;">
<columns>
<TableColumn fx:id="CustomerIDColumn" prefWidth="63.0" text="ID" />
<TableColumn fx:id="CustomerNameColumn" prefWidth="175.0" text="Customer Name" />
<TableColumn fx:id="CustomerPhoneColumn" prefWidth="123.0" text="Phone" />
<TableColumn fx:id="CustomerAddressColumn" prefWidth="123.0" text="Address" />
<TableColumn fx:id="CustomerPostalCodeColumn" prefWidth="123.0" text="Postal Code" />
<TableColumn fx:id="CustomerDivisionColumn" prefWidth="123.0" text="Division" />
<TableColumn fx:id="CustomerCountryColumn" prefWidth="123.0" text="Country" />
</columns>
</TableView>
</children>
</AnchorPane>
<ButtonBar layoutX="587.0" layoutY="564.0" prefHeight="40.0" prefWidth="200.0">
</ButtonBar>
<ButtonBar layoutX="500.0" layoutY="613.0" prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button fx:id="CustomerBackButton" mnemonicParsing="false" onAction="#CustomerBackButtonHandler" text="Back" />
<Button fx:id="CustomerDeleteButton" mnemonicParsing="false" onAction="#CustomerDeleteButtonHandler" text="Delete" />
</buttons>
</ButtonBar>
<Label fx:id="CustomerLabel" layoutX="542.0" layoutY="52.0" prefHeight="40.0" prefWidth="90.0" textFill="#1924e8">
<font>
<Font name="System Bold Italic" size="20.0" />
</font>
</Label>
</children>
</AnchorPane>
Following is a snippet of the corresponding controller:
public class CustomerScreenController implements Initializable {
#FXML
private TableView<Customer> CustomerTable;
#FXML
private TableColumn<Customer, String> CustomerIDColumn;
#FXML
private TableColumn<Customer, String> CustomerNameColumn;
#FXML
private TableColumn<Customer, String> CustomerPhoneColumn;
#FXML
private TableColumn<Customer, String> CustomerAddressColumn;
#FXML
private TableColumn<Customer, String> CustomerPostalCodeColumn;
#FXML
private TableColumn<Customer, String> CustomerDivisionColumn;
#FXML
private TableColumn<Customer, String> CustomerCountryColumn;
#FXML
private Button CustomerBackButton;
private Parent root;
private Stage stage;
private ObservableList<Customer> customerOL = FXCollections.observableArrayList();
#Override
public void initialize(URL url, ResourceBundle rb) {
PropertyValueFactory<Customer, String> custCustomerIDFactory = new PropertyValueFactory<>("customerID");
PropertyValueFactory<Customer, String> custNameFactory = new PropertyValueFactory<>("customerName");
PropertyValueFactory<Customer, String> custPhoneFactory = new PropertyValueFactory<>("phone"); //String value "CustomerPhone" calls getCustomerPhone method
PropertyValueFactory<Customer, String> custCountryFactory = new PropertyValueFactory<>("country");
PropertyValueFactory<Customer, String> custDivisionFactory = new PropertyValueFactory<>("division");
PropertyValueFactory<Customer, String> custAddressFactory = new PropertyValueFactory<>("address");
PropertyValueFactory<Customer, String> custPostalCodeFactory = new PropertyValueFactory<>("postalCode");
CustomerIDColumn.setCellValueFactory(custCustomerIDFactory);
CustomerNameColumn.setCellValueFactory(custNameFactory);
CustomerPhoneColumn.setCellValueFactory(custPhoneFactory);
CustomerCountryColumn.setCellValueFactory(custCountryFactory);
CustomerDivisionColumn.setCellValueFactory(custDivisionFactory);
CustomerAddressColumn.setCellValueFactory(custAddressFactory);
CustomerPostalCodeColumn.setCellValueFactory(custPostalCodeFactory);
try {
updateCustomerTableView();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
My UI is appearing like this:
This is appearing cropped. And the full column name Country is not visible. But if I resize it to maximum, then I do see the buttons. How can I make it scrollable? Both the full pane and the TableView inside it so that this issue doesn't appear on the screen.

It looks like you are using AnchorPane incorrectly. I would use VBox or BorderPane. This example uses VBox.
<?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.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="683.0" prefWidth="824.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label alignment="CENTER" prefHeight="38.0" prefWidth="226.0" style="-fx-border-color: gray; -fx-border-radius: 5;" text="Customer" textAlignment="CENTER">
<font>
<Font name="System Bold Italic" size="25.0" />
</font>
<VBox.margin>
<Insets bottom="60.0" top="20.0" />
</VBox.margin>
</Label>
<TableView fx:id="CustomerTable" style="-fx-border-color: black; -fx-border-radius: 5;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="CustomerIDColumn" prefWidth="63.0" text="ID" />
<TableColumn fx:id="CustomerNameColumn" prefWidth="175.0" text="Customer Name" />
<TableColumn fx:id="CustomerPhoneColumn" prefWidth="123.0" text="Phone" />
<TableColumn fx:id="CustomerAddressColumn" prefWidth="123.0" text="Address" />
<TableColumn fx:id="CustomerPostalCodeColumn" prefWidth="123.0" text="Postal Code" />
<TableColumn fx:id="CustomerDivisionColumn" prefWidth="123.0" text="Division" />
<TableColumn fx:id="CustomerCountryColumn" prefWidth="123.0" text="Country" />
</columns>
<VBox.margin>
<Insets left="10.0" right="10.0" />
</VBox.margin>
</TableView>
<ButtonBar>
<buttons>
<Button fx:id="CustomerBackButton" mnemonicParsing="false" onAction="#CustomerBackButtonHandler" text="Back" />
<Button fx:id="CustomerDeleteButton" mnemonicParsing="false" onAction="#CustomerDeleteButtonHandler" text="Delete" />
</buttons>
<VBox.margin>
<Insets bottom="20.0" right="20.0" top="20.0" />
</VBox.margin>
</ButtonBar>
</children>
</VBox>

Related

JavaFx TableView with Pagination

I made an FXML in the Scenebuilder with a Tableview and Pagination.
But I am having trouble to get the pagination to work, especially the PageFactory.
I have following code:
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
Controller:
public void fillTable(int page) {
this.dataModel.setTracksPage(page);
this.table.setItems(FXCollections.observableArrayList(this.dataModel.getTracks().getData()));
this.paginator.setCurrentPageIndex(page);
}
#Override
public void showOverview() {
recordsOverview.setVisible(true);
}
#Override
public void setDataModel(DataModel dataModel) {
if (this.dataModel == null) {
this.dataModel = dataModel;
}
fillTable(1);
paginator.setPageCount(this.dataModel.getTracks().getTotalPages());
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return null; // ???
}
);
}
I just want to fill the table with new data, but returning null gives me errors.
If I return something else like return new BorderPane(table), It doesn't work either, same error.
How can I solve this issue?
Your page factory needs to return the node that will be displayed as the "page". The Pagination will then manage that node and make it part of the scene graph under it. What you want to do is display the TableView in the pagination, so you should return it from the page factory.
You didn't post any of the stack traces from the errors you mention, but I'm guessing that what's happening is that when you return the table, you get an error because the TableView is already part of the scene graph, and nodes can't exist in two different places.
One solution is to omit the table entirely from the FXML, and just define it in the controller (set it up in the initialize() method, then return the reference to it from the page factory).
If you still want it defined in the FXML file, you can define elements in FXML which are not part of the scene graph by wrapping them in a <fx:define> block.
So your FXML would look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<fx:define>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</fx:define>
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
and then you do
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return table;
}
);

Label does not get displayed in javafx

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">

How to set Nodes from FXML JavaFX?

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.

having trouble with javafx program

I am in the process of creating a javafx desktop application. The problem I'm encountering is if I add a controller to my fxml files the controls dissapear somehow. The program uses a fade transition to switch between the fxml files
AnchorPane reorderLevels,purchaseorder,onlineSales,generalLedger
,cashBook,payments,departmentalTransfers
,purchaseInvoice
,productMantainance,
branchTransfers,stockMovement,invoiceRegistration,stockTake;
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#Override
public void initialize(URL url, ResourceBundle rb) {
//load all the fxml screens when the buttons are clicked
try {
//screens for the application
reorderLevels = FXMLLoader.load(getClass().getResource("ReorderLevels.fxml"));
purchaseorder = FXMLLoader.load(getClass().getResource("PurchaseOrder.fxml"));
onlineSales = FXMLLoader.load(getClass().getResource("OnlineSales.fxml"));
generalLedger = FXMLLoader.load(getClass().getResource("GeneralLedger.fxml"));
cashBook = FXMLLoader.load(getClass().getResource("CashBook.fxml"));
departmentalTransfers = FXMLLoader.load(getClass().getResource("DepartmentalTransfers.fxml"));
purchaseInvoice = FXMLLoader.load(getClass().getResource("PurchaseInvoice.fxml"));
productMantainance = FXMLLoader.load(getClass().getResource("ProductMantainance.fxml"));
branchTransfers = FXMLLoader.load(getClass().getResource("BranchTransfers.fxml"));
stockMovement = FXMLLoader.load(getClass().getResource("StockMovement.fxml"));
payments = FXMLLoader.load(getClass().getResource("Payments.fxml"));
invoiceRegistration = FXMLLoader.load(getClass().getResource("InvoiceRegistration.fxml"));
stockTake = FXMLLoader.load(getClass().getResource("StockTake.fxml"));
//set each and every individual node when the buttons are clicked
setNode(reorderLevels);
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void setNode(Node node) {
holderPane.getChildren().clear();
holderPane.getChildren().add((Node) node);
//the transition between the screens
FadeTransition ft = new FadeTransition(Duration.millis(1));
ft.setNode(node);
ft.setFromValue(0.1);
ft.setToValue(1);
ft.setCycleCount(1);
ft.setAutoReverse(false);
ft.play();
}
/* screens */
#FXML
private void switchReorderLevels(ActionEvent event) {
setNode(reorderLevels);
}
#FXML
private void switchOnlineSales(ActionEvent event) {
setNode(onlineSales);
}
#FXML
private void switchGeneralLedger(ActionEvent event) {
setNode(generalLedger);
}
#FXML
private void switchPurchaseOrder(ActionEvent event) {
setNode(purchaseorder);
}
#FXML
private void switchCashBook(ActionEvent event) {
setNode(cashBook);
}
#FXML
private void switchAlert(ActionEvent event) {
setNode(purchaseorder);
}
#FXML
private void switchPayments(ActionEvent event) {
setNode(payments);
}
#FXML
private void switchDepartmentalTransfers(ActionEvent event) {
setNode(departmentalTransfers);
}
#FXML
private void switchPurchaseInvoice(ActionEvent event) {
setNode(purchaseInvoice);
}
#FXML
private void switchProductMantainance(ActionEvent event) {
setNode(productMantainance);
}
#FXML
private void switchBranchTransfers(ActionEvent event) {
setNode(branchTransfers);
}
//this is a screen that will displayone of the layouts that will show re order levels
<AnchorPane id="AnchorPane" prefHeight="713.0" prefWidth="1219.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label layoutX="24.0" layoutY="17.0" prefHeight="30.0" prefWidth="285.0" style="-fx-font-size: 20; -fx-font-weight: bold; -fx-text-fill: #7387A8;" text="ReOrder Levels" />
<Separator layoutX="25.0" layoutY="54.0" prefHeight="5.0" prefWidth="1191.0" />
<Pane fx:id="tbl_reorderLevels" layoutX="25.0" layoutY="108.0" prefHeight="413.0" prefWidth="1174.0" style="-fx-background-color: #EFEFEF;">
<children>
<JFXComboBox fx:id="cmd_reOrder_productCode" layoutX="48.0" layoutY="33.0" prefHeight="25.0" prefWidth="267.0" promptText="Product Code" />
<JFXTextField fx:id="txt_reOrder_reorderLevel" labelFloat="true" layoutX="48.0" layoutY="91.0" prefHeight="25.0" prefWidth="267.0" promptText="Reorder Level" />
//this is the root layout that has buttons that will navigate between the screens using a fade transition
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.effect.InnerShadow?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<!-- root layout -->
<AnchorPane id="AnchorPane" nodeOrientation="LEFT_TO_RIGHT" prefHeight="623.0" prefWidth="1271.0" style="-fx-background-color: #fff;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller = "dashboard.FXMLDocumentController">
<children>
<Pane layoutX="-2.0" prefHeight="81.0" prefWidth="1272.0" style="-fx-background-color: #0b8dee;" styleClass="head-background" stylesheets="#style.css" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="labelEstock" layoutX="204.0" layoutY="-3.0" prefHeight="88.0" prefWidth="536.0" style="-fx-shape: round;" stylesheets="#custom.css" text="Oasys Estock" textFill="WHITE">
<font>
<Font name="Brush Script MT Italic" size="36.0" />
</font>
</Label>
<!-- <ImageView fx:id="imageEstock" fitHeight="110.0" fitWidth="92.0" layoutX="102.0" layoutY="8.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image
url="#../../../../AndroidStudioProjects/OasysEstock/app/src/main/res/drawable/fortified_icon.png" />
</image>
</ImageView> -->
</children>
</Pane>
<VBox layoutY="85.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="518.0" prefWidth="122.0" style="-fx-background-color: #0b8dee; -fx-background-radius: 15;">
<children>
<JFXButton id="btnReorderLevels" fx:id="btnReorderLevels" buttonType="RAISED" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onAction="#switchReorderLevels" prefHeight="47.0" prefWidth="107.0" style="-fx-background-radius: 100;" text="ReOrder Levels" textFill="#f5f0f0">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="Calibri" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnInvoiceRegistration" onAction="#switchInvoiceRegistration" prefHeight="25.0" prefWidth="121.0" text="Invoice Registration" textFill="#f8f4f4" />
<JFXButton fx:id="btnPurchaseOrder" buttonType="RAISED" onAction="#switchPurchaseOrder" prefHeight="34.0" prefWidth="107.0" text="Purchase Order" textFill="#f5f0f0">
<font>
<Font name="Cambria" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnOnlineSales" onAction="#switchOnlineSales" prefHeight="39.0" prefWidth="107.0" text="Online Sales" textFill="#fff9f9">
<font>
<Font name="Calibri" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnGeneralLedger" onAction="#switchGeneralLedger" prefHeight="40.0" prefWidth="108.0" text="General Ledger" textFill="#f2eeee" />
<JFXButton fx:id="btnCashBook" onAction="#switchCashBook" prefHeight="35.0" prefWidth="104.0" text="Cash Book" textFill="#fffefe" />
<JFXButton fx:id="btnPayments" buttonType="RAISED" onAction="#switchPayments" prefHeight="25.0" prefWidth="114.0" text="Payments" textFill="#fcf6f6" />
<JFXButton fx:id="btnDepartmentalTransfers" buttonType="RAISED" layoutX="10.0" layoutY="205.0" onAction="#switchDepartmentalTransfers" prefHeight="25.0" prefWidth="114.0" text="Dept Transfers" textFill="#fcf6f6" />
<JFXButton fx:id="btnProductMantainance" buttonType="RAISED" layoutX="10.0" layoutY="230.0" onAction="#switchProductMantainance" prefHeight="56.0" prefWidth="121.0" text="Product Mantainance" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnPurchaseInvoice" buttonType="RAISED" layoutX="10.0" layoutY="255.0" onAction="#switchPurchaseInvoice" prefHeight="56.0" prefWidth="121.0" text="Purchase Invoice" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnBranchTransfers" buttonType="RAISED" layoutX="10.0" layoutY="311.0" onAction="#switchBranchTransfers" prefHeight="56.0" prefWidth="121.0" text="Branch Transfers" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnStockMovement" buttonType="RAISED" layoutX="10.0" layoutY="367.0" onAction="#switchStockMovement" prefHeight="56.0" prefWidth="121.0" text="Stock Movement" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnStockTake" buttonType="RAISED" layoutX="10.0" layoutY="448.0" onAction="#switchStockTake" prefHeight="56.0" prefWidth="121.0" text="Stock Take" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
</children>
<effect>
<InnerShadow blurType="TWO_PASS_BOX" choke="0.58" color="#212122" height="26.69" radius="10.620000000000001" width="17.79" />
</effect>
</VBox>
<AnchorPane fx:id="holderPane" layoutX="125.0" layoutY="96.0" prefHeight="507.0" prefWidth="1134.0"/>
</children>
</AnchorPane>

JavaFX, SceneBuilder, MenuItem --> Image

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);
//...
//...
}

Resources