0

So I'm coding this chat-client for a school project, and now I need to implement a GUI, using JavaFX. I've built a neat looking GUI in Scene Builder. Whenever the client recieves a message it should now call a method in the controller to append the recived string to a TextField.

However, when I try to load the controller from the FXML-file I get this error:

null/../../../../img/jim.png
javafx.fxml.LoadException: 
unknown path:16

at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2425)
at com.example.main.GUI.start(GUI.java:46)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$176(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
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.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1100)
at javafx.scene.image.Image.<init>(Image.java:681)
at com.sun.javafx.fxml.builder.JavaFXImageBuilder.build(JavaFXImageBuilder.java:47)
at com.sun.javafx.fxml.builder.JavaFXImageBuilder.build(JavaFXImageBuilder.java:37)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:763)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
... 11 moreCaused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1092)
... 17 more

Here's my code for getting the controller and calling a method in it:

    try {
        FXMLLoader loader = new FXMLLoader();
        Pane p = loader.load(getClass().getResource("ChatForm.fxml").openStream());
        ChatForm chatForm = (ChatForm) loader.getController();
        chatForm.test();
    } catch (IOException e) {
        e.printStackTrace();
    }

Finally, my FXML file:

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

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

<AnchorPane prefHeight="410.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.main.ChatForm">
   <children>
      <VBox prefHeight="410.0" prefWidth="300.0">
         <children>
            <ImageView fitHeight="135.0" fitWidth="300.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../../../../img/jim.png" />
               </image>
            </ImageView>
            <TextArea fx:id="chatTextArea" editable="false" focusTraversable="false" prefHeight="232.0" prefWidth="300.0" wrapText="true" />
            <TextField fx:id="messageTextField" />
            <Label text="Skriv &quot;.disconnect&quot; för att logga ut">
               <font>
                  <Font size="10.0" />
               </font>
            </Label>
     </children>
  </VBox>

Clearly something strange is up when loading the logo-image. Any ideas?

Happy new year's!

1 Answer 1

3

The syntax url="@..." in your FXML file refers to a path relative to the current FXMLLoader's location property.

However, when you load the FXML file, you are not providing the FXMLLoader with a location, but an input stream. Thus the location is null and (as seen in the stack trace), your path gets interpreted as

null/../../../../img/jim.png

To fix this, provide the location to the FXMLLoader, instead of the input stream:

try {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("ChatForm.fxml"));
    Pane p = loader.load();
    ChatForm chatForm = (ChatForm) loader.getController();
    chatForm.test();
} catch (IOException e) {
    e.printStackTrace();
}

This will fix the immediate problem, assuming the path is actually correct. I think you still have other, essentially unrelated, problems, as you never seem to do anything with the scene graph you load (i.e. you never display the pane p).

Sign up to request clarification or add additional context in comments.

3 Comments

It did fix the problem, and you're right, it doesn't do what I wanted it to do. This simply gives me a copy of the controller, and no the same instance as I'm using in another class, doesn't it? I need the same instance, to be able to manipulate the TextField in it.
Yes, exactly. So you just need to call getController() in the same way when you load the actual FXML you display, and make that controller instance available where you need it. That's a different question entirely, though...
Alright, James. Totaly new to this stuff. Thanks for your time :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.