2017-08-24 106 views
0

我希望有人可以向我解釋我做錯了什麼,或者如果這個答案以前答案指向我的答案(我一直在附近尋找2天尋找答案)。爲什麼我的JavaFX控制器沒有加載?

我正在嘗試創建一個啓動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 ,而不是標籤(並更新了上面的代碼塊來反映這一點)。我還將異常處理更改爲使用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 [[email protected], [email protected][org.netbeans.api.annotations.common], [email protected][org.openide.awt], [email protected][org.netbeans.api.progress], [email protected][org.netbeans.swing.plaf], [email protected][org.openide.dialogs], [email protected][org.openide.nodes], [email protected][org.openide.windows], [email protected][org.netbeans.swing.tabcontrol], [email protected][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的,這讓我開始尋找我的控制器類多一些,而且我注意到,場景生成器幾乎已經決定,我的文本字段沒有按不存在作爲標記的項目(當我將simNameField的fx:id分配給Scene Builder中的TextField時,我得到「No injectable field ...」警告,並右鍵單擊僅用於控件的fx:id字段顯示buildSphereButton標籤)。因此,我從控制器類中刪除了simNameField,右鍵單擊NetBeans中的FXML文件,並將其告知Make Controller。它使用正確的fx:id和@FXML標籤添加了TextField。場景生成器仍然認爲這是一個沒有可注射字段的fx:id。

所以我明顯有一些FXML和控制器之間的斷開方式,但我不知道它可能是什麼?

UPDATE2:

拿出第一堆棧跟蹤,因爲它已不再是相關的和更新的幾行代碼(如添加導入該包到FXML)。

一直在玩它。如果我刪除了控制器引用,則GUI將按預期啓動(這樣我們就知道FXML文件正在加載)。如果我實例化一個Controller對象(在我調用FXMLLoader.load(< ...>)之前),它按預期方式實例化,並且我可以通過NetBeans調試器驗證它是否爲空,所以我知道該控制器類已編譯,並在班級路徑上。

那麼爲什麼FXMLLoader不能找到它呢?我應該使用替代方法來加載它嗎?我想過只是在代碼中創建控制器對象並設置它,但是當涉及到fx:controller語句時,這似乎讓NetBeans煩惱(即,如果FXML中的元素需要控制器,那麼語句不在那裏,NetBeans將其標記爲不正確)。

+1

這看起來不像完整的堆棧跟蹤。通常在那裏有「由...引起」的部分(通常有不同的格式等) –

+2

實際上,你沒有發佈的「由...引起」的部分應該相當清楚地表明你正試圖給一個「TextField」分配一個'Label' ... –

+0

這就是我從IOException獲得的所有堆棧跟蹤(我將循環添加到catch塊以獲取完整的堆棧跟蹤)。 是否有另一個例外,我應該一直在尋找,會給出更多? – sngillis

回答

4

在FXML你有

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

但在控制器,你有

@FXML 
private Label SimNameField ; 

這將嘗試一個文本字段分配給Label類型的字段,這將導致在運行錯誤時間。

+0

血腥地獄,我怎麼錯過了? – sngillis

+1

@sngillis通過不顯示和閱讀完整的堆棧跟蹤... :) –

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

現在按預期工作。

相關問題