2014-01-22 27 views
1

我正嘗試使用JavaFX和多個FXML文件中的自定義控件。我創建一個自定義控制:Java FX使用多個FXML文件獲得自定義控件的工作

public class PetListGUIManager extends BorderPane 
{ 
    @FXML ListView<String> petList; 

    private PetManager pm; 

    public PetListGUIManager() 
    { 
     try 
     { 
      FXMLLoader loader = new FXMLLoader(getClass().getResource("PetList.fxml")); 

      loader.setRoot(this); 
      loader.setController(this); 

      loader.load(); 

     } 
     catch (IOException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     pm = new PetManager(); 

     ObservableList<String> items = FXCollections.observableArrayList(pm.getDisplayablePets()); 

     petList.setItems(items); 
    } 

    @FXML 
    public void handleButtonAction(ActionEvent event) 
    { 
     Button b = (Button) event.getSource(); 
     b.setText("Clicked!"); 
    } 
} 

使用此FXML文件:

<fx:root type="javafx.scene.layout.BorderPane" xmlns:fx="http://javafx.com/fxml"> 
    <bottom> 
    <Button onAction="#handleButtonAction" text="Click Me!" /> 
    </bottom> 
    <center> 
    <ListView fx:id="petList" prefHeight="200.0" prefWidth="200.0" /> 
    </center> 
</fx:root> 

然後我用這等主要程序:

public class TestMain extends Application 
{ 
    PetListGUIManager pm; 
    @FXML FlowPane mainPane; 

    @Override 
    public void start(Stage stage) throws Exception 
    { 

     Parent root = FXMLLoader 
       .load(getClass().getResource("Main.fxml")); 

     Scene scene = new Scene(root); 

     stage.setTitle("Test Main"); 
     stage.setScene(scene); 
     stage.show(); 


     pm = new PetListGUIManager(); 

    } 
    /** 
    * Purpose: 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     Application.launch(args); 
    } 

    @FXML 
    public void doSomething(ActionEvent ae) 
    { 
     System.out.println("In do something: " + mainPane); 
     ObservableList<Node> children = mainPane.getChildren(); 
     System.out.println("Children are " + children); 
     children.add(pm); 

    } 
} 

使用這種FXML文件:

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="TestMain"> 
    <children> 
    <FlowPane fx:id="mainPane" prefHeight="400.0" prefWidth="600.0" > 
    <Button text="Click here to start" onAction="#doSomething"/> 
    </FlowPane> 
    </children> 
</AnchorPane> 

當我點擊按鈕我在主窗口 - 應加載自定義控件我得到一個java.lang.reflect.InvocationTargetException異常導致:java.lang.NullPointerException:子節點:子節點爲null:parent = FlowPane [id = mainPane]

我在這裏錯過了什麼?

第二個問題:您可能會注意到我隨意在主窗口中添加了一個按鈕,因此當它被點擊時,我可以加載我的BorderPane自定義控件類。理想情況下,我想直接在TestMain的start方法中執行此操作,但mainPane在start方法中爲null - 它何時變爲非null?

+0

如果調試代碼,mainPane是否在doSomething()中爲null? –

回答

4

你應該從來沒有使您的主要應用程序類控制器 - 它只是太混亂和充滿錯誤,如你遇到過。

發生什麼事情是,當你加載Main.fxml時,FXMLLoader將創建一個Application類的新實例。當你點擊主fxml UI中定義的按鈕時,doSomething方法將在新的TestMain對象上被調用,而不是在你的應用程序啓動時創建的原始TestMain對象。

解決方案是創建一個MainController.java,該MainController.java作爲Main.fxml GUI的控制器(類似於您已經完成的PetListGUIManager),並從您的主應用程序類中完全刪除任何@FXML相關表示法。

相關問題