Java 通过另一个文件中的控制器实例引用在MainController中设置文本字段
我正在尝试从另一个文件设置MainController中的文本字段的文本。 我读到: 这是在Javafx中获取控制器实例引用的方式。我试图实现它,但在尝试设置TextField时,它给了我一个NullPointerException。 这是我的密码: Main.java:Java 通过另一个文件中的控制器实例引用在MainController中设置文本字段,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,我正在尝试从另一个文件设置MainController中的文本字段的文本。 我读到: 这是在Javafx中获取控制器实例引用的方式。我试图实现它,但在尝试设置TextField时,它给了我一个NullPointerException。 这是我的密码: Main.java: package application; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.P
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class Main extends Application {
static MainController mc;
@Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
Scene scene = new Scene(root,348,212);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("Flextime calculator");
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("assets/icon.png")));
primaryStage.setResizable(false);
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
mc = (MainController) loader.getController();
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
public static MainController getMc() {
return mc;
}
}
MainController.java:
public class MainController {
@FXML Label fxFlextime;
@FXML Label fxTotalFlextime;
@FXML TextField fxStarttime;
@FXML TextField fxEndtime;
@FXML TextField fxDailyWorktime;
@FXML TextField fxBreaktime;
@FXML TextField fxAddBreaktime;
@FXML TextField fxBreakGap;
@FXML CheckBox fxAddBreak;
//Create Model, Userconfig
Model model = new Model();
UserConfig config = new UserConfig();
public void initialize() {
config.initialize();
}
}
UserConfig.java:
public class UserConfig {
public void initialize() {
insertDefault();
}
void insertDefault() {
List<String> prefValues = getPreference();
//FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
//MainController mc = (MainController) loader.getController();
// ^Tried also putting it here to see wether im referencing the variable wrong or something,
// so maybe im getting the Controller wrong? With mc.fxStarttime.setText("") it also didnt work here
Main.mc.fxStarttime.setText("");
Main.mc.fxEndtime.setText(prefValues.get(2));
Main.mc.fxDailyWorktime.setText(prefValues.get(3));
Main.mc.fxBreaktime.setText(prefValues.get(4));
Main.mc.fxAddBreaktime.setText(prefValues.get(5));
Main.mc.fxBreakGap.setText(prefValues.get(6));
}
static List<String> getPreference() {
// This will define a node in which the preferences can be stored
Preferences userPrefs = Preferences.userNodeForPackage(Main.class);
try {
String[] keys = userPrefs.keys();
if (keys == null) {
userPrefs.put("DEFStarttime" , "1");
userPrefs.put("DEFEndtime" , "");
userPrefs.put("DEFDailyWorktime", "");
userPrefs.put("DEFBreaktime" , "");
userPrefs.put("DEFAddBreaktime" , "");
userPrefs.put("DEFBreakGap" , "");
}
} catch (BackingStoreException ex) {
System.err.println(ex);
}
List<String> prefValues = new ArrayList<String>();
prefValues.add(userPrefs.get("DEFStarttime" , ""));
prefValues.add(userPrefs.get("DEFEndtime" , ""));
prefValues.add(userPrefs.get("DEFDailyWorktime" , ""));
prefValues.add(userPrefs.get("DEFBreaktime" , ""));
prefValues.add(userPrefs.get("DEFAddBreaktime" , ""));
prefValues.add(userPrefs.get("DEFBreakGap" , ""));
/*
for(String string : prefValues) {
System.out.println(string);
}
*/
return prefValues;
}
}
我试着把代码减少到最少
编辑:
这里是Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="212.0" prefWidth="348.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<MenuBar fx:id="fxMenuBar">
<menus>
<Menu fx:id="fxFileMenu" mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="fxExitItem" mnemonicParsing="false" onAction="#exitProgram" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Settings">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<FlowPane alignment="CENTER_LEFT" prefHeight="25.0" prefWidth="403.0">
<children>
<Label alignment="CENTER" prefHeight="15.0" prefWidth="65.0" text="Starttime:" underline="true">
<FlowPane.margin>
<Insets left="10.0" top="10.0" />
</FlowPane.margin>
</Label>
<TextField fx:id="fxStarttime" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00:00">
<FlowPane.margin>
<Insets top="10.0" />
</FlowPane.margin></TextField>
<Label alignment="CENTER" prefHeight="17.0" prefWidth="112.0" text="Required daily hours:" underline="true">
<FlowPane.margin>
<Insets left="10.0" right="5.0" top="10.0" />
</FlowPane.margin>
</Label>
<TextField fx:id="fxDailyWorktime" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00.00">
<FlowPane.margin>
<Insets top="10.0" />
</FlowPane.margin></TextField>
</children>
</FlowPane>
<FlowPane alignment="CENTER_LEFT" prefHeight="36.0" prefWidth="300.0">
<children>
<Label alignment="CENTER" prefHeight="15.0" prefWidth="65.0" text="Endtime:" underline="true">
<FlowPane.margin>
<Insets left="10.0" />
</FlowPane.margin>
</Label>
<TextField fx:id="fxEndtime" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00:00" />
<Label alignment="CENTER" prefHeight="15.0" prefWidth="65.0" text="Breaktime:" underline="true">
<FlowPane.margin>
<Insets left="57.0" right="5.0" />
</FlowPane.margin>
</Label>
<TextField fx:id="fxBreaktime" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00" />
</children>
</FlowPane>
<FlowPane prefHeight="38.0" prefWidth="300.0">
<children>
<CheckBox fx:id="fxAddBreak" mnemonicParsing="false" text="Add:">
<FlowPane.margin>
<Insets left="20.0" top="5.0" />
</FlowPane.margin>
</CheckBox>
<TextField fx:id="fxAddBreaktime" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00">
<FlowPane.margin>
<Insets left="10.0" right="5.0" top="5.0" />
</FlowPane.margin>
</TextField>
<Label text="breaktime from ">
<FlowPane.margin>
<Insets top="5.0" />
</FlowPane.margin>
</Label>
<TextField fx:id="fxBreakGap" alignment="CENTER" prefHeight="25.0" prefWidth="45.0" promptText="00.00">
<FlowPane.margin>
<Insets top="5.0" />
</FlowPane.margin>
</TextField>
<Label text="working hours">
<FlowPane.margin>
<Insets left="5.0" top="5.0" />
</FlowPane.margin>
</Label>
</children>
</FlowPane>
<FlowPane alignment="CENTER_RIGHT" prefHeight="32.0" prefWidth="300.0">
<children>
<Label text="Flextime:">
<FlowPane.margin>
<Insets right="10.0" />
</FlowPane.margin>
</Label>
<Label fx:id="fxFlextime" alignment="CENTER" prefHeight="10.0" prefWidth="35.0" text="0.00" textAlignment="CENTER">
<FlowPane.margin>
<Insets />
</FlowPane.margin>
</Label>
<Label text="h">
<FlowPane.margin>
<Insets right="10.0" />
</FlowPane.margin>
</Label>
</children>
</FlowPane>
<FlowPane alignment="CENTER_RIGHT" prefHeight="32.0" prefWidth="300.0">
<children>
<Label text="Total flextime:" underline="true">
<FlowPane.margin>
<Insets right="10.0" />
</FlowPane.margin>
</Label>
<Label fx:id="fxTotalFlextime" alignment="CENTER" prefHeight="10.0" prefWidth="35.0" text="0.00" textAlignment="CENTER">
<FlowPane.margin>
<Insets />
</FlowPane.margin>
</Label>
<Label text="h">
<FlowPane.margin>
<Insets right="10.0" />
</FlowPane.margin>
</Label>
</children>
</FlowPane>
<FlowPane alignment="CENTER_RIGHT" prefHeight="38.0" prefWidth="300.0">
<children>
<Button mnemonicParsing="false" onAction="#calculate" text="Calculate" underline="true">
<FlowPane.margin>
<Insets right="10.0" />
</FlowPane.margin>
</Button>
<Button mnemonicParsing="false" onAction="#addToTotal" text="Add to total" />
<Button mnemonicParsing="false" onAction="#clear" text="Clear">
<FlowPane.margin>
<Insets left="10.0" right="10.0" />
</FlowPane.margin>
</Button>
</children>
</FlowPane>
</children>
</VBox>
获取
NullPointerException
的原因是,Main.mc在您试图访问UserConfig中的it字段时为null
在加载main.fxmlParent root=fxmloader.load(getClass().getResource(“main.fxml”))的行中
调用控制器MainController
中的initialize()
方法,此时您正在调用userConfig.initialize()
,该方法还向后引用Main.mc
,此时该方法为null
在主类中设置mc
字段后,可以在MainController类中公开配置并初始化用户配置。或者您可以将MainController作为参数注入UserConfig initialize方法
Main.java
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
Parent root = (Parent) loader.load();
Scene scene = new Scene(root,348,212);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("Flextime calculator");
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("assets/icon.png")));
primaryStage.setResizable(false);
mc = (MainController) loader.getController();
mc.config.initialize();
MainController.java
public UserConfig config = new UserConfig();
@FXML
public void initialize() {
//remove the config.initialize(); from here
}
你能分享
main.fxml
@Thecarisma Done的源代码吗。在main.fxml中提到了很多方法,但是这些方法都非常好用,所以我在给出的代码中没有提到它们。如果有必要,我当然可以添加整个文件,我只是认为这样会更容易阅读。您必须在其控制器可用之前加载fxml。这是FXMLLoader流的答案这似乎是错误设计的。您的UserConfig
类根本不应该引用控制器。只需在UserConfig
类中定义方法来返回数据(getStartTime()
,getEndTime()
,等等)。将初始化代码(读取首选项,如果不可用,则诉诸默认值,当前在静态
(为什么??)getPreference()
方法中)移动到构造函数。然后在控制器的initialize()
方法中创建一个UserConfig
实例,并通过调用那些getStartTime()
方法等初始化字段。
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
Parent root = (Parent) loader.load();
Scene scene = new Scene(root,348,212);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("Flextime calculator");
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("assets/icon.png")));
primaryStage.setResizable(false);
mc = (MainController) loader.getController();
mc.config.initialize();
public UserConfig config = new UserConfig();
@FXML
public void initialize() {
//remove the config.initialize(); from here
}