简体   繁体   English

需要Javafx位置(从另一个文件夹/程序包加载FXML文件)

[英]Javafx location is required (loading FXML file from another folder/package)

I have an issue using Java with FXML files. 我在将Java与FXML文件一起使用时遇到问题。

I searched for hours now and couldn't find anything that solves my problem, so my last hope is to ask the question for my specific case (I'm aware of question like this one and others but none really helped me in this regard. 我现在搜索了几个小时,却找不到能解决我问题的任何东西,所以我的最后希望是针对我的具体情况提出问题(我知道像这样的问题和其他问题,但在这方面没有一个真正的帮助我。

Simple explanation: I have an Eclipse Java Project and my (important for this question) classes are in the package [Project Name]/src/measurements.gui. 简单说明:我有一个Eclipse Java Project,并且我的(对于这个问题很重要)类位于软件包[Project Name] /src/measurements.gui中。 My FXML file is in the folder [Project Name]/resources. 我的FXML文件在[项目名称] /资源文件夹中。

My class that loads the FXML file ElementsProperties.java looks like this: 加载FXML文件ElementsProperties.java的类如下所示:

import java.io.IOException;

import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;

public class ElementsProperties {

  public static void show(Window parent, String title) {

    ElementsProperties el = new ElementsProperties();
    BorderPane root = el.loadFXMLFile("resources/TestWindow.fxml");

    Stage dialog = new Stage();
    dialog.initOwner(parent);
    dialog.setTitle(title);
    dialog.initModality(Modality.WINDOW_MODAL);
    dialog.setScene(new Scene(root));
    dialog.show();
  }

  @SuppressWarnings({ "finally", "static-access" })
  private BorderPane loadFXMLFile(String filePath) {
    BorderPane borderPane = null;
    try {
      borderPane = new BorderPane();
      FXMLLoader fxmlLoader = new FXMLLoader();
      Parent content = fxmlLoader.load(getClass().getResource(filePath));
      borderPane.setCenter(content);
    }
    catch (IOException e) {
      e.printStackTrace();
      System.err.println("Couldn't find the specified file");
    }
    catch(Exception e){
      e.printStackTrace();
    }
    finally {
     return borderPane;
    }
}}

The FXML file is shown as a dialog with the following simple line: ElementsProperties.show(parent, "TestWindow"); FXML文件显示为带有以下简单行的对话框: ElementsProperties.show(parent, "TestWindow");

My FXML file (created with the JavaFXSceneBuilder 2.0) looks like this: ` 我的FXML文件(使用JavaFXSceneBuilder 2.0创建)如下所示:

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

<?import javafx.scene.effect.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
  <children>
    <MenuBar VBox.vgrow="NEVER">
      <menus>
        <Menu mnemonicParsing="false" text="File">
          <items>
            <MenuItem mnemonicParsing="false" text="New" />
            <MenuItem mnemonicParsing="false" text="Open…" />
            <Menu mnemonicParsing="false" text="Open Recent" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Close" />
            <MenuItem mnemonicParsing="false" text="Save" />
            <MenuItem mnemonicParsing="false" text="Save As…" />
            <MenuItem mnemonicParsing="false" text="Revert" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Preferences…" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Quit" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Edit">
          <items>
            <MenuItem mnemonicParsing="false" text="Undo" />
            <MenuItem mnemonicParsing="false" text="Redo" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Cut" />
            <MenuItem mnemonicParsing="false" text="Copy" />
            <MenuItem mnemonicParsing="false" text="Paste" />
            <MenuItem mnemonicParsing="false" text="Delete" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Select All" />
            <MenuItem mnemonicParsing="false" text="Unselect All" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Help">
          <items>
            <MenuItem mnemonicParsing="false" text="About MyHelloApp" />
          </items>
        </Menu>
      </menus>
    </MenuBar>
    <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
      <children>
        <Label alignment="CENTER" layoutX="155.0" layoutY="177.0" style="&#10;" text="Drag components from Library here…" textAlignment="CENTER" textFill="#9f9f9f" wrapText="false">
          <font>
            <Font size="18.0" />
          </font>
        </Label>
            <GridPane layoutX="-2.0" layoutY="-3.0" prefHeight="407.0" prefWidth="659.0">
              <columnConstraints>
                <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>
               <children>
                  <HBox prefHeight="134.0" prefWidth="654.0" spacing="20.0" GridPane.rowIndex="1">
                     <children>
                        <Button mnemonicParsing="false" prefHeight="46.0" prefWidth="60.0" text="Click me" wrapText="true" />
                        <Button mnemonicParsing="false" prefHeight="47.0" prefWidth="73.0" text="No, click me" wrapText="true" />
                        <Button mnemonicParsing="false" prefHeight="46.0" prefWidth="120.0" text="Don't you dare click me" wrapText="true" />
                     </children>
                     <padding>
                        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
                     </padding>
                  </HBox>
                  <TextField promptText="Type something here..." GridPane.columnIndex="1" GridPane.rowIndex="1">
                     <GridPane.margin>
                        <Insets left="20.0" right="20.0" />
                     </GridPane.margin>
                  </TextField>
               </children>
            </GridPane>
      </children>
    </AnchorPane>
  </children>
</VBox>

This is actually all that is needed. 实际上,这就是所需要的。 If I try to run the programm and make the dialog show up, the Exception 如果我尝试运行程序并显示对话框,则异常

java.lang.NullPointerException: Location is required.

is given. 给出。 If I move the FXML file into the same package as the main class, being measurements.gui, and change the filePath in the ELementsProperties.java class' show-method to "TestWindow.fxml" , it all works fine and I see the created window in my application. 如果我将FXML文件移动到与主类相同的包中,即Measurements.gui,并将ELementsProperties.java类的show-method中的filePath更改为"TestWindow.fxml" ,那么一切正常,我看到创建的我的应用程序中的窗口。 But I want to have the fxml file in the seperate resource folder for convenience of inserting other fxml files. 但我想将fxml文件放在单独的资源文件夹中,以便于插入其他fxml文件。

I hope I could explain my problem clearly and you can help me solve this. 希望我能清楚地解释我的问题,并且您可以帮助我解决这个问题。 Any ideas on how to load fxml files from a different package than the main class is? 关于如何从不同于主类的包中加载fxml文件的任何想法? Btw, things I've already tried are: 顺便说一句,我已经尝试过的事情是:

  1. adding the resource folder to the class path 将资源文件夹添加到类路径
  2. set the path to "/resources/TestWindow.fxml" (with the forward slash at the beginning 将路径设置为“ /resources/TestWindow.fxml”(以正斜杠开头
  3. use getClass().getClassLoader().getResource(filePath) as parameter for the FXMLLoader's load method 使用getClass().getClassLoader().getResource(filePath)作为FXMLLoader的加载方法的参数

Thank you in advance. 先感谢您。

Thanks, Roland, for the link. 感谢Roland提供的链接。 I've tried to copy the folder structure and came up with the following (for others who might have the same problem): 我试图复制文件夹结构,并提出了以下建议(适用于可能存在相同问题的其他人):

I created a test project JavaFXTest. 我创建了一个测试项目JavaFXTest。 I have one main class in the package org.example.main. 我在org.example.main包中有一个主类。 The package is, as usual, in the src folder of the project. 像往常一样,该软件包位于项目的src文件夹中。

MyJavaFXDialog.java: MyJavaFXDialog.java:

package org.example.main;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class MyJavaFXDialog extends Application{

    public void start(Stage primaryStage) {

    MyJavaFXDialog javaFx = new MyJavaFXDialog();
    BorderPane root = javaFx.loadFXMLFile("/resources/TestWindow.fxml");

    Stage dialog = new Stage();
    dialog.initModality(Modality.WINDOW_MODAL);
    dialog.setScene(new Scene(root));
    dialog.show();
    }

    @SuppressWarnings({ "finally", "static-access" })
    private BorderPane loadFXMLFile(String filePath) {
    BorderPane borderPane = null;
    try {
        borderPane = new BorderPane();
        FXMLLoader fxmlLoader = new FXMLLoader();
        Parent content = fxmlLoader.load(getClass().getResource(filePath));
        borderPane.setCenter(content);
    }
    catch (IOException e) {
        e.printStackTrace();
        System.err.println("Couldn't find the specified file");
    }
    catch(Exception e){
        e.printStackTrace();
    }
    finally {
        return borderPane;
    }
    }

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

I created a normal folder "resources" in the src folder. 我在src文件夹中创建了一个普通文件夹“ resources”。 That resource folder contains only my TestWindow.fxml file which is exactly the same as in my question above. 该资源文件夹仅包含我的TestWindow.fxml文件,该文件与上述问题完全相同。 Now, the fxml file is found and displayed as the main window when I start the application. 现在,当我启动应用程序时,找到了fxml文件并将其显示为主窗口。

So the solution was actually to move the resources folder into the src folder, which is still a viable solution for my case. 因此,解决方案实际上是将资源文件夹移至 src文件夹,对于我的情况而言,这仍然是可行的解决方案。 I just didn't want the enduser to have to poke around in the depths of other packages to save his own fxml file. 我只是不希望最终用户不得不在其他软件包的最深处四处摸索以保存自己的fxml文件。

Again, thanks, Roland, for pointing me towards that solution. 再次感谢Roland向我指出该解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM