JavaFX unable to find node declared in FXML at runtime using ID - javafx

Im unable to find a node "VBox" with id "#mainScrollPaneVbox" declared in FXML.
Here is my FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.conuretech.video_assembler.FXMLController">
<top>
<MenuBar prefHeight="16.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleNewAction" text="New" />
<MenuItem mnemonicParsing="false" onAction="#handleOpenProjectAction" text="Open Project" />
<MenuItem mnemonicParsing="false" onAction="#handleSaveAsAction" text="Save As..." />
<MenuItem mnemonicParsing="false" onAction="#handleSaveAction" text="Save..." />
<MenuItem mnemonicParsing="false" onAction="#handleCovertImagesToVideoAction" text="Convert Project To video" />
<MenuItem mnemonicParsing="false" onAction="#handleImportLocalAction" text="Import Local Images" />
<MenuItem mnemonicParsing="false" onAction="#handleImportRemoteAction" text="Import Remote Images" />
<MenuItem mnemonicParsing="false" onAction="#handleExitAction" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Add New Frame From" />
<MenuItem mnemonicParsing="false" text="Delete Current Frame" />
<MenuItem mnemonicParsing="false" text="Edit Frame Properties" />
<MenuItem mnemonicParsing="false" text="Video Properties" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<left>
<ScrollPane id="#mainScrollPane" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<content>
<VBox id="#mainScrollPaneVbox" prefHeight="200.0" prefWidth="200.0" />
</content></ScrollPane>
</left>
<center>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</center>
</BorderPane>
Here is the Java code, that attempts to find the "Vbox" at runtime:
VBox vbox = (VBox) MainApp.scene.lookup("#mainScrollPaneVbox");
I also tried :
VBox vbox = (VBox) MainApp.scene.lookup("mainScrollPaneVbox");
But this still returns null.
Any ideas?
Thanks

Why your code doesn't work
The id attribute in the FXML should contain just the id of the node, not the CSS lookup for the id. In other words, you have
<VBox id="#mainScrollPaneVbox" ... >
when you need
<VBox id="mainScrollPaneVbox" ... >
The lookup should have the CSS lookup:
VBox vbox = (VBox) MainApp.scene.lookup("#mainScrollPaneVbox");
But I would not advise doing things this way anyway, especially since you already have a controller class.
Recommended Approach
CSS lookups are not very robust. They rely on String binding, and are not typesafe. Moreover, any errors will not be caught until the lookup is actually performed, which may be well after the application has been launched (e.g. when the user performs some action).
A better approach is to use #FXML injection. While these still rely on String binding and there is no compile-time type checking, errors will be caught when the FXML file is loaded, so any failures happen much earlier. This makes it much easier to detect and fix errors.
To use #FXML injection you would do
<VBox fx:id="mainScrollPaneVbox"
and then in your controller class:
public class FXMLController {
#FXML
private VBox mainScrollPaneVbox ; // same field name as the fx:id
// ...
public void initialize() {
// popuplate mainScrollPaneVbox ...
// can similarly be accessed in event handlers
// ...
}
// ...
}

Related

TextField textProperty Listener across embedded scenes JavaFX

This may be a little convoluted but please bear with me.
I have 3 scenes built using SceneBuilder. The first ("Main") I am using as the parent scene. This scene contains 1 AnchorPane which holds a TabPane and a ToolBar which holds 3 Buttons ("Previous", "Next" and "Close").
The second scene ("PersonaDetails") contains an AnchorPane, a GridPane a number of Textflow (which I am using as field labels) several TextField and DatePicker. This whole scene is embedded into one of the tabs on the TabPane on the first scene ("Main").
The third scene ("Address") is very similar to the second where it contains an AnchorPane, a GridPane a number of Textflow (which I am using as field labels) several TextField and ComboBox. This whole scene is embedded into the other tab on the TabPane on the first scene ("Main").
(I have included the FXML script for each below)
The application will later include additional scenes on additional tab on the TabPane on the first scene ("Main"). This application will form part of larger application and is meant to be a kind of wizard that allows new clients to be registered.
Furthermore, each FXML file and its Controller are in separate packages.
This issue I am having is that I need to add .textProperty() listeners on several of the Textfield so that I can enable, or disable the "Next" Button on the first, or parent, scene ("Main").
I have tried the following code in the MainController class, but it does not work, although it does not generate any errors.
package com.yas.registrationwizard.main;
import com.yas.registrationwizard.personaldetails.PersonalDetailsController;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.AnchorPane;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
#FXML AnchorPane apMain;
#FXML ToolBar tbMain;
#FXML TabPane tpMain;
#FXML Button btnPrevious;
#FXML Button btnNext;
#FXML Button btnClose;
#Override
public void initialize(URL location, ResourceBundle resources) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../personaldetails/PersonalDetails.fxml"));
try {
fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
PersonalDetailsController personalDetailsController = fxmlLoader.getController();
personalDetailsController.tfFirstName.textProperty().addListener((obs, oldVal, newVal) -> {
if(newVal.equals("")) {
btnNext.setDisable(true);
} else {
btnNext.setDisable(false);
}
});
}
}
The FXML scripts are as follows:
Main
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="apMain" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.main.MainController">
<children>
<ToolBar fx:id="tbMain" layoutX="259.0" layoutY="339.0" prefHeight="40.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="355.0">
<items>
<Pane prefHeight="30.0" prefWidth="370.0" />
<Button fx:id="btnPrevious" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Previous" />
<Button fx:id="btnNext" layoutX="10.0" layoutY="13.0" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Next" />
<Button fx:id="btnClose" layoutX="66.0" layoutY="13.0" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Close" />
</items>
</ToolBar>
<TabPane fx:id="tpMain" layoutX="14.0" layoutY="14.0" prefHeight="335.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<tabs>
<Tab fx:id="tabPersonalDetails" text="Personal Deatils">
<content>
<fx:include fx:id="apPersonalDetails" source="../personaldetails/PersonalDetails.fxml" />
</content></Tab>
<Tab fx:id="tabAddress" text="Address">
<content>
<fx:include fx:id="apAddress" source="../address/Address.fxml" />
</content></Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Address
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="apAddress" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="325.0" prefWidth="590.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.address.AddressController">
<children>
<GridPane fx:id="gpAddress" layoutX="195.0" layoutY="103.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="103.0" minWidth="3.0" prefWidth="82.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="219.0" minWidth="10.0" prefWidth="155.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="422.0" minWidth="10.0" prefWidth="274.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="93.0" minWidth="0.0" prefWidth="78.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="295.0" text="House Name / Number:" GridPane.columnIndex="1" GridPane.rowIndex="2">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin></Label>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="246.0" text="Address Line 1:" GridPane.columnIndex="1" GridPane.rowIndex="3">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin></Label>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="239.0" text="Address Line 2:" GridPane.columnIndex="1" GridPane.rowIndex="4">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin></Label>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Town / City:" GridPane.columnIndex="1" GridPane.rowIndex="5">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin></Label>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="237.0" text="Region / County:" GridPane.columnIndex="1" GridPane.rowIndex="6">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin></Label>
<TextField fx:id="tfHseNameNum" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<TextField fx:id="tfAddLine1" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<TextField fx:id="tfAddLine2" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<TextField fx:id="tfTownCity" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<TextField fx:id="tfRegionCounty" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Postcode:" GridPane.columnIndex="1" GridPane.rowIndex="7">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin>
</Label>
<TextField fx:id="tfPostcode" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Country:" GridPane.columnIndex="1" GridPane.rowIndex="8">
<GridPane.margin>
<Insets right="10.0" />
</GridPane.margin>
</Label>
<ComboBox fx:id="cboCountry" prefHeight="25.0" prefWidth="294.0" GridPane.columnIndex="2" GridPane.rowIndex="8" />
</children>
</GridPane>
</children>
</AnchorPane>
PersonDetails
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="apPersonalDetails" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="325.0" prefWidth="590.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.personaldetails.PersonalDetailsController">
<children>
<GridPane fx:id="gpPersonalDetails" layoutX="195.0" layoutY="103.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="37.0" prefWidth="37.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="236.0" minWidth="10.0" prefWidth="236.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="422.0" minWidth="10.0" prefWidth="277.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="38.0" prefWidth="41.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="tfFirstName" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<TextField fx:id="tfMidNameInit" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<TextField fx:id="tfLastName" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<DatePicker fx:id="dpDoB" prefHeight="25.0" prefWidth="365.0" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<TextField fx:id="tfNatInsNum" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<TextFlow fx:id="tflFirstName" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="2">
<GridPane.margin>
<Insets right="10.0" top="10.0" />
</GridPane.margin></TextFlow>
<TextFlow fx:id="tflLastName" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="4">
<padding>
<Insets right="10.0" top="10.0" />
</padding>
</TextFlow>
<TextFlow fx:id="tflDoB" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="5">
<padding>
<Insets right="10.0" top="10.0" />
</padding>
</TextFlow>
<TextFlow fx:id="tflNatInsNum" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="6">
<padding>
<Insets right="10.0" top="10.0" />
</padding>
</TextFlow>
<TextFlow fx:id="tflMidNameInit" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="3">
<padding>
<Insets right="10.0" top="10.0" />
</padding>
</TextFlow>
</children>
</GridPane>
</children>
</AnchorPane>
The folder structure for the project is shown in the image below:
Firstly, I am bit confused with the wording "scene" in the question. I believe what you mentioned in the question is about handling the nodes, because all the fxmls are handled in the same Scene/Stage.
Anyway, the main problem of the issue lies in the MainController initialize method. You are loading a new instance of PersonalDetailsController and working on it, instead of working on the controller that is actually binded to MainController.
When including fxmls in an fxml, the sub fxml's controller will be already injected to the main fxml controller. So I believe changing your MainController code as below should work as expected.
Update: Sorry for a bit misleading info. The correct thing is, you need to inject the controller with a certain naming convention. If you are including an fxml using fx:include, to get the controller you need to inject with a naming convention <fxid>Controller and <fxid> for getting the node reference.
So considering your example, for the given fx:include line:
<fx:include fx:id="apPersonalDetails" source="../personaldetails/PersonalDetails.fxml" />
your code in MainController should be:
// For controller reference
#FXML PersonalDetailsController apPersonalDetailsController;
// For Node reference
#FXML AnchorPane apPersonalDetails;
So the updated code will be as below:
import com.yas.registrationwizard.personaldetails.PersonalDetailsController;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.AnchorPane;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
#FXML AnchorPane apMain;
#FXML ToolBar tbMain;
#FXML TabPane tpMain;
#FXML Button btnPrevious;
#FXML Button btnNext;
#FXML Button btnClose;
#FXML PersonalDetailsController apPersonalDetailsController;
#Override
public void initialize(URL location, ResourceBundle resources) {
apPersonalDetailsController.tfFirstName.textProperty().addListener((obs, oldVal, newVal) -> {
if(newVal.equals("")) {
btnNext.setDisable(true);
} else {
btnNext.setDisable(false);
}
});
}
}

While making own JOptionPane like class in JavaFX [duplicate]

I get
javafx.fxml.LoadException:
When I'm loading and fxml file using following line of code.
AnchorPane anchorPane = (AnchorPane)loader.load()
This is my fxml file excluding import statements.
<AnchorPane prefHeight="537.0" prefWidth="374.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.buddhikajay.controller.NewTransactionDialogController">
<children>
<GridPane hgap="5.0" layoutX="30.0" layoutY="10.0" prefHeight="544.0" prefWidth="314.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="69.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="226.0" minWidth="10.0" prefWidth="225.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="105.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="156.0" minHeight="10.0" prefHeight="51.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="154.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="160.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="161.0" minHeight="10.0" prefHeight="63.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="301.0" minHeight="10.0" prefHeight="180.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="231.0" minHeight="10.0" prefHeight="106.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<Label text="ID" />
<Label text="Date" GridPane.rowIndex="1" />
<Label text="Amont" GridPane.rowIndex="2" />
<Label text="Person" GridPane.rowIndex="4" />
<Label text="Type" GridPane.rowIndex="3" />
<Label text="Resolved" GridPane.rowIndex="5" />
<Label />
<Label text="Description" GridPane.rowIndex="6" />
<TextField fx:id="idTextField" GridPane.columnIndex="1" />
<TextField fx:id="dateTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextArea fx:id="descriptionTextArea" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="225.0" spacing="20.0" GridPane.columnIndex="1" GridPane.rowIndex="7">
<GridPane.margin>
<Insets />
</GridPane.margin>
<padding>
<Insets bottom="10.0" left="20.0" right="10.0" top="10.0" />
</padding>
<children>
<Button fx:id="okButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#okActionFired" prefHeight="25.0" prefWidth="75.0" text="Ok" />
<Button fx:id="cancleButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#cancleActionFired" prefHeight="25.0" prefWidth="75.0" text="Cancle" />
</children>
</HBox>
<ComboBox fx:id="typeComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<ComboBox fx:id="personComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<ComboBox fx:id="resolvedComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children>
</GridPane>
</children>
</AnchorPane>
The compiler complains that there is an error in line number 1. I'm sure that the path of fxml file is correct. What is wrong with my code?
Here is the full error stack
javafx.fxml.LoadException:
/C:/Users/Buddhika/Documents/Programming/IdeaProjects/VirtualCreditDesktop/out/production/VirtualCreditDesktop/com/buddhikajay/view/NewTransactionDialog.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:928)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:967)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2701)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2521)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at com.buddhikajay.controller.NewTransactionDialogController.showNewTransactionDialog(NewTransactionDialogController.java:68)
at com.buddhikajay.controller.MainApp.start(MainApp.java:51)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$50/1976027283.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/301541210.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/474926796.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1662429848.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/519284171.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InstantiationException: com.buddhikajay.controller.NewTransactionDialogController
at java.lang.Class.newInstance(Class.java:423)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:923)
... 23 more
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.newInstance(Class.java:408)
... 25 more
The problem is described in the stack trace:
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.()
which basically says your controller class doesn't have a zero-argument constructor.
By default, the FXMLLoader will create the controller by calling its zero-argument constructor. Remove the constructor that you have defined in the controller class, or remove the parameters that it takes.
If you really need to pass arguments to the controller's constructor, you can either create the controller in Java code and pass it to the FXMLLoader:
NewTransactionDialogController controller = new NewTransactionDialogController(someValue);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setController(controller);
AnchorPane anchorPane = loader.load();
(Using this code, you must remove the fx:controller attribute from the FXML.)
Or, set a controller factory:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setControllerFactory(clazz -> {
if (clazz == NewTransactionDialogController.class) {
return new NewTransactionDialogController(someValue);
} else {
// default behavior:
try {
return clazz.newInstance();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
});
AnchorPane anchorPane = loader.load();
(In this version, leave the fx:controller attribute in the FXML file.)
I was about to enter a different question as remarked by #James_D for my comment because Until I Read the first line of the FXML on this question, I had thought that I had a different problem.
For my sins, I reduced the challenge to a simple example of a single controller and two FXML files. One worked and the second fail/failed.
The starting point is the Netbeans sample "[Click me!]" sample. The code is pasted below. And, first a solution.
As preamble, let me say that it seems that everyone has been blaming the Java controller for these load errors. I had a bunch of errors like this on a project a couple of years ago. We exhausted "controller" debugging and eventually pressed-forward by re-building the FXML screens with ScendBuilder. I didn't have time to investigate further then.
Last week I perfectly working FXML screen started failing to load because we moved it to a runtime directory (previously it was in the JAR resources area).
KLUNK!
After 3 or 4 days tweaking that and this, I made a comment here on my error:
unknown path: 7
Javafx fxml LoadException: Error resolving onAction='#handleButtonAction', either the event handler is not in the Namespace or there is an error in the script.
On only the "simple.fxml" file, but not the "Scene.fxml" file. The file "simple.fxml" is reduced from the app FXML file that initially gave the problem. There were too many variables on that original file, so chop-chop-chop to match the canned demo.
When you use ONLY this:
xmlns:fx="http://javafx.com/fxml"
FXML load-s from files on disk under in your application folder work just like you want them to (well, like I want, anyway). Looking at the FXML above it is using a more 'fragile' namespace, viz.
Queston's original FXML:
<AnchorPane ...
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" ... >
By using diff, I slowly morphed "simple.fxml" to be as close as possible to "Scene.fxml", and "simple" just keeps failing to load. Please note; always using the same controller
Loading FXML with other metadata has not worked consistently an FXML file was moved. I don't have an explanation as to how this is so.
The FXML is kept in a directory called "test/resources/fxml/simple.fxml" for example. When I was building with both files in the project JAR, the 'same' FXML in both cases loaded and worked as expected. To me there's something un-said about aspects of the file load precess. Again for me, this is undesirable because the KEY value of a external scene definition would be interchange.
These kind of bear traps in XML mark-up that are (apparently) not picked up by development tools like SceneBuilder or the FXMLLoader() are barriers to progress on live projects that don't have slack to investigate esoteric weirdness like this.
This is witnessed by our previous project experience -- I was easier to re-edit a complex screen with SceneBuilder as a whole than track down load problems like this one. The call to action is: Diagnostics on FXML load -- an FXML Lint would be almost a requirement.
Controller, SimpleController.java:
package ex.view.views;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class SimpleController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The failing FXML started life as one of the Maven archetypes (I think) and that file worked fine until I moved the FXML files to a folder and loaded them from a InputStream.
I have formatted the AnchorPane markup on multiple lines for readability.
simple.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ex.view.views.SimpleController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
</children>
</AnchorPane>
The working FXML mark-up is from the Netbeans 8.1 samples.
Scene.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns:fx="http://javafx.com/fxml"
fx:controller="ex.view.views.SimpleController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>

Add elements to a Stage from a different controller

I have a MainInterface.fxml, with its own controller MainController in which a button opens a new Stage from NewCrawler.fxml with its associated controller AddCrawlerController.
It looks fine, but i need to add stuff into the MainInterface using the interface NewCrawler .
The goal is adding a new "itemCrawler" each time someone press the "Start Crawling" button in NewCrawler, like the one hardcoded in MainInterface. How Can I do that?
MainController.java
public class MainController {
#FXML private AnchorPane mainPane;
#FXML
public void addCrawlerInstance(String domain) { //TODO dynamically add itemCrawler (Like the one hardcoded in MainInterface
Button b = new Button(domain); //it is only a try to add elements from a different controller
mainPane.getChildren().add(b);
}
#FXML
private void createCrawler () throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("guifxml/NewCrawler.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
AddCrawlerController.java
public class AddCrawlerController { //ADD Button from Main Interface
#FXML private Button abortButton;
#FXML private Button addCrawlerButton;
#FXML
private void abortCurrentWindow () {
Stage currentStage = (Stage) abortButton.getScene().getWindow();
currentStage.close();
}
#FXML
private void addNewCrawler () throws Exception { //TODO ref. Maincontroller.AddCrawlerInstance
FXMLLoader loader = new FXMLLoader(getClass().getResource("guifxml/MainInterface.fxml"));
Parent root = loader.load();
String d = "prova";
MainController controller = loader.getController();
controller.addCrawlerInstance("prova");
}
}
MainInterface.fxml
<VBox fx:id="mainApp" maxWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wsa.gui.MainController">
<children>
<ButtonBar maxWidth="643.0" nodeOrientation="RIGHT_TO_LEFT" prefHeight="40.0" prefWidth="643.0">
<buttons>
<Button alignment="CENTER" mnemonicParsing="false" text="Set Path" />
<Button alignment="CENTER" mnemonicParsing="false" text="Delete" />
<Button alignment="CENTER" mnemonicParsing="false" text="Stop" />
<Button alignment="CENTER" mnemonicParsing="false" text="Start" />
<Button alignment="CENTER" mnemonicParsing="false" onMouseClicked="#createCrawler" text="Add" />
</buttons>
<VBox.margin>
<Insets />
</VBox.margin>
<padding>
<Insets right="5.0" />
</padding>
</ButtonBar>
<AnchorPane fx:id="mainPane" maxHeight="-1.0" maxWidth="-1.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<Separator layoutY="2.0" prefHeight="3.0" prefWidth="645.0" />
<Pane fx:id="itemCrawler" prefHeight="52.0" prefWidth="645.0">
<children>
<Text layoutX="44.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField editable="false" layoutX="124.0" layoutY="13.0" prefHeight="25.0" prefWidth="319.0" text="http://www.prova.org" />
<Button alignment="CENTER" layoutX="456.0" layoutY="13.0" mnemonicParsing="false" text="Add URI" />
<Button alignment="CENTER" layoutX="528.0" layoutY="13.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0" text="Explore" />
<CheckBox layoutX="14.0" layoutY="18.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="17.0" />
<Separator layoutY="51.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="3.0" prefWidth="645.0" />
</children>
</Pane>
</children>
</AnchorPane>
</children>
</VBox>
NewCrawler.fxml
<AnchorPane fx:controller="wsa.gui.AddCrawlerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea layoutX="119.0" layoutY="89.0" prefHeight="237.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain" wrappingWidth="74.13671875">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField layoutX="119.0" layoutY="32.0" prefHeight="25.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="111.0" strokeType="OUTSIDE" strokeWidth="0.0" text="URI list" textAlignment="CENTER" wrappingWidth="74.13672208786011">
<font>
<Font size="20.0" />
</font>
</Text>
<Text layoutX="119.0" layoutY="85.0" strokeType="OUTSIDE" strokeWidth="0.0" text="one URI on each line " textAlignment="CENTER" wrappingWidth="467.00000166893005" />
<Button fx:id="addCrawlerButton" layoutX="260.0" layoutY="353.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="115.0" onMouseClicked="#addNewCrawler" text="Start Crawling" />
<Button fx:id="abortButton" layoutX="118.0" layoutY="353.0" mnemonicParsing="false" onMouseClicked="#abortCurrentWindow" prefHeight="25.0" prefWidth="115.0" text="Abort" />
</children>
</AnchorPane>
MainInterface
NewCrawler
What I understand is that you need a dynamic list of itemCrawlers.
Instead of hardcoding a newCrawler, you should use a ListView with a custom CellFactory that constructs custom ListCell to represent itemCrawler.
This tutorial tells you how to do that : http://docs.oracle.com/javafx/2/ui_controls/list-view.htm
I am not 100% sure about this, so correct me if I am wrong.
In the NewCrawler's controller you load the FXML in its constructor. Then you can instantiate the NewCrawler controller and work with it as with any other object inside your MainController.

Why I'm getting javafx.fxml.LoadException even the path of the fxml file is correct

I get
javafx.fxml.LoadException:
When I'm loading and fxml file using following line of code.
AnchorPane anchorPane = (AnchorPane)loader.load()
This is my fxml file excluding import statements.
<AnchorPane prefHeight="537.0" prefWidth="374.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.buddhikajay.controller.NewTransactionDialogController">
<children>
<GridPane hgap="5.0" layoutX="30.0" layoutY="10.0" prefHeight="544.0" prefWidth="314.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="69.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="226.0" minWidth="10.0" prefWidth="225.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="105.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="156.0" minHeight="10.0" prefHeight="51.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="154.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="160.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="161.0" minHeight="10.0" prefHeight="63.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="301.0" minHeight="10.0" prefHeight="180.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="231.0" minHeight="10.0" prefHeight="106.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<Label text="ID" />
<Label text="Date" GridPane.rowIndex="1" />
<Label text="Amont" GridPane.rowIndex="2" />
<Label text="Person" GridPane.rowIndex="4" />
<Label text="Type" GridPane.rowIndex="3" />
<Label text="Resolved" GridPane.rowIndex="5" />
<Label />
<Label text="Description" GridPane.rowIndex="6" />
<TextField fx:id="idTextField" GridPane.columnIndex="1" />
<TextField fx:id="dateTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextArea fx:id="descriptionTextArea" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="225.0" spacing="20.0" GridPane.columnIndex="1" GridPane.rowIndex="7">
<GridPane.margin>
<Insets />
</GridPane.margin>
<padding>
<Insets bottom="10.0" left="20.0" right="10.0" top="10.0" />
</padding>
<children>
<Button fx:id="okButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#okActionFired" prefHeight="25.0" prefWidth="75.0" text="Ok" />
<Button fx:id="cancleButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#cancleActionFired" prefHeight="25.0" prefWidth="75.0" text="Cancle" />
</children>
</HBox>
<ComboBox fx:id="typeComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<ComboBox fx:id="personComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<ComboBox fx:id="resolvedComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children>
</GridPane>
</children>
</AnchorPane>
The compiler complains that there is an error in line number 1. I'm sure that the path of fxml file is correct. What is wrong with my code?
Here is the full error stack
javafx.fxml.LoadException:
/C:/Users/Buddhika/Documents/Programming/IdeaProjects/VirtualCreditDesktop/out/production/VirtualCreditDesktop/com/buddhikajay/view/NewTransactionDialog.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:928)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:967)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2701)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2521)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at com.buddhikajay.controller.NewTransactionDialogController.showNewTransactionDialog(NewTransactionDialogController.java:68)
at com.buddhikajay.controller.MainApp.start(MainApp.java:51)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$50/1976027283.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/301541210.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/474926796.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1662429848.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/519284171.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InstantiationException: com.buddhikajay.controller.NewTransactionDialogController
at java.lang.Class.newInstance(Class.java:423)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:923)
... 23 more
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.newInstance(Class.java:408)
... 25 more
The problem is described in the stack trace:
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.()
which basically says your controller class doesn't have a zero-argument constructor.
By default, the FXMLLoader will create the controller by calling its zero-argument constructor. Remove the constructor that you have defined in the controller class, or remove the parameters that it takes.
If you really need to pass arguments to the controller's constructor, you can either create the controller in Java code and pass it to the FXMLLoader:
NewTransactionDialogController controller = new NewTransactionDialogController(someValue);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setController(controller);
AnchorPane anchorPane = loader.load();
(Using this code, you must remove the fx:controller attribute from the FXML.)
Or, set a controller factory:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setControllerFactory(clazz -> {
if (clazz == NewTransactionDialogController.class) {
return new NewTransactionDialogController(someValue);
} else {
// default behavior:
try {
return clazz.newInstance();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
});
AnchorPane anchorPane = loader.load();
(In this version, leave the fx:controller attribute in the FXML file.)
I was about to enter a different question as remarked by #James_D for my comment because Until I Read the first line of the FXML on this question, I had thought that I had a different problem.
For my sins, I reduced the challenge to a simple example of a single controller and two FXML files. One worked and the second fail/failed.
The starting point is the Netbeans sample "[Click me!]" sample. The code is pasted below. And, first a solution.
As preamble, let me say that it seems that everyone has been blaming the Java controller for these load errors. I had a bunch of errors like this on a project a couple of years ago. We exhausted "controller" debugging and eventually pressed-forward by re-building the FXML screens with ScendBuilder. I didn't have time to investigate further then.
Last week I perfectly working FXML screen started failing to load because we moved it to a runtime directory (previously it was in the JAR resources area).
KLUNK!
After 3 or 4 days tweaking that and this, I made a comment here on my error:
unknown path: 7
Javafx fxml LoadException: Error resolving onAction='#handleButtonAction', either the event handler is not in the Namespace or there is an error in the script.
On only the "simple.fxml" file, but not the "Scene.fxml" file. The file "simple.fxml" is reduced from the app FXML file that initially gave the problem. There were too many variables on that original file, so chop-chop-chop to match the canned demo.
When you use ONLY this:
xmlns:fx="http://javafx.com/fxml"
FXML load-s from files on disk under in your application folder work just like you want them to (well, like I want, anyway). Looking at the FXML above it is using a more 'fragile' namespace, viz.
Queston's original FXML:
<AnchorPane ...
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" ... >
By using diff, I slowly morphed "simple.fxml" to be as close as possible to "Scene.fxml", and "simple" just keeps failing to load. Please note; always using the same controller
Loading FXML with other metadata has not worked consistently an FXML file was moved. I don't have an explanation as to how this is so.
The FXML is kept in a directory called "test/resources/fxml/simple.fxml" for example. When I was building with both files in the project JAR, the 'same' FXML in both cases loaded and worked as expected. To me there's something un-said about aspects of the file load precess. Again for me, this is undesirable because the KEY value of a external scene definition would be interchange.
These kind of bear traps in XML mark-up that are (apparently) not picked up by development tools like SceneBuilder or the FXMLLoader() are barriers to progress on live projects that don't have slack to investigate esoteric weirdness like this.
This is witnessed by our previous project experience -- I was easier to re-edit a complex screen with SceneBuilder as a whole than track down load problems like this one. The call to action is: Diagnostics on FXML load -- an FXML Lint would be almost a requirement.
Controller, SimpleController.java:
package ex.view.views;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class SimpleController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The failing FXML started life as one of the Maven archetypes (I think) and that file worked fine until I moved the FXML files to a folder and loaded them from a InputStream.
I have formatted the AnchorPane markup on multiple lines for readability.
simple.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ex.view.views.SimpleController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
</children>
</AnchorPane>
The working FXML mark-up is from the Netbeans 8.1 samples.
Scene.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns:fx="http://javafx.com/fxml"
fx:controller="ex.view.views.SimpleController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>

How to merge cells in JavaFX Scene builder?

I have a gridpane looks like a KeyBoard, and I need to merge some cells to put a "Space" button.. But I cant find any option in the settings of the gridpane which would solve my problem.. Does anyone have an idea how I could achieve it?
Setup your Grid with items in it
Create a GridPane.
Place nodes in the grid.
Select a node in the grid.
It is very, very important that a node in the grid be selected at this stage . . .
After that either:
A. Use the Menu Items
Choose Modify | GridPane
Choose any of
Increase Row Span
Decrease Row Span
Increase Column Span
Decrease Column Span
B. Use the Layout Panel
Modify the Row Span or the Column Span values.
Layout Notes
To really get something to fill up the grid and span rows or columns in the way you want, you may need to modify other layout parameters of the node or it's grid constraints in the layout panel. For example a Button won't normally grow beyond it's preferred size, so set it's max height and width to MAX_VALUE. Another example is to have a Label centered across two columns, set its Hgrow to ALWAYS and its Halignment to CENTER.
Sample Screenshot
There are menu items for setting the Row and Column Span and there are also layout text fields for the same on the far right. Unfortunately, StackOverflow compresses the pic and makes it a little blurry.
Sample FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<children>
<GridPane layoutX="116.0" layoutY="155.0">
<children>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Button" GridPane.columnIndex="0" GridPane.columnSpan="2147483647" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS" />
<Label text="Label" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Label maxWidth="-1.0" text="Label" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="0" />
<Label text="Label" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<Label text="Label" GridPane.columnIndex="1" GridPane.rowIndex="2" GridPane.rowSpan="2" />
<Label text="Label" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<Label text="Label" GridPane.columnIndex="2" GridPane.rowIndex="3" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
</AnchorPane>

Resources