2015-02-01 2 views
0

У меня проблема с использованием Java с файлами FXML.Требуется местоположение Javafx (загрузка файла FXML из другой папки/пакета)

Я искал часы и не нашел ничего, что могло бы решить мою проблему, поэтому моя последняя надежда состоит в том, чтобы задать вопрос для моего конкретного случая (я знаю вопрос, например, this one и другие, но никто мне не помог в этом отношении.

Простое объяснение: У меня есть проект Java Eclipse, и мой (важный для этого вопроса) класс находится в пакете [Имя проекта] /src/measurements.gui. Мой файл FXML находится в папке [Название проекта ]/ресурсы

Мой класс, который загружает файл 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; 
    } 
}} 

Файл FXML отображается в диалоговом окне с помощью следующей простой линии: ElementsProperties.show(parent, "TestWindow");

Моего файла 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> 

Это на самом деле все, что нужно. Если я попытаюсь запустить программу и открыть диалоговое окно, Исключение

java.lang.NullPointerException: Location is required. 

дано. Если я перетащил файл FXML в тот же пакет, что и основной класс, и это будет Measure.gui, и изменим filePath в show-method класса ELementsProperties.java на "TestWindow.fxml", все работает отлично, и я вижу созданное окно в своем приложении , Но я хочу иметь файл fxml в отдельной папке ресурсов для удобства вставки других файлов fxml.

Надеюсь, я смог бы четко объяснить свою проблему, и вы можете помочь мне решить эту проблему. Любые идеи о том, как загрузить файлы fxml из другого пакета, кроме основного? Btw, то я уже пробовал это:

  1. добавление папки ресурсов в пути класса
  2. установить путь к «/resources/TestWindow.fxml» (с косой чертой в начале
  3. использование getClass().getClassLoader().getResource(filePath) в качестве параметра для метода загрузки в FXMLLoader в

Спасибо заранее.

+0

Мой ответ здесь может быть полезным: http://stackoverflow.com/questions/23975897/how-to-add-a-css-stylesheet-in-fxml/28123426#28123426 ... и если нет, пожалуйста предоставить полный проверенный пример, а не только некоторые части вашей проблемы. – Roland

+0

Спасибо, @Roland! Эта структура папок дала мне толчок, который мне нужен. Извините, если я не был достаточно ясен о своей проблеме, я думал, что написал все, что нужно знать об этой проблеме. – Chris777

ответ

0

Спасибо, Роланд, за ссылку. Я попытался скопировать структуру папок и придумал следующее (для других, у кого может быть такая же проблема):

Я создал тестовый проект JavaFXTest. У меня есть один основной класс в пакете org.example.main. Пакет, как обычно, находится в папке src проекта.

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. Эта папка ресурса содержит только мой файл TestWindow.fxml, который точно такой же, как в моем вышеперечисленном вопросе. Теперь файл fxml находится и отображается в качестве основного окна при запуске приложения.

Таким образом, решение было фактически переместить папку ресурсов в папку src, которая по-прежнему является жизнеспособным решением для моего дела. Я просто не хотел, чтобы enduser должен был выкапывать в глубину других пакетов, чтобы сохранить свой собственный файл fxml.

Еще раз спасибо, Роланд, за то, что указал на это решение.

+0

Просто не связанный комментарий: 'FXMLLoader.load (URL)' является статическим методом; вы не вызываете его на созданный вами экземпляр 'fxmlLoader' (и который вы никогда не используете). Вы должны удалить экземпляр 'fxmlLoader' и вызвать статический метод обычным способом:' Parent content = FXMLLoader.load (...); '(или указать местоположение на экземпляре' fxmlLoader' и вызвать no-argument ' load() '). –

+0

На самом деле, я думал, что статические методы загрузки из FXMLLoader (планируются) устарели. Вот почему я пошел на этот подход. – Chris777

+0

Было такое обсуждение, но я не знаю, было ли это решение (возможно, это было). Однако ваш код по-прежнему вызывает статический метод. –

Смежные вопросы