【问题标题】:"FXMLLoader.constructLoadException" when trying to run java fx application尝试运行 java fx 应用程序时出现“FXMLLoader.constructLoadException”
【发布时间】:2015-06-30 10:00:25
【问题描述】:

我已经搜索了互联网的最深处,但似乎找不到答案-.-

问题出在我想编写的 javaFx 程序中。但除了添加控制器类之外,我无法做到这一点。我几乎遵循了所有可以找到的教程,但我仍然不知道这个问题。

这是个例外:

javafx.fxml.LoadException: 
/U:/BankingSolutions/MediaCenterFX/bin/main/ressources/view/MainUI.fxml:12

at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2617)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:976)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:738)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2723)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3230)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3191)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3164)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3140)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3120)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3113)
at application.Main.start(Main.java:15)
at com.sun.javafx.application.LauncherImpl$8.run(LauncherImpl.java:837)
at com.sun.javafx.application.PlatformImpl$7.run(PlatformImpl.java:335)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:301)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:298)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$6.run(PlatformImpl.java:298)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: /java/controllers/MainUIController
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:925)
... 24 more

这是代码。有 3 个类:Main.class,我使用 scenebuilder 2 创建的 MainUI.fxml 和我的 MainUIController.class,它显然应该作为 mainuis 控制器工作

package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;


public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            AnchorPane root = (AnchorPane) FXMLLoader.load(getClass().getResource("/main/ressources/view/MainUI.fxml"));
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args); 
    }
}

_______________________________________________

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

<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane fx:id="root" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="/java/controllers/MainUIController">
   <children>
      <BorderPane fx:id="borderPane01" layoutX="657.0" layoutY="304.0" prefHeight="336.0" prefWidth="403.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <bottom>
            <AnchorPane fx:id="bp_bottom" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
         </bottom>
         <left>
            <GridPane fx:id="bp_left_grid" prefHeight="680.0" prefWidth="238.0" BorderPane.alignment="CENTER">
              <columnConstraints>
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
              </columnConstraints>
              <rowConstraints>
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
              </rowConstraints>
               <children>
                  <Button fx:id="btn_search" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Suche" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER">
                     <GridPane.margin>
                        <Insets />
                     </GridPane.margin>
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_series" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Serien" wrapText="true" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_download" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Download" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_movies" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Filme" wrapText="true" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_exit" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Beenden" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="6" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_settings" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Optionen" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="4" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>
                  <Button fx:id="btn_dashboard" mnemonicParsing="false" prefHeight="48.0" prefWidth="172.0" text="Dashboard" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Button>

               </children>
            </GridPane>
         </left>
         <top>
            <AnchorPane fx:id="bp_top" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
               <children>
                  <Label fx:id="headlabel" alignment="CENTER" layoutX="737.0" layoutY="92.0" prefHeight="200.0" prefWidth="1920.0" text="Dashboard" textAlignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                     <font>
                        <Font size="48.0" />
                     </font>
                  </Label>
               </children>
            </AnchorPane>
         </top>
         <center>
            <AnchorPane fx:id="bp_center" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
         </center>
         <right>
            <AnchorPane fx:id="bp_right" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
         </right>
      </BorderPane>
   </children>
</AnchorPane>

______________________________________________

package main.java.controllers;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;

public class MainUIController{

    @FXML // ResourceBundle that was given to the FXMLLoader
    private ResourceBundle resources;

    @FXML // URL location of the FXML file that was given to the FXMLLoader
    private URL location;

    @FXML // fx:id="btn_search"
    private Button btn_search; // Value injected by FXMLLoader

    @FXML // fx:id="btn_movies"
    private Button btn_movies; // Value injected by FXMLLoader

    @FXML // fx:id="btn_exit"
    private Button btn_exit; // Value injected by FXMLLoader

    @FXML // fx:id="btn_series"
    private Button btn_series; // Value injected by FXMLLoader

    @FXML // fx:id="bp_right"
    private AnchorPane bp_right; // Value injected by FXMLLoader

    @FXML // fx:id="bp_bottom"
    private AnchorPane bp_bottom; // Value injected by FXMLLoader

    @FXML // fx:id="borderPane01"
    private BorderPane borderPane01; // Value injected by FXMLLoader

    @FXML // fx:id="headlabel"
    private Label headlabel; // Value injected by FXMLLoader

    @FXML // fx:id="bp_left_grid"
    private GridPane bp_left_grid; // Value injected by FXMLLoader

    @FXML // fx:id="bp_top"
    private AnchorPane bp_top; // Value injected by FXMLLoader

    @FXML // fx:id="root"
    private AnchorPane root; // Value injected by FXMLLoader

    @FXML // fx:id="btn_download"
    private Button btn_download; // Value injected by FXMLLoader

    @FXML // fx:id="btn_dashboard
    private Button btn_dashboard; // Value injected by FXMLLoader

    @FXML // fx:id="bp_center"
    private AnchorPane bp_center; // Value injected by FXMLLoader

    @FXML // fx:id="btn_settings"
    private Button btn_settings; // Value injected by FXMLLoader

    @FXML // This method is called by the FXMLLoader when initialization is complete
    void initialize() {
        assert root         != null : "fx:id=\"root\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert borderPane01 != null : "fx:id=\"borderPane01\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert bp_top       != null : "fx:id=\"bp_top\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert headlabel    != null : "fx:id=\"headlabel\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert bp_left_grid != null : "fx:id=\"bp_left_grid\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert bp_center    != null : "fx:id=\"bp_center\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert bp_right     != null : "fx:id=\"bp_right\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert bp_bottom    != null : "fx:id=\"bp_bottom\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_search   != null : "fx:id=\"btn_search\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_series   != null : "fx:id=\"btn_series\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_movies   != null : "fx:id=\"btn_movies\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_download != null : "fx:id=\"btn_download\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_settings != null : "fx:id=\"btn_settings\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_dashboard!= null : "fx:id=\"dashboard\" was not injected: check your FXML file 'MainUI.fxml'.";
        assert btn_exit     != null : "fx:id=\"btn_exit\" was not injected: check your FXML file 'MainUI.fxml'.";

        btn_search.setOnAction(value -> {
            System.out.println("Search pressed"); //TODO
        });
        btn_series.setOnAction(value ->{
            System.out.println("series pressed");
        });
        btn_movies.setOnAction(value ->{
            System.out.println("movies pressed");
        });
        btn_download.setOnAction(value ->{
            System.out.println("download pressed");
        });
        btn_settings.setOnAction(value ->{
            System.out.println("settings pressed");
        });
        btn_dashboard.setOnAction(value ->{
            System.out.println("dashboard pressed");
        });
        btn_exit.setOnAction(value ->{
            System.out.println("exit pressed");
        });


    }
}

编辑:这是我的包结构:

src
|-application
    |here is my main application
|-main
    |-java
        |-controllers
            |here are my controllers
        |-dao
        |-service
    |-ressources
        |-css
        |-images
        |-view
           |here are the fxml files

【问题讨论】:

  • 考虑到main/resources 只是你的类路径,你试过用getClass().getResource("/view/MainUI.fxml") 替换getClass().getResource("/main/ressources/view/MainUI.fxml") 吗?
  • 你也可以添加 fxml 的代码吗?我认为您的 fmxl 中的控制器也不正确。
  • 不确定,但我猜MainUIController 的包是错误的。 Caused by: java.lang.ClassNotFoundException: /java/controllers/MainUIController 表示该类在包中 java.controllers 但该类本身将包定义为:package main.java.controllers;
  • @ItachiUchiha 是的,我已经尝试过了:/
  • @Malaka 我编辑了我的帖子并将我的包结构添加到其中。你有什么建议?

标签: java xml javafx


【解决方案1】:

fx:controller 属性需要控制器类的完全限定类名。 IE。假设你有

package main.java.controllers ;

public class MainUIController { ... }

你应该有

fx:controller="main.java.controllers.MainUIController"

【讨论】:

  • 我已经试过了,但是谢谢。 :/ 但它并没有改变任何东西
  • 如果您阅读堆栈跟踪,很明显fx:controller 是问题所在。在阅读了您上面的 cmets 后,我稍微更新了答案。
  • 哇,对不起,伙计,我再次尝试了你的答案,并用 Malakas 对包架构的建议对其进行了改进,现在它工作得很好!太棒了:)
【解决方案2】:

我建议改变项目结构。资源不应驻留在源本身中。所以我的建议是以下项目结构:

src
|-main
    |-java <-- This should be your 'sources root'
        |-application <-- The application itself is within the new sources root
        |-controllers
            |here are my controllers
        |-dao
        |-service
    |-resources <-- all resources (css files, images, fxml files) should be with a subfolder of the resources. This folder should be marked as 'resources root'
        |-css
        |-images
        |-view
            |here are the fxml files

可以在任何 IDE 中设置此结构。如何设置它取决于 IDE 本身。通常,您只需右键单击概览中的文件夹并将其标记为源/资源根。 'source root' 和 'resources root' 的确切名称取决于 IDE。

Main 现在在包application 中,MainUIController 在包controllers 中。

在 FXML 文件中您应该指定:

fx:controller="controllers.MainUIController"

加载 FXML 文件应该可以使用:

AnchorPane root = (AnchorPane) FXMLLoader.load(getClass().getClassLoader().getResource("view/MainUI.fxml"));

作为下面解释的参考,看看here:
ClassLoader 始终从资源的根目录开始。如果只使用getClass,则资源的路径是相对路径。在处理了几次之后,我自己决定始终使用绝对路径,因此使用getClassLoader
如上面链接中所述,请注意

getClass().getClassLoader().getResource("view/MainUI.fxml");

可以替换为

getClass().getResource("view/MainUI.fxml");

我认为我在某处读到过,如果可用,最好直接使用InputStream,因为有时在 JAR 文件中处理 URL 可能会很棘手(但我目前找不到支持它的参考) .因此,作为getResource(..) 的替代方案,您可以使用:

FXMLLoader loader = new FXMLLoader();
Parent root = loader.load(getClass().getClassLoader().getResourceAsStream("view/MainUI.fxml");

【讨论】:

  • 是的,谢谢。除了应用程序文件夹位于 java 文件夹内之外,它就像那样。文本框一定弄乱了我的间距
  • 您可以使用 JavaFX Maven archetype 生成 MalaKa 建议的布局(尽管如果您不熟悉 Maven,它可能会让您感到困惑,而不仅仅是帮助)。
  • 嗯.. getClassLoader() - 似乎是未知的.. 我错过了这里的任何导入吗?
  • @PooBucket 是的,很抱歉。请查看更新后的行,应该可以。
  • 作为对FXMLLoader 的另一个说明,如果您使用load(InputStream) 方法,您将丢失任何基于位置的信息:即Location Resolution 在您的FXML 中不起作用。如果您有 FXML 资源(文件等),那么您应该使用基于 URL 的加载; imo您应该只在极少数情况下使用 InputStream 加载“即时”生成流(即没有资源)。我更喜欢FXMLLoader l = new FXMLLoader(URL); Parent root = l.load();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 2018-06-19
  • 1970-01-01
相关资源
最近更新 更多