Java 应用程序启动方法中出现异常。带Maven的OpenJFX13

Java 应用程序启动方法中出现异常。带Maven的OpenJFX13,java,maven,javafx,openjfx,Java,Maven,Javafx,Openjfx,我尝试使用带有Maven的OpenJFX模块启动一个新项目。我遵循以下步骤:(使用Maven转到JavaFX->Modular with Maven),但在应用程序启动方法中得到了一个例外 错误: Exception in Application start method java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke

我尝试使用带有Maven的OpenJFX模块启动一个新项目。我遵循以下步骤:(使用Maven转到JavaFX->Modular with Maven),但在应用程序启动方法中得到了一个例外

错误:

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:567)
    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:567)
    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:830)
Caused by: java.lang.IllegalStateException: Location is not set.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2459)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
    at org.openjfx/org.openjfx.App.loadFXML(App.java:31)
    at org.openjfx/org.openjfx.App.start(App.java:20)
    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(AccessController.java:391)
    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
Exception running application org.openjfx.App
pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.openjfx</groupId>
    <artifactId>Oblig1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>13</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>13</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <release>11</release>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>0.0.1</version>
            <configuration>
                <mainClass>org.openjfx.App</mainClass>
            </configuration>
        </plugin>
        </plugins>
    </build>
</project>
primary.fxml:

secondary.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<VBox alignment="CENTER" spacing="20.0" 
xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="org.openjfx.SecondaryController">
    <children>
        <Label text="Secondary View" />
        <Button fx:id="secondaryButton" text="Switch to Primary View" 
onAction="#switchToPrimary" />
    </children>
    <padding>
        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
    </padding>
</VBox>
董事:

    src
        main
            java
                org.openjfx
                    App.java
                    PrimaryController.java
                    SecondaryController.java
            resources 
                org.openjfx
                    primary.fxml
                    secondary.fxml

我认为这可能与FXML加载程序中的链接有关,我见过其他人也有类似的问题(),但我的directorary的resources文件夹与他们的不同。感谢您的帮助。

错误消息

java.lang.IllegalStateException:未设置位置。
表示您提供给
fxmloader
构造函数的URL为
null
。如果找不到指定的资源,则
Class.getResource(…)
方法将以静默方式返回
null

发生这种情况是因为您提供给
loadFXML
方法以及最终提供给
App.class.getResource(…)
的资源名称不正确。您提供给
Class.getResource(…)
的值是一个资源名称,其详细信息已记录在案

资源名称由“类的包的完全限定名,但转换”构成 所有句点(.)到斜杠(/)(见下文)。如果不了解buid文件夹和/或jar文件的结构,就不可能准确地知道到底出了什么问题,但可能应该是这样的

scene = new Scene(loadFXML("/org/openjfx/primary"));
由于您的FXML文件和执行此代码的类位于同一个包中,因此您也可能只需要

scene = new Scene(loadFXML("primary"));
该文件的某些相关部分:

资源、名称和上下文

资源由一个字符串标识,该字符串由一系列 子字符串,由斜杠(/)分隔,后跟资源名称。 每个子字符串必须是有效的Java标识符。资源名称为 形式为shortName或shortName.extension。shortName和 扩展必须是Java标识符

资源的名称独立于Java实现;在里面 特别是,路径分隔符始终是斜杠(/)。但是, Java实现控制了 资源映射到文件、数据库或其他包含 实际资源

资源名称的解释是相对于类加载器的 例子类加载器类实现的方法实现了这一点 口译

资源名称

类使用的资源名称的一个常见约定是 使用类的包的完全限定名,但转换 将所有句点(.)添加到斜杠(/),并添加表单的资源名称 name.extension。支持这一点,并简化细节处理 对于系统类(getClassLoader为其返回null),类 类提供了两个方便的方法,它们调用适当的 类加载器中的方法

给定给类方法的资源名称可能具有初始起始名称 “/”将其标识为“绝对”名称。资源名称可以 不以“/”开头是“相对的”

因此,
“/org.openjfx/primary”
不是有效的资源名称,因为
“org.openjfx”
不是有效的Java标识符

在您的结构中,请注意,
org.openjfx
不是一个文件夹,而是一个包。IDE和构建工具将把它转换为文件系统上的文件夹层次结构,最终转换为jar文件中的文件夹层次结构,包的子包结构将被文件夹和子文件夹替换。因此,在源代码结构中,您将有一个带有“org”子文件夹、“openjfx”子文件夹的“java”文件夹,以及
org.openjfx
包中类的java源文件。在“resources”文件夹中,您还将有一个“org”子文件夹、“openjfx”子文件夹,以及您创建的资源文件(包括FMXL文件)

构建工具(Maven或只是您的IDE)识别特定的源文件夹;在您的案例中,这些配置包括“java”和“resources”。构建应用程序时,在构建目标中重新创建源文件夹下结构的并集;在这里,这只会产生一个
org
文件夹和
openjfx
子文件夹。任何Java源文件都编译为类文件;任何其他文件都只是复制的。最后,整个过程被捆绑到一个jar文件中(本质上只是一个zip归档文件)

如果您在文件系统中找到jar文件(默认情况下,Maven会将其放在名为“target”的文件夹中,该文件夹位于“src”文件夹旁边),您可以使用

jar-tf Oblig1-1.0-SNAPSHOT.jar
(我认为,
Oblig1-1.0-SNAPSHOT.jar
是生成的jar文件的名称,但如果需要,显然可以对其进行调整)。您应该看到我概述的文件夹结构,输出应该包括

/org/openjfx/App.class
/org/openjfx/PrimaryController.class
/org/openjfx/SecondaryController.class
/org/openjfx/primary.fxml
/org/openjfx/secondary.fxml
(同样的结构应该存在于
target/classes
文件夹下,不过文件夹的命名和位置也取决于您的Maven设置。)


顺便说一句,您真的不应该将
org.openjfx
用于您自己的包名和Maven组ID;使用特定于您自己或您的组织的内容。

是的,请先修复项目结构,如果错误仍然存在,您必须添加控制器代码。看起来您的控制器缺少
@FXML URL位置。是的,我忘了主菜。很抱歉。还将控制器类添加到问题中,如果使用正确的jar文件名运行
jar-tf
(不管它是什么;它可能在某个地方的
target
文件夹下)会得到什么
package org.openjfx;

import java.io.IOException; 
import javafx.fxml.FXML;

public class SecondaryController {

    @FXML
    private void switchToPrimary() throws IOException {
        App.setRoot("PrimaryController");
    }
}
    src
        main
            java
                org.openjfx
                    App.java
                    PrimaryController.java
                    SecondaryController.java
            resources 
                org.openjfx
                    primary.fxml
                    secondary.fxml
scene = new Scene(loadFXML("/org/openjfx/primary"));
scene = new Scene(loadFXML("primary"));