【问题标题】:JavaFX: ClassNotFoundException for imported class in FXMLJavaFX:FXML 中导入类的 ClassNotFoundException
【发布时间】:2016-05-16 04:43:01
【问题描述】:

我正在尝试创建一个文本字段,其标题嵌入在字段边框中,例如:

按照here 发布的解决方案,我在src>main>java 目录中创建了一个名为TitledBorder.java 的.java 文件。我的 FXML 位于 src>main>resources 目录中,我已添加:

<?import TitledBorder?> 在顶部,它没有显示如下错误:

然后我将此代码添加到 FXML

<HBox prefHeight="100.0" prefWidth="200.0">
    <children>
      <TitledBorder title="Email" >
        <TextField fx:id="emailField" prefHeight="44.0" prefWidth="143.0" />
      </TitledBorder>
    </children>
</HBox>

它也没有显示错误。然后我启动我的 main 方法,该方法也在 src>main>java 中的一个类中,但它在 .fxml 中出现错误,说 javafx.fxml.LoadException: /C:/Users/ME/Documents/Automation/target/classes/demofxml.fxml

Caused by: java.lang.ClassNotFoundException
    at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2899)

我不确定为什么它引用“/target/classes/...”而不是“/src/main/java/...”。

这是我找到的唯一 FXML 示例,所以我很困惑为什么我在编译时遇到错误,但之前没有显示错误?删除对TitledBorder 的所有引用允许我的所有代码正常运行/编译。由于它在 src 包中,因此我在 FXML 中使用此代码与控制器 fx:controller="loadController"&gt; 连接。 CSS也被正确添加了。

想法?

【问题讨论】:

  • 你能显示你的 FXML 文件中的导入吗?至于“我不确定为什么它引用“/target/classes/...”而不是“/src/main/java/...”,那肯定是因为它是运行时 FXML 文件的位置(而不是在编译时)。
  • James,问题是我使用的是默认包,应该在我的 java 包中创建一个包,然后在 FXML 中从那里引用 TitledBorder 类。感谢您的关注。

标签: javafx textfield fxml titled-border


【解决方案1】:

线

<?import TitledBorder?>

意味着您将TitledBorder.java 文件放入默认包(即此文件的源代码中没有包声明)。但是FXMLLoader的源代码会检查FXML文件中的导入,并在下面的loadType(...)中拆分包路径名和类名,以便稍后使用loadTypeForPackage()加载导入的类:

private Class<?> loadType(String name, boolean cache) throws ClassNotFoundException {
    int i = name.indexOf('.');
    int n = name.length();
    while (i != -1
        && i < n
        && Character.isLowerCase(name.charAt(i + 1))) {
        i = name.indexOf('.', i + 1);
    }

    if (i == -1 || i == n) {
        throw new ClassNotFoundException();
    }

    String packageName = name.substring(0, i);
    String className = name.substring(i + 1);

    Class<?> type = loadTypeForPackage(packageName, className);

    if (cache) {
        classes.put(className, type);
    }

    return type;
}

// TODO Rename to loadType() when deprecated static version is removed
private Class<?> loadTypeForPackage(String packageName, String className) throws ClassNotFoundException {
    return getClassLoader().loadClass(packageName + "." + className.replace('.', '$'));
}

导入的类名为“TitledBorder”,因此loadType 方法中第一行的变量i 将被评估为name.indexOf('.') = -1,并将在下一行代码中抛出ClassNotFoundException

通常使用默认包是不好的做法。将 TitledBorder.java 放入某个包中并导入为

<?import my.some.package.TitledBorder?>

【讨论】:

  • 这行得通,谢谢 Uluk。奇怪的是,我以为我昨晚尝试了这个,但显然我在 java 包之外创建了一个包,而不是在里面。我从你的帖子中学到了一些东西,感谢它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 2021-04-29
  • 2011-02-28
相关资源
最近更新 更多