刚刚开始熟悉java -我在这里有点困惑,我有一个简单的控制器与以下代码
package com.ajaxict.edhub;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.IOException;
public class WelcomeController {
public Stage stage;
private Scene scene;
private Parent root;
public void switchToWelcome(ActionEvent event) throws IOException {
root = FXMLLoader.load(getClass().getResource("welcome_view.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setTitle("EdHub - Welcome");
stage.setScene(scene);
stage.show();
}
public void switchToRegister(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("register_view.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setTitle("EdHub - Register");
stage.setScene(scene);
stage.show();
}
public void quit_frame (ActionEvent event) {
// stage = (Stage)((Node)event.getSource()).getScene().getWindow();
stage.close();
}
}
从上面的代码中,我相信stage属性会在我调用switchToWelcome()或switchToRegister()方法时被初始化-因此,如果我稍后调用quit_frame()方法,也不会出现任何问题,因为这个stage属性可以通过这个类访问。但每次我尝试调用quit_frame()方法时,仍然会得到NullPointerException
我在quit_frame()方法中添加了现在已注解的行,即在调用close()方法之前重新初始化该阶段,一切正常。但我觉得我不需要这一行,因为该阶段已使用我最初调用的switchToRegister()初始化。
下面是批量错误消息的最后部分
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.stage.Stage.close()" because "this.stage" is null
at com.ajaxict.edhub/com.ajaxict.edhub.WelcomeController.quit_app(WelcomeController.java:45)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 53 more
我尝试在quit_frame()方法中重新初始化stage属性,它可以工作,但我不认为这是最好的主意
下面是一个可重现的示例:WelcomeMain.java
package com.ajaxict.edhub;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class WelcomeMain extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(WelcomeMain.class.getResource("welcomeView.fxml"));
// Scene scene = new Scene(fxmlLoader.load(), 320, 240);
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("EdHub - Welcome");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
我的欢迎视图.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="309.0" prefWidth="543.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.ajaxict.edhub.WelcomeController">
<children>
<TextField fx:id="txt_email" layoutX="241.0" layoutY="147.0" prefHeight="35.0" prefWidth="263.0" />
<TextField fx:id="txt_pword" layoutX="241.0" layoutY="192.0" prefHeight="35.0" prefWidth="263.0" />
<Button fx:id="btn_login" layoutX="426.0" layoutY="258.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="78.0" text="Log In" />
<Label layoutX="45.0" layoutY="147.0" prefHeight="35.0" prefWidth="141.0" text="Email Address">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="45.0" layoutY="182.0" prefHeight="35.0" prefWidth="109.0" text="Password">
<font>
<Font size="17.0" />
</font>
</Label>
<Label alignment="CENTER" layoutX="23.0" layoutY="22.0" prefHeight="43.0" prefWidth="499.0" text="EdHub ">
<font>
<Font name="Monotype Corsiva" size="52.0" />
</font>
</Label>
<Button fx:id="btn_register" layoutX="138.0" layoutY="258.0" mnemonicParsing="false" onAction="#switchToRegister" prefHeight="27.0" prefWidth="78.0" text="Register" />
<Button fx:id="btn_quit" layoutX="45.0" layoutY="258.0" mnemonicParsing="false" onAction="#quit_app" prefHeight="27.0" prefWidth="78.0" text="Quit" />
</children>
</AnchorPane>
我的注册表视图.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="487.0" prefWidth="564.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.ajaxict.edhub.WelcomeController">
<children>
<TextField fx:id="txt_email" layoutX="248.0" layoutY="205.0" prefHeight="35.0" prefWidth="263.0" />
<Button fx:id="btn_login" layoutX="142.0" layoutY="420.0" mnemonicParsing="false" onAction="#switchToWelcome" prefHeight="27.0" prefWidth="78.0" text="Log In" />
<Label layoutX="52.0" layoutY="205.0" prefHeight="35.0" prefWidth="141.0" text="Lastname">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="50.0" layoutY="338.0" prefHeight="35.0" prefWidth="109.0" text="Password">
<font>
<Font size="17.0" />
</font>
</Label>
<Label alignment="CENTER" layoutX="33.0" layoutY="19.0" prefHeight="43.0" prefWidth="499.0" text="EdHub ">
<font>
<Font name="Monotype Corsiva" size="52.0" />
</font>
</Label>
<Button fx:id="btn_register" layoutX="433.0" layoutY="420.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="78.0" text="Register" />
<Button fx:id="btn_quit" layoutX="50.0" layoutY="420.0" mnemonicParsing="false" onAction="#quit_app" prefHeight="27.0" prefWidth="78.0" text="Quit" />
<Label layoutX="52.0" layoutY="292.0" prefHeight="35.0" prefWidth="109.0" text="Gender">
<font>
<Font size="17.0" />
</font>
</Label>
<ComboBox layoutX="247.0" layoutY="297.0" prefHeight="35.0" prefWidth="263.0" />
<TextField fx:id="txt_email1" layoutX="248.0" layoutY="250.0" prefHeight="35.0" prefWidth="263.0" />
<Label layoutX="52.0" layoutY="250.0" prefHeight="35.0" prefWidth="141.0" text="Email Address">
<font>
<Font size="17.0" />
</font>
</Label>
<TextField fx:id="txt_email2" layoutX="251.0" layoutY="160.0" prefHeight="35.0" prefWidth="263.0" />
<Label layoutX="55.0" layoutY="160.0" prefHeight="35.0" prefWidth="141.0" text="Firstname">
<font>
<Font size="17.0" />
</font>
</Label>
<PasswordField layoutX="245.0" layoutY="343.0" prefHeight="35.0" prefWidth="263.0" />
</children>
</AnchorPane>
我的welcomeController.java
package com.ajaxict.edhub;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.IOException;
public class WelcomeController {
public Stage stage;
private Scene scene;
private Parent root;
public void switchToWelcome(ActionEvent event) throws IOException {
root = FXMLLoader.load(getClass().getResource("welcomeView.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setTitle("EdHub - Welcome");
stage.setScene(scene);
stage.show();
}
public void switchToRegister(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("registerView.fxml"));
stage = (Stage)((Node)event.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setTitle("EdHub - Register");
stage.setScene(scene);
stage.show();
}
public void quit_app (ActionEvent event) {
// stage = (Stage)((Node)event.getSource()).getScene().getWindow();
this.stage.close();
}
}
1条答案
按热度按时间qv7cva1a1#
示例变量
stage
仅在调用switchToWelcome
或switchToRegister
时在每个控制器中初始化。但在这两种情况下,您都要立即用从FXML文件加载的视图替换当前视图,这将创建一个新的控制器。stage
变量不会在该新控制器示例中初始化。因此,无论何时调用quitApp()
,stage
在调用它的示例上为空。对于为不同FXML文件创建的控制器,使用相同的控制器类是一个不好的主意,因为这会直接导致引起此错误的那种混淆。每个FXML文件都应有自己的控制器类。
要获取对当前窗口的引用,直接从该窗口中显示的节点获取要干净得多,可以用通常的方式将其注入控制器。
比如说你可以
然后
这将关闭当前窗口。如果你真的想关闭整个应用程序(而不仅仅是关闭当前窗口,这可能会也可能不会退出应用程序),你当然可以用
Platform.exit()
来代替。下面是使用这种方法的应用程序版本。
请注意,
fx:id
添加到了FMXL的根元素中。WelcomeView.fxml:
WelcomeController.java:
(我真的不明白为什么你的“欢迎”屏幕有“切换到欢迎”功能,但我把它留在了里面。)
registerView.fxml:
RegisterController.java:
显然,您可以通过使用委托或继承来删除控制器中的重复代码。