为什么我的JavaFX控制器没有加载?

时间:2017-08-24 23:38:27

标签: java javafx fxml

我希望有人可以向我解释我做错了什么,或者如果以前已经回答过,请指出我的答案(我已经在这里找了2天寻找答案)。

我正在尝试创建一个启动JavaFX GUI的演示应用程序。当我的应用程序准备启动GUI(应用程序必须先在后台处理事情)时,我打电话给:

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

这是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位于JAR文件&是与StarFXDemo相同的包(而不是在另一个包或子包中)。所以

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

返回文件的URL。

StarFXDemoDoc.fxml是这样的:

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

StarFXDemoDocController.java是这样的:

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()
    {

    }
}

这些方法中还没有真正的东西,因为我只是试图让GUI出现在这个时候。我有空构造函数,以及带有fx:id标记的GUI元素上的@FXML标记(以及它们对应的方法)。

当我运行程序时,我打电话

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

它抛出以下异常(此异常不再相关,请参阅下面的异常):

我假设我的格式错误,但我不知道它是什么。

有人可以帮助我吗?

EDIT / UPDATE:

根据James_D的评论(谢谢詹姆斯,很明显我一直在盯着它看太久......),我在我的控制器中修复了明显的错误并使SimNameField成为TextField,而不是Label (并更新了上面的代码块以反映这一点)。我还更改了异常处理以使用printStackTrace。这些更改现在让我得到以下堆栈跟踪:

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                                                 

所以我看到了ClassNotFoundException,它让我开始更多地查看我的控制器类,并且我注意到Scene Builder几乎已经确定我的TextField不作为标记项存在(当我分配时) fx:simNameField的id到Scene Builder中的TextField,我得到&#34; No injectable字段......&#34;警告,右键单击控件的fx:id字段只显示buildSphereButton标记。所以我从控制器类中删除了simNameField,右键单击了NetBeans中的FXML文件,并将其告诉Make Controller。它将TextField添加回正确的fx:id和@FXML标记。 Scene Builder仍然认为它是一个没有可注入字段的fx:id。

所以我显然在FXML和控制器之间有某种脱节方式,但我不知道它可能是什么?

UPDATE2:

取出第一个堆栈跟踪,因为它不再相关并更新了几行代码(比如将包的导入添加到FXML)。

一直在玩它。如果我删除控制器引用,GUI将按预期启动(因此我们知道FXML文件正在加载)。如果我实例化一个Controller对象(在我调用FXMLLoader.load(&lt; ...&gt;)之前),它会按预期实例化,我可以通过NetBeans调试器验证它是否为null,所以我知道控制器类编译,并在类路径上。

那么为什么FXMLLoader无法找到它呢?我应该使用替代方法来加载它吗?我已经考虑过只是在代码中创建控制器对象并以这种方式设置它,但是当涉及到fx:controller语句时,这似乎会让NetBeans感到烦恼(即如果你在FXML中有需要控制器的元素,并且该声明不在其中,NetBeans将其标记为不正确)。

2 个答案:

答案 0 :(得分:4)

在FXML中你有

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

但你在控制器中

@FXML
private Label SimNameField ;

这会尝试将文本字段分配给Label类型的字段,这会在运行时导致错误。

答案 1 :(得分:0)

对于任何遇到过这种情况的人来说,我确实在一个时尚之后解决了这个问题。我仍然不知道为什么发布的设置不起作用,我认为它与路径和包引用有关。

无论如何,我能够让它像这样工作:

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

现在它按预期工作。