Why I can not use FXML with Controllers and fxid in controller? - javafx

I found here what I need. I need access from 1 Controller to another.
But I have a question. Why when I use FXML annotaion I get exception?
I want to make
public class MainController {
#FXML Tab1Controller tab1Controller;
#FXML Tab2Controller tab2Controller;
#FXML Tab tab1; //THIS
#FXML Tab tab2; // And this call exception. But if i comment both fields is evertying OK.
#FXML public void initialize() {
System.out.println("Application started");
tab1Controller.init(this);
tab2Controller.init(this);
}
public String loadLblTextFromTab1() {
return tab1Controller.lbl1.getText();
}
public void setTab2LabelText(String text) {
tab2Controller.lbl2.setText(text);
}
}
P.S add the XML file where I have that fx:id
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="299.0" prefWidth="309.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
<children>
<TabPane prefHeight="299.0" prefWidth="309.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab closable="false" text="Tab 1">
<content>
<fx:include fx:id="tab1" source="tab/Tab1.fxml" />
</content></Tab>
<Tab closable="false" text="Tab 2">
<content>
<fx:include fx:id="tab2" source="tab/Tab2.fxml" />
</content></Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
PSS.
If I use my FXML and Class like this I will get NullPointerException because of tab1Controller == null
public class MainController {
#FXML Tab tab1;
#FXML Tab1Controller tab1Controller;
#FXML public void initialize() {
tab1Controller.init(this); // Line 15
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="controller.MainController">
<TabPane>
<Tab fx:id="tab1" closable="false" text="Tab 1">
<fx:include source="tab/Tab1.fxml"/>
</Tab>
</TabPane>
</AnchorPane>
Exception looks like
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2566)
... 17 more
Caused by: java.lang.NullPointerException
at controller.MainController.initialize(MainController.java:15)
... 27 more
So, now I can not understand why I get that exception? Anyway I generated my Tab from fxml file itself.

The error message:
Caused by: java.lang.IllegalArgumentException:
Can not set javafx.scene.control.Tab field controller.MainController.tab1 to javafx.scene.layout.AnchorPane
explains what the problem is. The <fx:include> generates an AnchorPane (presumably that is the root element of Tab1.fxml), and you are trying to use a field of type Tab to reference it.
If you only need access to the content of the tab, just change the type of the field accordingly:
public class MainController {
#FXML Tab1Controller tab1Controller;
#FXML Tab2Controller tab2Controller;
#FXML AnchorPane tab1;
#FXML AnchorPane tab2;
#FXML public void initialize() {
System.out.println("Application started");
tab1Controller.init(this);
tab2Controller.init(this);
}
public String loadLblTextFromTab1() {
return tab1Controller.lbl1.getText();
}
public void setTab2LabelText(String text) {
tab2Controller.lbl2.setText(text);
}
}
If you specifically need access to the tabs themselves, then you'll need fx:ids on the Tab. As before, to get a reference to the controller, you need an fx:id on the <fx:include>. So if you want an actual reference to the Tab as well as to the controller, you will need (different) fx:ids on both the Tab and the <fx:include>:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="299.0" prefWidth="309.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
<children>
<TabPane prefHeight="299.0" prefWidth="309.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab fx:id="tab1" closable="false" text="Tab 1">
<content>
<fx:include fx:id="tab1Content" source="tab/Tab1.fxml" />
</content></Tab>
<Tab fx:id="tab2" closable="false" text="Tab 2">
<content>
<fx:include fx:id="tab2Content" source="tab/Tab2.fxml" />
</content></Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
and
public class MainController {
#FXML Tab1Controller tab1ContentController;
#FXML Tab2Controller tab2ContentController;
#FXML Tab tab1;
#FXML Tab tab2;
#FXML public void initialize() {
System.out.println("Application started");
tab1Controller.init(this);
tab2Controller.init(this);
}
public String loadLblTextFromTab1() {
return tab1ContentController.lbl1.getText();
}
public void setTab2LabelText(String text) {
tab2ContentController.lbl2.setText(text);
}
}

Related

Changing the value of comboBox via another controller isn't triggering the onAction callback in JavaFX

Two controllers are there and their respective FXML files.
If I click on the button in View1.fxml, the value of the comboBox is being changed however I am not getting the output in the console.
But if I click on the changeValueOfDemoComboBoxBtn in View2.fxml, the output is printed in the console.
View1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller1">
<children>
<Button fx:id="button" layoutX="187.0" layoutY="120.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Button" />
</children>
</AnchorPane>
View2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller2">
<children>
<Button fx:id="changeValueOfDemoComboBoxBtn" layoutX="200.0" layoutY="264.0" mnemonicParsing="false" onAction="#handleChangeValueOfDemoComboBoxBtnAction" text="Button" />
<ComboBox fx:id="demoComboBox" layoutX="161.0" layoutY="127.0" onAction="#handleDemoComboBox" prefWidth="150.0" />
</children>
</AnchorPane>
Controller1.java
#FXML
private Button button;
#FXML
private void handleButtonAction() throws IOException {
StackPane contentStackPane = (StackPane)mainScene.lookup("#contentStackPane");
FXMLLoader loader = new FXMLLoader(getClass().getResource("view2.fxml));
Parent view2Fxml = loader.load();
Controller2 controller2 = loader.getController();
controller2.setDemoComboBox("Apple");
contentStackPane.getChildren().removeAll();
contentStackPane.getChildren().setAll(view2Fxml );
}
Controller2.java
#FXML
private ComboBox<String> demoComboBox;
#FXML
private Button changeValueOfDemoComboBoxBtn;
#FXML
private void handleDemoComboBox() {
System.out.println("Value changed in Demo ComboBox");
}
#FXML
private void handleChangeValueOfDemoComboBoxBtnAction(){
setDemoComboBox("Oranges");
}
public void setDemoComboBox(String value){
demoComboBox.setValue(value);
}

Passing data from one controller to another in javafx. java.lang.IllegalArgumentException

I am creating a reporting application in which I have 3 scenes with 3 controller classes. My aim is to click on a button (Send Email) from my MaintainanceBacklog_Controller Class, which uses 3 ObservableList from the same controller class and 1 ObservableList from another controller class(BatchProcesses_Controller). I need to pass this one List from BatchProcesses_Controller to my MaintainanceBacklog_Controller. I am getting
Caused by: java.lang.IllegalArgumentException: Can not set reporting.controllers.BatchProcesses_Controller field reporting.controllers.MainScreen_Controller.batchProcesses_Controller to javafx.scene.layout.AnchorPane
I am attaching my code snippets for these three Controller classes + main Class + all three fxml files snippets + Error Stack trace..
Please help. Not able to figure out the issue.
MainScreen_Controller.java
package reporting.controllers;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import reporting.model.BatchProcess_OnlySuccessCount;
import reporting.controllers.BatchProcesses_Controller;
import reporting.controllers.MaintainanceBacklog_Controller;
public class MainScreen_Controller {
#FXML private BatchProcesses_Controller batchProcesses_Controller;
#FXML private MaintainanceBacklog_Controller maintainanceBacklog_Controller;
public void initialize() {
batchProcesses_Controller.init(this);
maintainanceBacklog_Controller.init(this);
}
public ObservableList<BatchProcess_OnlySuccessCount>
getBatchProcessListData() {
return batchProcesses_Controller.data_SuccessCount;
}
}
BatchProcesses_Controller.java
.
.//other #FXML declarations
.
#FXML
private DatePicker datePck_To;
private MainScreen_Controller mainScreen;
#Override
public void initialize(URL location, ResourceBundle resources) {
assert cmbBox_Product != null : "fx:id=\"cmbBox_Product\" was not
injected: check your FXML file 'MaintainanceBacklog_BatchProcesses.fxml'.";
dateCol.setCellValueFactory(new PropertyValueFactory<>("Date"));
...//other column setCellValues here
showGraphCol.setCellValueFactory(new PropertyValueFactory<>
("showGraphBtn"));
}
//injecting main screen controller to this class
public void init(MainScreen_Controller mainScreen_Controller) {
mainScreen = mainScreen_Controller;
}
MaintainanceBacklog_Controller.java
...//other imports
import reporting.util.Maint_ProcessesEnum;
import reporting.controllers.MainScreen_Controller;
public class MaintainanceBacklog_Controller implements Initializable {
...//other FXM`enter code here`L declarations
private MainScreen_Controller main;
#Override
public void initialize(URL location, ResourceBundle resources) {
//other table column setCellValuesFactorys
}
public void onButtonClick_EmailReport() {
EmailGenerator email = new EmailGenerator();
email.setDataInTable(data_after, data_before,data_businessErr,
main.getBatchProcessListData());
}//calling getBatchProcessListData to get the required list
Main.java
public class Main extends Application {private Parent rootNode;
public static void main(String[] args) {
launch(args);
}
#Override
public void init() throws Exception {
FXMLLoader fxmlLoader = new
FXMLLoader(reporting.design.Test.class.getResource("MainScreen.fxml"));
rootNode = fxmlLoader.load();
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("RSA Reporting");
stage.setScene(new Scene(rootNode));
stage.show();
}
MainScreen.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="833.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="reporting.controllers.MainScreen_Controller">
<children>
<TabPane prefHeight="791.0" prefWidth="1046.0">
<tabs>
<Tab text="BatchProcess">
<content>
<fx:include fx:id="batchProcesses_Controller" source="BatchProcesses.fxml" />
</content>
</Tab>
<Tab text="MaintainanceBacklog">
<content>
<fx:include fx:id="maintainanceBacklog_Controller" source="MaintainanceBacklog.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
BatchProcesses.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="batchProcesses" prefHeight="791.0" prefWidth="1046.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="reporting.controllers.BatchProcesses_Controller">
<children>
<Label layoutX="194.0" layoutY="73.0" prefHeight="17.0" prefWidth="82.0" text="Select Process" />
<ComboBox fx:id="cmbBox_Product" layoutX="288.0" layoutY="69.0" prefHeight="25.0" prefWidth="174.0" promptText="Select">
<items>
<FXCollections fx:factory="observableArrayList">
...
MaintainanceBacklog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="maintainanceBacklog" prefHeight="791.0" prefWidth="1046.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="reporting.controllers.MaintainanceBacklog_Controller">
<children>
<ComboBox fx:id="cmbBox_Product_MaintainanceBacklog" layoutX="151.0" layoutY="52.0" prefHeight="25.0" prefWidth="313.0" promptText="Select">
<items>
<FXCollections fx:factory="observableArrayList">
...
ErrorStackTrace
log4j:WARN No appenders could be found for logger (reporting.util.Util).
log4j:WARN Please initialize the log4j system properly.
Apr 20, 2018 3:37:16 PM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 8.0.141 by JavaFX runtime of version 8.0.122-ea
Apr 20, 2018 3:37:16 PM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 8.0.141 by JavaFX runtime of version 8.0.122-ea
Exception in Application init method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application init method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:912)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Unknown Source)
Caused by: javafx.fxml.LoadException:
/C:/SyntBotsServices/ProductionReporting/bin/reporting/design/MainScreen.fxml:13
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at application.Main.init(Main.java:72)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:841)
... 2 more
Caused by: java.lang.IllegalArgumentException: Can not set reporting.controllers.BatchProcesses_Controller field reporting.controllers.MainScreen_Controller.batchProcesses_Controller to javafx.scene.layout.AnchorPane
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source)
at java.lang.reflect.Field.set(Unknown Source)
at javafx.fxml.FXMLLoader.injectFields(FXMLLoader.java:1163)
at javafx.fxml.FXMLLoader.access$1600(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$ValueElement.processValue(FXMLLoader.java:857)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:751)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 6 more
Exception running application application.Main
Since the root element of BatchProcesses.fxml is a <AnchorPane> element, an AnchorPane is created for the following line.
<fx:include fx:id="batchProcesses_Controller" source="BatchProcesses.fxml" />
The field in your controller corresponding to the value of the fx:id attribute is
#FXML private BatchProcesses_Controller batchProcesses_Controller;
FXMLLoader fails to assign a AnchorPane to a field of type BatchProcesses_Controller for obvious reasons.
If you need the controller of the included fxml to be assigned to a controller field, you need to use append Controller to the fx:id of the <fx:include>:
#FXML private AnchorPane batchProcesses_Controller;
#FXML private BatchProcesses_Controller batchProcesses_ControllerController;

JavaFx: multiple controllers

I'm working on the project which contains multiple controllers (1 main and two for each of the Fxml files). Unfortunately while running the program, console throw the NullPointerExeption at me. I found out that it's the main controller fault, but still having this information I'm unable to fix this. Could you give me some tips how to solve this issue ?
Here i got the full track:
MainController class:
public class MainController {
#FXML LogInController logInController;
DBConnect dbConnect;
#FXML FlightControlController flightControlController;
#FXML public void initialize() {
logInController.initialize(this);
flightControlController.initialize(this);
dbConnect.initialize(this);
}
}
DBConnect class:
public void dbConnect() throws SQLException {
try {
Conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/nasa", "root", "1234");
} catch(Exception e) {
System.out.println(e.getStackTrace());
}
}
public boolean isCorrect(String login,String password) throws SQLException, IOException {
Stmt = Conn.createStatement();
Rs = Stmt.executeQuery("SELECT * FROM Users WHERE login='"+login+"'AND password='"+password+"';");
if(Rs.next()) {
return true;
} else {
return false;
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
LogInController class:
MainController mainController;
#FXML DBConnect dbConnect;
#FXML TextField logginField = null;
#FXML PasswordField passwordFiled=null;
#FXML Button logInButton;
#FXML
public void buttonClicked(ActionEvent event) throws SQLException, IOException {
mainController.dbConnect.dbConnect();
if(mainController.dbConnect.isCorrect(logginField.getText(),passwordFiled.getText())) {
Parent root = FXMLLoader.load(getClass().getResource("/view/FlightControlView.fxml"));
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} else {
System.out.print("An error have occured");
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
FlightControlController Class:
#FXML Label label;
MainController mainController;
public void initialize(MainController mainController) {
this.mainController = mainController;
}
And the error which occurs:
Caused by: java.lang.NullPointerException at
controller.LogInController.buttonClicked(LogInController.java:31) ...
62 more
I'm not sure but is it possible that MainController (which doesn't have his own Fxml file) so that FXMLLoader doesn't initialize MainController's properties?
#EDIT
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="693.0" prefWidth="1062.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.LogInController">
<children>
<SplitPane dividerPositions="0.21320754716981133" layoutX="331.0" layoutY="220.0" prefHeight="693.0" prefWidth="1062.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Label alignment="CENTER" layoutY="-1.0" maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="222.0" text="NASA DATABASE" />
<TextField fx:id="logginField" layoutX="18.0" layoutY="101.0" promptText="Login" />
<PasswordField fx:id="passwordFiled" layoutX="18.0" layoutY="165.0" promptText="Password" />
<Button fx:id="logInButton" onAction="#buttonClicked" layoutX="79.0" layoutY="230.0" mnemonicParsing="false" text="Log In" />
</children>
</AnchorPane>
<AnchorPane prefHeight="691.0" prefWidth="493.0" SplitPane.resizableWithParent="false">
<children>
<Label alignment="CENTER" layoutX="97.0" layoutY="104.0" prefHeight="417.0" prefWidth="635.0" text="NOT AVAILABLE, PLEASE LOG IN" AnchorPane.leftAnchor="113.0" AnchorPane.rightAnchor="113.0">
<font>
<Font name="System Bold Italic" size="37.0" />
</font>
</Label>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>

JAVAFX - Change specific Pane only using 1 window

Can you Help me how to change the Spesific pane in 1 scene.
So when i want to click the Menu A. The Content will change to content A.
And when i click the menu B. The Content will be change to Content B
i try with the 2 FXML and using normal method like load screen A an screen B
But the result only change the window. i want to change the content with 1 window only.
Is there any suggestion how to change the specific pane in 1 window?
As an option.
Make FXML and controller for any "Content" and when the some button is clicked to delete the old "Content" and upload new.
Working example below (edited according to James_D comment):
Main.java
public class Main extends Application {
Parent root;
Stage stage;
#Override
public void start(Stage primaryStage) {
try {
root = FXMLLoader.load(getClass().getResource("Main.fxml"));
stage = primaryStage;
stage.setTitle("Stage");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane fx:id="mainPane" 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="application.Controller">
<left>
<ToolBar orientation="VERTICAL" BorderPane.alignment="CENTER">
<items>
<Button mnemonicParsing="false" onAction="#onBtnAClick" text="A" />
<Button mnemonicParsing="false" onAction="#onBtnBClick" text="B" />
<Button mnemonicParsing="false" onAction="#onBtnCClick" text="C" />
</items>
</ToolBar>
</left>
</BorderPane>
Controller.java
import javafx.fxml.FXML;
import javafx.scene.layout.BorderPane;
public class Controller {
#FXML
BorderPane mainPane;
#FXML
public void onBtnAClick(){
ContentA contentA = new ContentA();
mainPane.setCenter(contentA);
}
#FXML
public void onBtnBClick(){
ContentB contentB = new ContentB();
mainPane.setCenter(contentB);
}
#FXML
public void onBtnCClick(){
ContentC contentC = new ContentC();
mainPane.setCenter(contentC);
}
}
And some sample of Content:
ContentA.java
public class ContentA extends AnchorPane{
public ContentA(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ContentA.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ContentA.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root prefHeight="200.0" prefWidth="300.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ListView layoutX="50.0" layoutY="-26.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</fx:root>
try to use this, its easy
Parent root = null;
try {
root=FXMLLoader.load(getClass().getResource("your_FXML_File.fxml"));
} catch (Exception e) {
}
borderpane.setCenter(root);

JavaFX. Communication between controllers

Hello I'm starting in JavaFX and I've got some problems.
I want to communicate two controlles from two diferents views. How can I do it?
I'm working with tabs and i have this two controllers and i want to do something similar like this:
Application.java:
public class JavaFXApplication6 extends Application
{
#Override
public void start(Stage primaryStage)
{
try
{
Parent root = FXMLLoader.load(getClass().getResource(
"/view/FXML_Main.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e){
e.printStackTrace();
}
primaryStage.setTitle("Back-end GUI");
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
FXML_Main.fxml:
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0"
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"
fx:controller="controller.FXML_MainController">
<children>
<TabPane layoutX="61.0" layoutY="30.0" prefHeight="400.0" prefWidth="600.0"
tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<tabs>
<Tab text="Untitled Tab 1">
<content>
<fx:include source="FXML_Tab1.fxml" />
</content>
</Tab>
<Tab text="Untitled Tab 2">
<content>
<fx:include source="FXML_Tab2.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
FXML_MainController.java:
public class FXML_MainController implements Initializable {
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
FXML_Tab1.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="400.0" prefWidth="600.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="controller.FXML_Tab1Controller">
<children>
<Label fx:id="Label1" layoutX="282.0" layoutY="108.0" text="Label" />
<TextField fx:id="FextField1" layoutX="215.0" layoutY="146.0" />
<Button fx:id="Button1" layoutX="269.0" layoutY="197.0" mnemonicParsing="false"
onAction="#actionButton1" text="Button" />
</children>
</AnchorPane>
FXML_Tab1Controller.java:
public class FXML_Tab1Controller implements Initializable {
FXML_Tab2Controller tab2controller;
#FXML public Label Label1;
#FXML public TextField TextField1;
#FXML public Button Button1;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML private void actionButton1(ActionEvent event)
{
Label1.setText(tab2controller.TextField2.getText());
}
}
FXML_Tab2.fxml:
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="controller.FXML_Tab2Controller">
<children>
<Label fx:id="Label2" layoutX="282.0" layoutY="99.0" text="Label" />
<TextField fx:id="TextField2" layoutX="215.0" layoutY="149.0" />
<Button fx:id="Button2" layoutX="270.0" layoutY="200.0" mnemonicParsing="false"
onAction="#actionButton2" text="Button" />
</children>
</AnchorPane>
FXML_Tab2Controller.java:
public class FXML_Tab2Controller implements Initializable {
FXML_Tab1Controller tab1controller;
#FXML public Label Label2;
#FXML public TextField TextField2;
#FXML public Button Button2;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML private void actionButton2(ActionEvent event){
Label2.setText(tab1controller.TextField1.getText());
}
}
something similar like that video:
https://www.youtube.com/watch?v=XLVx46ycxco
Add an fx:id to each of your <fx:include> tags:
<tabs>
<Tab text="Untitled Tab 1">
<content>
<fx:include source="FXML_Tab1.fxml" fx:id="tab1" />
</content>
</Tab>
<Tab text="Untitled Tab 2">
<content>
<fx:include source="FXML_Tab2.fxml" fx:id="tab2" />
</content>
</Tab>
</tabs>
This will allow you to inject the corresponding controllers into your FXML_MainController:
public class FXML_MainController {
#FXML
private FXML_Tab1Controller tab1Controller ;
#FXML
private FXML_Tab2Controller tab2Controller ;
}
The variable naming is very important here: the fields must be named xController where x is the value for the fx:id attribute in the fx:include. See the Introduction to FXML documentation for details.
Now in your main controller's initialize() method, you can establish the relationship between the two controllers:
public class FXML_MainController {
#FXML
private FXML_Tab1Controller tab1Controller ;
#FXML
private FXML_Tab2Controller tab2Controller ;
public void initialize() {
tab1Controller.tab2Controller = tab2Controller ;
tab2Controller.tab1Controller = tab1Controller ;
}
}

Resources