【发布时间】:2017-02-28 22:37:48
【问题描述】:
我目前正在研究将我的 SQL 连接保存在我的 JavaFX 项目中的最简单方法,以便在我的所有控制器中使用它。 由于我在 SideBar FXML 文件中创建控制器,因此无法将对象从一个控制器传递到另一个控制器。
因此,我想使用 Node.setUserData() 方法并将连接对象保存到根节点。不幸的是,当我想调用它时,我得到了 NullPointers。
保存效果很好:
myStage.getScene().getRoot().setUserData(con);
从同一个阶段变量调用它也可以正常工作:
... = (Connection) myStage.getScene().getRoot().getUserData();
但我正在通过我的 Sidebar.fxml 访问舞台
Stage stage = (Stage) myButton.getScene().getWindow();
在通过访问 UserData 时导致 NullPointers 的原因
stage.getScene().getRoot().getUserData();
我知道这是因为它不是“完全相同”的阶段变量。但它必须是同一个阶段(当我在那里显示一个新视图时,它会显示在与以前相同的阶段)。
如何找到与我之前保存过的 UserData 完全相同的节点?或者有没有办法从我没有舞台的另一个上下文访问同一个节点?
编辑:我在这里放了一个 MCVE 来显示我的问题是什么:https://github.com/lud-hu/myJavaFxMcve/ 编辑:代码现在在 Github 中运行,我将在此处发布带有初始问题的代码:
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>
【问题讨论】:
-
"无法将对象从一个控制器传递到另一个控制器。"为什么不呢?
-
另外,如果你真的想通过将其设置为根节点上的用户数据来做到这一点,那应该可以工作(尽管从设计角度来看,它非常糟糕)。什么实际上是空的?为什么它是空的?
-
使用 userData 似乎不是推荐的方法。相关:Passing Parameters JavaFX FXML 和 What is the main way to connect a view and a model in JavaFX?
-
@James_D 这是不可能的,因为我必须从无法将连接传递到的侧边栏中实例化新的控制器。至少我试了好几个小时还是没用。
-
@James_D 当我从上面提到的侧边栏控制器调用时,我从 getUserData() 获得的对象为空。我知道它应该工作,但不幸的是我没有。 :(
标签: javafx