在 JAVAFX 11 FXML 中导入 java.lang.String 失败

import of java.lang.String fails in JAVAFX 11 FXML

我有一个 JAVAFX 11 FXML 文件描述了我在应用程序中使用的弹出窗口 window。在重构我将 FXML 从 "app" 项目移动到另一个项目的项目结构后,我得到 NullPointerException 错误,因为 XML 加载器无法导入 java.lang.String (并且其他)

FXML 看起来像这样:

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

<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<TitledPane fx:id="GeneticMain" 
animated="false"
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity" 
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="400.0"
text="Genetic Scanner Config" 
xmlns="http://javafx.com/javafx/8.0.141"
xmlns:fx="http://javafx.com/fxml/1">
  <content>
    <AnchorPane minHeight="-Infinity" minWidth="-Infinity">
         <children>
            <GridPane layoutX="10.0"
...

堆栈底部跟踪:

Caused by: java.lang.NullPointerException
    at javafx.fxml.FXMLLoader.loadTypeForPackage(FXMLLoader.java:2931) ~[javafx-fxml-12.0.1-linux.jar:?]
    at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2920) ~[javafx-fxml-12.0.1-linux.jar:?]
    at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2861) ~[javafx-fxml-12.0.1-linux.jar:?]
    at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2707) ~[javafx-fxml-12.0.1-linux.jar:?]
    at javafx.fxml.FXMLLoader.processProcessingInstruction(FXMLLoader.java:2676) ~[javafx-fxml-12.0.1-linux.jar:?]
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2542) ~[javafx-fxml-12.0.1-linux.jar:?]

Javafx 的有效 POM 依赖如下所示:

<properties>
   ...
   <dependencyversion.openjfx>12.0.1</dependencyversion.openjfx>
   ...
</properties>
...
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-base</artifactId>
    <version>12.0.2</version>
</dependency>
<dependency>
  <groupId>de.gsi.chart</groupId>
  <artifactId>chartfx-chart</artifactId>
  <version>11.0.3</version>
  <scope>compile</scope>
  <exclusions>
    <exclusion>
      <artifactId>commons-logging</artifactId>
      <groupId>commons-logging</groupId>
    </exclusion>
    <exclusion>
      <artifactId>javafx-base</artifactId>
      <groupId>org.openjfx</groupId>
    </exclusion>
    <exclusion>
      <artifactId>javafx-web</artifactId>
      <groupId>org.openjfx</groupId>
    </exclusion>
  </exclusions>
</dependency>

我很高兴收到任何建议...

感谢 fabian 我能够为我的问题提供解决方案。

我的问题的根本原因是我的弹出窗口 window 的 class 加载程序(在 PopupController.showPopupWindow() 中调用)为空。 初始代码:

 public void showPopupWindow() throws Exception {
        Parent popupWindowRoot = null;
        try {
            URL url = getClass().getResource(url.to.popupFXML.file);
            final FXMLLoader fxmlLoader = new FXMLLoader(url);
            fxmlLoader.setController(this);
            popupWindowRoot = (Parent) fxmlLoader.load();
        } catch (final IOException e) {
            MessageLogger.logError(getClass(), e);
            throw e;
        }
        ...
}

这是通过主程序中的 onAction 方法调用的 window:

private void handle_onAction(event onAction) throws Exception {
    popupController = new PopupController();
    popupController.setParentController(this);
    try {
        popupController.showPopupWindow();
    } catch (final Exception ex) {
        APPLOGGER.error(true, true, "Error caught in method showPopupWindow(): ");
    }
}

按照 Fabian 的建议,我将主 window 阶段传递给方法 showPopupWindow 并使用此阶段显式设置弹出窗口的 classLoader window. 新密码:

 public void showPopupWindow(Stage parentStage) throws Exception {
        Parent popupWindowRoot = null;
        try {
            URL url = getClass().getResource(url.to.popupFXML.file);
            final FXMLLoader fxmlLoader = new FXMLLoader(url);
            fxmlLoader.setController(this);
            fxmlLoader.setClassLoader(parentStage.getClass().getClassLoader());
            popupWindowRoot = (Parent) fxmlLoader.load();
        } catch (final IOException e) {
            MessageLogger.logError(getClass(), e);
            throw e;
        }
        ...
}

调用方式相应调整