0
votes

I'm hoping someone can either explain to me what I am doing wrong, or point me to the answer if this has been answered previously (I've been rooting around hereabouts for 2 days looking for an answer).

I am trying to create an demo application that launches a JavaFX GUI. When my app is ready to launch the GUI (the app has to take care of things in the background first), I call:

Application.launch(StarFXDemo.class, "");

Here is StarFXDemo.java:

package standalonedemo;

import java.io.IOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class StarFXDemo extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        Parent root = null;
        try
        {
            root = FXMLLoader.load(getClass().getResource("StarFXDemoDoc.fxml"));
        } catch (IOException ioe)
        {
            ioe.printStackTrace(System.out);
        }

        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
}

StarFXDemoDoc.fxml is in the JAR file & is the same package as StarFXDemo (rather than in another package or in a sub package). So

getClass().getResource("/standalonedemo/resources/StarFXDemoDoc.fxml")

Comes back with a URL to the file.

StarFXDemoDoc.fxml is this:

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

<?import standalonedemo.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<TitledPane animated="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="FX Sim Demo" 
            xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
           fx:controller="standalonedemo.StarFXDemoDocController">
  <content>
    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
         <children>
            <VBox prefHeight="85.0" prefWidth="322.0" spacing="5.0" style="-fx-background-color: coral;">
               <children>
                  <Label text="Sim Title" />
                  <TextField fx:id="SimNameField" onMouseDragExited="#setSimulationName" />
               </children>
               <padding>
                  <Insets left="25.0" top="15.0" />
               </padding>
            </VBox>
            <Button fx:id="BuildSphereButton" layoutX="14.0" layoutY="100.0" mnemonicParsing="false" onAction="#buildSphereAction" text="Build Sphere" />
         </children></AnchorPane>
  </content>
</TitledPane>

And StarFXDemoDocController.java is this:

package standalonedemo;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

public class StarFXDemoDocController implements Initializable
{
    @FXML
    private TextField SimNameField;
    @FXML
    private Button BuildSphereButton;

    /**
     * RequiredConstructor
     */
    public StarFXDemoDocController() {}

    @Override
    public void initialize(URL url, ResourceBundle rb)
    {

    } 

    @FXML
    private void buildSphereAction(ActionEvent event)
    {

    }

    @FXML
    private void setSimulationName()
    {

    }
}

There is nothing really in the methods yet because I'm just trying to get the GUI to appear at this time. I have the empty constructor, and the @FXML tags on the GUI elements with fx:id tags (as well as their corresponding methods).

When I run the program, at the point I call

FXMLLoader.load(getClass().getResource("/standalonedemo/resources/StarFXDemoDoc.fxml"));

it throws the following exception (this exception is no longer relevant, see the exception below):

I am assuming I have something formatted wrong, but I have no idea what it is.

Can anyone help me out here?

EDIT/UPDATE:

As per James_D's comments (thank you James, obviously I had been staring at that for way too long...), I fixed the obvious error in my controller and made SimNameField a TextField, rather than a Label (and updated the code block above to reflect this). I also changed the exception handling to use printStackTrace. The changes now get me the following stack trace:

javafx.fxml.LoadException: file:<properPathTo>/StandAloneDemo/dist/StandAloneDemo.jar!/standalonedemo/resources/StarFXDemoDoc.fxml:11
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:103)             
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:922)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)                
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)           
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)                       
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)                                  
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)                                  
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)                                      
at standalonedemo.StarFXDemo.start(StarFXDemo.java:35)                                    
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)        
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)              
at java.security.AccessController.doPrivileged(Native Method)                                  
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)          
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)            
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)                                 
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)                 
at java.lang.Thread.run(Thread.java:745)                                                       
Caused by: java.lang.ClassNotFoundException: standalonedemo.StarFXDemoDocController starting from SystemClassLoader[55 modules] with possible defining loaders null and declared parents [org.netbeans.MainImpl$BootClassLoader@97e1986, ModuleCL@1fa50985[org.netbeans.api.annotations.common], ModuleCL@7251b0ac[org.openide.awt], ModuleCL@7d1344a8[org.netbeans.api.progress], ModuleCL@26b9eb92[org.netbeans.swing.plaf], ModuleCL@7feb85da[org.openide.dialogs], ModuleCL@15c98cea[org.openide.nodes], ModuleCL@ed11c24[org.openide.windows], ModuleCL@621f6603[org.netbeans.swing.tabcontrol], ModuleCL@2a3ed4eb[org.netbeans.swing.outline], ...40 more]                                                  
at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:224)                                                                                                                                                         
at org.netbeans.ModuleManager$SystemClassLoader.loadClass(ModuleManager.java:722)                                                                                                                                             
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)                                                                                                                                                                      
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:920)                                                                                                                                                  
... 22 more                                                                                                                                                                                                                   
Caused by: java.lang.ClassNotFoundException: standalonedemo.StarFXDemoDocController                                                                                                                                                   
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)                                                                                                                                                                 
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)                                                                                                                                                                      
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)                                                                                                                                                              
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)                                                                                                                                                                      
at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:222)                                                                                                                                                         
... 25 more                                                 

So I see the ClassNotFoundException, which got me to start looking at my controller class some more, and I noticed that Scene Builder has all but decided that my TextField doesn't exist as a tagged item (when I assign the fx:id of simNameField to the TextField in Scene Builder, I get the "No injectable field..." warning, and right clicking on the fx:id field for the control only shows the buildSphereButton tag). So I removed the simNameField from the controller class, right clicked on the FXML file in NetBeans, and told it to Make Controller. It added the TextField back with the correct fx:id and @FXML tag. Scene Builder still thinks it's an fx:id without an injectable field.

So I obviously have some manner of disconnect between the FXML and the controller, but I have no clue what it could be?

UPDATE2:

Took out the first stack trace, as it was no longer relevant and updated a few lines of code (like adding the import for the package to the FXML).

Been playing with it. If I remove the controller reference, the GUI launches as expected (so we know the FXML file is loading). If I instantiate a Controller object (before I call FXMLLoader.load(<...>)), it instantiates as expected, and I can verify that it is not null through the NetBeans debugger, so I know that the controller class is compiled, and on the class path.

So why can't the FXMLLoader find it? Should I be using an alternative method to load it? I've thought about just creating the controller object in the code and setting it that way, but that seems to annoy NetBeans when it comes to the fx:controller statement (i.e. If you have elements in the FXML that require a controller, and that statement isn't in there, NetBeans flags it as incorrect).

2
That doesn't look like the complete stack trace. Usually there are "Caused by" sections in there (and it usually has different formatting, etc) - James_D
Actually, the "caused by" sections you didn't post should say fairly clearly that you are trying to assign a TextField to a Label... - James_D
That was all the stack trace I got from the IOException (I added loop to the catch block to get the full stack trace). Is there another Exception I should have been looking to catch that would give out more? - sngillis
No, you should be doing iOException.printStackTrace() in the catch block. - James_D
I updated the question. - sngillis

2 Answers

4
votes

In the FXML you have

<TextField fx:id="SimNameField" onMouseDragExited="#setSimulationName" />

but in the controller you have

@FXML
private Label SimNameField ;

This tries to assign a text field to a field of type Label, which will cause an error at run time.

0
votes

FYI for anyone who runs across this, I did solve the problem after a fashion. I still have no idea why the posted setup did not work, I'm thinking it has something to do with paths and package references.

Anyway, I was able to make it work like this:

URL fxmlFile = getClass().getResource("/standalonedemo/resources/StarFXDemoDoc.fxml");
StarFXDemoDocController sdCon = new StarFXDemoDocController();
FXMLLoader loader = new FXMLLoader(fxmlFile);
loader.setController(sdCon);
root = (TitledPane) loader.load();

Now it works as expected.