Javafx位置是必需的(从另一个文件夹/包加载FXML文件) [英] Javafx location is required (loading FXML file from another folder/package)

查看:183
本文介绍了Javafx位置是必需的(从另一个文件夹/包加载FXML文件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Java和FXML文件时遇到了问题。

I have an issue using Java with FXML files.

我现在搜索了几个小时,找不到任何可以解决我问题的东西,所以我最后的希望就是针对我的具体案例提出问题(我知道的是问题如这一个和其他人在这方面没有真正帮助我。

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.

简单的解释:我有一个Eclipse Java项目,我的(这个问题很重要)类在包[Project]中名称] /src/measurements.gui。我的FXML文件位于[项目名称] /资源文件夹中。

Simple explanation: I have an Eclipse Java Project and my (important for this question) classes are in the package [Project Name]/src/measurements.gui. My FXML file is in the folder [Project Name]/resources.

我加载FXML文件的类ElementProperties.java看起来像这个:

My class that loads the FXML file ElementsProperties.java looks like this:

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;
    }
}}

FXML文件显示为对话框以下简单行:
ElementsProperties.show(parent,TestWindow);

The FXML file is shown as a dialog with the following simple line: ElementsProperties.show(parent, "TestWindow");

我的FXML文件(使用JavaFXSceneBuilder 2.0创建)如下所示:
`

My FXML file (created with the JavaFXSceneBuilder 2.0) looks like this: `

<?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.

。如果我将FXML文件移动到与主类相同的包中,即为measurements.gui,并将ELementsProperties.java类的show-method中的filePath更改为TestWindow.fxml,一切正常,我在应用程序中看到了创建的窗口。但我希望将fxml文件放在单独的资源文件夹中,以方便插入其他fxml文件。

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. But I want to have the fxml file in the seperate resource folder for convenience of inserting other fxml files.

我希望我能清楚地解释我的问题,你可以帮我解决这个。有关如何从与主类不同的包加载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? Btw, things I've already tried are:


  1. 将资源文件夹添加到类路径

  2. 将路径设置为/resources/TestWindow.fxml(开头的正斜杠

  3. 使用 getClass() .getClassLoader()。getResource(filePath)作为FXMLLoader加载方法的参数

  1. adding the resource folder to the class path
  2. set the path to "/resources/TestWindow.fxml" (with the forward slash at the beginning
  3. use getClass().getClassLoader().getResource(filePath) as parameter for the FXMLLoader's load method

提前谢谢。

推荐答案

谢谢,Roland,链接。我试图复制文件夹结构并出现了以下(对于可能遇到同样问题的其他人):

Thanks, Roland, for the link. I've tried to copy the folder structure and came up with the following (for others who might have the same problem):

我创建了一个测试项目JavaFXTest。我在包org.example.main中有一个主类。像往常一样,该软件包位于项目的src文件夹中。

I created a test project JavaFXTest. I have one main class in the package org.example.main. The package is, as usual, in the src folder of the project.

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);
    }
}

我在src中创建了一个普通文件夹resources夹。该资源文件夹仅包含我的TestWindow.fxml文件,该文件与我上面的问题完全相同。
现在,当我启动应用程序时,找到并显示fxml文件作为主窗口。

I created a normal folder "resources" in the src folder. That resource folder contains only my TestWindow.fxml file which is exactly the same as in my question above. Now, the fxml file is found and displayed as the main window when I start the application.

所以解决方案实际上是移动资源文件夹进入 src文件夹,对我的案例来说仍然是一个可行的解决方案。我只是不希望最终用户不得不在其他软件包的深处探索以保存自己的fxml文件。

So the solution was actually to move the resources folder into the src folder, which is still a viable solution for my case. I just didn't want the enduser to have to poke around in the depths of other packages to save his own fxml file.

再次感谢Roland指点我这个解决方案。

Again, thanks, Roland, for pointing me towards that solution.

这篇关于Javafx位置是必需的(从另一个文件夹/包加载FXML文件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆