I'm currently looking into the easiest way to save my SQL Connection within my JavaFX project in order to use it in all of my Controllers. Since I'm creating the Controller in a SideBar FXML file it is not possible to pass the Object from one Controller to the other.
Therefore I wanted to use the Node.setUserData() method and just save the Connection Object to the root node. Unfortunately I get NullPointers when I want to call it.
Saving it works fine:
myStage.getScene().getRoot().setUserData(con);
And calling it from the same stage variable works fine as well:
... = (Connection) myStage.getScene().getRoot().getUserData();
But I'm accessing the stage within my Sidebar.fxml via
Stage stage = (Stage) myButton.getScene().getWindow();
what then leads to NullPointers while accessing the UserData via
stage.getScene().getRoot().getUserData();
I see that the reason for this is, that it is not the "exact same" stage variable. But it has to be the same stage (when I display a new view there it is displayed on the same stage as before).
How can I find the exact same Node I've saved the UserData before? Or is there a way to access the same Node from another context where I do not have the stage?
EDIT: I've put a MCVE here to show what my Problem is: https://github.com/lud-hu/myJavaFxMcve/ EDIT: Code is working in Github now, I'll post the Code with the initial problem here:
MyMcveStarter.java
package myMcve;
import myMcve.controller.LoginController;
import javafx.application.Application;
import javafx.stage.Stage;
public class MyMcveStarter extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
LoginController controller = new LoginController(primaryStage);
controller.displaySceneOn(primaryStage);
}
}
LoginController.java
package myMcve.controller;
import myMcve.view.LoginSceneView;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class LoginController {
private LoginSceneView view;
private Parent scene;
Stage myStage;
String defaultUrl;
String defaultName;
String defaultPassword;
public LoginController(Stage stage) {
defaultUrl = "jdbc:mysql://localhost:3306/db";
defaultName = "root";
defaultPassword = "localhost";
myStage = stage;
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../view/LoginScene.fxml"));
try {
scene = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
view = loader.getController();
}
public void displaySceneOn(Stage stage) {
stage.setTitle("login");
Scene myScene = new Scene(scene, 1250, 650);
stage.setScene(myScene);
stage.show();
try {
initializeDbConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void initializeDbConnection() throws SQLException {
try {
DriverManager.setLoginTimeout(15);
Connection con = DriverManager.getConnection(defaultUrl, defaultName, defaultPassword);
UserManagementController controller = new UserManagementController(myStage, con);
controller.displaySceneOn(myStage);
} catch (Exception e) {
}
}
}
SideBarController.java
package myMcve.controller;
import myMcve.controller.LevelManagementController;
import myMcve.controller.LoginController;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class SideBarController{
@FXML
private Button levelManBtn;
public Button getLevelManBtn() {
return levelManBtn;
}
@FXML
private void levelMan(ActionEvent event){
//start other Controller from here (SideBar)
//how do I access the DB Connection here?
Stage stage = (Stage) levelManBtn.getScene().getWindow();
//LevelManagementController controller = new LevelManagementController(stage, con);
//controller.displaySceneOn(stage);
}
}
UserManagementController.java
package myMcve.controller;
import com.sun.prism.impl.Disposer;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.util.Callback;
import myMcve.view.UserManagementView;
import java.io.IOException;
import java.sql.*;
public class UserManagementController{
private UserManagementView view;
private Parent scene;
Stage myStage;
Connection con;
public UserManagementController(Stage stage, Connection con){
myStage = stage;
this.con = con;
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../view/UserManagementScene.fxml"));
try {
scene = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
view = loader.getController();
}
public void displaySceneOn(Stage stage){
stage.setTitle("user management");
Scene myScene = new Scene(scene, 1250, 650);
stage.setScene(myScene);
stage.show();
}
}
LoginSceneView.java
package myMcve.view;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class LoginSceneView {
@FXML
private Label label;
public Label getLabel() {
return label;
}
}
LoginScene.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.112-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myMcve.view.LoginSceneView">
<Label fx:id="label" text="login Buttons etc..." />
</AnchorPane>
SideBar.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="sidebar" prefHeight="650.0" prefWidth="250.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myMcve.controller.SideBarController">
<children>
<Button fx:id="levelManBtn" layoutX="10.0" layoutY="123.0" prefHeight="50.0" prefWidth="350.0" text="Level Management" onAction="#levelMan"/>
</children>
</VBox>
UserManagementView.java
package myMcve.view;
import javafx.fxml.FXML;
import javafx.scene.control.*;
public class UserManagementView {
@FXML
private Label label;
public Label getLabel() {
return label;
}
}
UserManagementScene.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myMcve.view.UserManagementView">
<left>
<!-- SideBar import -->
<fx:include fx:id="sidebar" source="SideBar.fxml" />
</left>
<center>
<Label fx:id="label" text="user managemnt tableview and Buttons etc..." />
</center>
</BorderPane>