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