首页 文章

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

提问于
浏览
0

我希望有人可以向我解释我做错了什么,或者如果以前已经回答了这个问题,请指出我的答案(我已经在这里找了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"));

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

我假设我有一些格式错误,但我不知道它是什么 .

有人可以帮我从这里出去吗?

编辑/ 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不存在作为标记项(当我指定simNameField的fx:id时在Scene Builder中的TextField中,我得到“No injectable field ...”警告,右键单击控件的fx:id字段只显示buildSphereButton标记 . 所以我从控制器类中删除了simNameField,右键单击了NetBeans中的FXML文件,并将其告诉Make Controller . 它将TextField添加回正确的fx:id和@FXML标记 . Scene Builder仍然认为它是一个没有可注入字段的fx:id .

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

UPDATE2:

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

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

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

2 回答

  • 4

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

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

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

    现在它按预期工作 .

  • 0

    在FXML中你有

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

    但在控制器中你有

    @FXML
    private Label SimNameField ;
    

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

相关问题