javafx.fxml.LoadException的未知原因



我有一个三阶段的JavaFX应用程序(现在只有登录/注册/空白视图(,我试图在它们之间进行通信。我创建了一个超级类,所有阶段都扩展了这个超级类。现在,当我像下面这样运行主类时,我会得到运行时错误:

public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
conn = DBUtils.connectToDB(DB_SCHEMA);
new LoginController(primaryStage);
}

例外:

Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javafx.fxml.LoadException: 
/C:/Mihai/Faculta/Anul%203/Licenta/Aplicatie/licenta-mihai-laza/out/production/licenta-mihai-laza/application/login.fxml:7
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:105)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:941)
at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:980)
at javafx.fxml/javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:227)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:752)
at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at licenta.mihai.laza/application.superclasses.StageSuperclass.<init>(StageSuperclass.java:20)
at licenta.mihai.laza/application.LoginController.<init>(LoginController.java:45)
at licenta.mihai.laza/application.Main.start(Main.java:21)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
... 1 more
Caused by: java.lang.InstantiationException: application.LoginController
at java.base/java.lang.Class.newInstance(Class.java:571)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:936)
... 24 more
Caused by: java.lang.NoSuchMethodException: application.LoginController.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3350)
at java.base/java.lang.Class.newInstance(Class.java:556)
... 25 more
[INFO] Connection to database closed
Exception running application application.Main

StageSuperclass.java:

public class StageSuperclass extends Stage {
// Frame window
private Stage stage;
private double xOffset = 0;
private double yOffset = 0;
public StageSuperclass(Stage stage, String fxmlFilePath) throws java.io.IOException {
this.stage = stage;
Parent root = FXMLLoader.load(getClass().getResource(fxmlFilePath));
Scene scene = new Scene(root, Color.TRANSPARENT);
root.setStyle("-fx-background-color: transparent;");
this.initStyle(StageStyle.UNDECORATED);
root.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
xOffset = mouseEvent.getSceneX();
yOffset = mouseEvent.getSceneY();
}
});
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
stage.setX(mouseEvent.getScreenX() - xOffset);
stage.setY(mouseEvent.getScreenY() - yOffset);
}
});
this.setScene(scene);
this.show();
}
public Stage getStage() {
return this.stage;
}

LoginController.java:

public class LoginController extends StageSuperclass {
// Constants
private static final String LOGIN_FXML_PATH = "/application/login.fxml";
private static final String WRONG_CREDENTIALS_MSG = "Datele de logare sunt gresite!";
private static final String BLANK_CREDENTIALS_MSG = "Introduceti username si parola!";
// PageObjects
RegisterController registerPage;
// FXML Objects
@FXML
private Button btnLogin;
@FXML
private Button btnIesire;
@FXML
private TextField tfdUsername;
@FXML
private TextField tfdParola;
@FXML
private Label lblInvalid;
@FXML
private Hyperlink lnkInregistrare;
// Constructor
public LoginController(Stage stage) throws IOException {
super(stage, LOGIN_FXML_PATH);
}
public void inregistrareLinkOnAction(ActionEvent event) throws IOException {
new RegisterController(this.getStage());
}
public void loginButtonOnAction(ActionEvent event) throws IOException {
if (!tfdUsername.getText().isBlank() && !tfdParola.getText().isBlank()) {
if (validareLogin()) {
new MainWindowController(this.getStage());
}
} else {
lblInvalid.setText(BLANK_CREDENTIALS_MSG);
}
}
public void iesireButtonOnAction(ActionEvent event) {
Stage stage = (Stage) btnIesire.getScene().getWindow();
stage.close();
}
private boolean validareLogin() {
List<String> columns = Arrays.asList(COL_USERNAME, COL_PAROLA);
List<String> whereValues = Arrays.asList(tfdUsername.getText(), tfdParola.getText());
if (DBUtils.select(columns, columns, whereValues, DBUtils.TABEL_UTILIZATORI.TABLE_NAME, Main.conn).size() == 1) {
return true;
} else {
lblInvalid.setText(WRONG_CREDENTIALS_MSG);
return false;
}
}
}

登录.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="300.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.LoginController">
<AnchorPane prefHeight="60.0" prefWidth="300.0" style="-fx-background-color: #0084b8;">
<children>
<Label alignment="CENTER" contentDisplay="CENTER" layoutY="17.0" prefHeight="17.0" prefWidth="300.0"
text="LOGIN" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="18.0"/>
</font>
</Label>
</children>
</AnchorPane>
<Button id="btnLogin" fx:id="btnLogin" layoutX="33.0" layoutY="216.0" mnemonicParsing="false"
onAction="#loginButtonOnAction" prefHeight="25.0" prefWidth="233.0" style="-fx-background-color: #0084b8;"
text="Login" textFill="WHITE">
<font>
<Font size="13.0"/>
</font>
</Button>
<TextField id="tfdUsername" fx:id="tfdUsername" layoutX="89.0" layoutY="82.0" promptText="User">
<font>
<Font size="14.0"/>
</font>
</TextField>
<PasswordField id="tfdParola" fx:id="tfdParola" layoutX="89.0" layoutY="123.0" promptText="Parola">
<font>
<Font size="14.0"/>
</font>
</PasswordField>
<Hyperlink id="lnkInregistrare" fx:id="lnkInregistrare" layoutX="118.0" layoutY="153.0"
onAction="#inregistrareLinkOnAction" text="Nu ai cont? Inregistreaza-te!">
<font>
<Font size="11.0"/>
</font>
</Hyperlink>
<Label layoutX="33.0" layoutY="87.0" text="User">
<font>
<Font size="14.0"/>
</font>
</Label>
<Label layoutX="32.0" layoutY="128.0" text="Parola">
<font>
<Font size="14.0"/>
</font>
</Label>
<Button id="btnCancel" fx:id="btnIesire" layoutX="33.0" layoutY="254.0" mnemonicParsing="false"
onAction="#iesireButtonOnAction" prefHeight="25.0" prefWidth="233.0" style="-fx-background-color: #0084b8;"
text="Iesire" textFill="WHITE">
<font>
<Font size="13.0"/>
</font>
</Button>
<Label id="lblInvalid" fx:id="lblInvalid" alignment="TOP_CENTER" contentDisplay="CENTER" layoutX="44.0"
layoutY="194.0" prefHeight="16.0" prefWidth="233.0" textAlignment="CENTER" textFill="RED">
<font>
<Font size="11.0"/>
</font>
</Label>
</AnchorPane>

你对解决这个异常有什么建议吗?

异常是因为您的FXML文件指定了fx:controller="application.LoginController"。这将导致FXMLLoader通过(有效地(调用其无参数构造函数来创建application.LoginController的实例。然而,LoginController类没有无参数构造函数:因此出现了异常:

Caused by: java.lang.NoSuchMethodException: application.LoginController.<init>()

典型的方法是加载FXML文件,并让FXMLLoader为您创建控制器。除了在非常高级的用法中,您不应该自己实例化控制器类,因为FXMLLoader会为您执行此操作。

去掉LoginController中的继承(即,它不需要是其他控制器类的子类,当然也不应该是Stage的子类(。那就做

public class MyApplication extends Application {
private double xOffset = 0 ;
private double yOffset = 0 ;
public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource(LOGIN_FXML_PATH));
Parent root = loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
root.setOnMousePressed(mouseEvent -> {
xOffset = mouseEvent.getSceneX();
yOffset = mouseEvent.getSceneY();
});

root.setOnMouseDragged(mouseEvent ->  {
stage.setX(mouseEvent.getScreenX() - xOffset);
stage.setY(mouseEvent.getScreenY() - yOffset);
});
primaryStage.show();
}
}

如果您需要重复使用相同的功能,只需以正常方式创建一个单独的类:

public class StageDragHandler {
private double xOffset = 0 ;
private double yOffset = 0 ;
public Stage createStage(Parent root) {
Stage stage = new Stage();
configureStage(root, stage);
return stage ;
}
public void configureStage(Parent root, Stage stage) {
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UNDECORATED);
root.setOnMousePressed(mouseEvent -> {
xOffset = mouseEvent.getSceneX();
yOffset = mouseEvent.getSceneY();
});

root.setOnMouseDragged(mouseEvent -> {
stage.setX(mouseEvent.getScreenX() - xOffset);
stage.setY(mouseEvent.getScreenY() - yOffset);
});
}
}

然后您的应用程序类减少为:

public class MyApplication extends Application {
public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource(LOGIN_FXML_PATH));
Parent root = loader.load();
new StageDragHandler().configureStage(root, primaryStage);   
primaryStage.show();
}
}

你可以在任何需要的地方使用类似的代码。

最新更新