2012-09-07 26 views
5

Tôi muốn tìm một nút VBox trong một cảnh nạp với FXMLoader nhờ Node#lookup() nhưng tôi nhận được ngoại lệ sau đây:JavaFX 2.0 + FXML - lạ tra cứu hành vi

java.lang.ClassCastException: com.sun.javafx.scene.control.skin.SplitPaneSkin$Content cannot be cast to javafx.scene.layout.VBox

Mã:

public class Main extends Application { 
    public static void main(String[] args) { 
     Application.launch(Main.class, (java.lang.String[]) null); 
    } 
    @Override 
    public void start(Stage stage) throws Exception { 
     AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("test.fxml")); 
     Scene scene = new Scene(page); 
     stage.setScene(scene); 
     stage.show(); 

     VBox myvbox = (VBox) page.lookup("#myvbox"); 
     myvbox.getChildren().add(new Button("Hello world !!!")); 
    } 
} 

File fxml:

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" > 
    <children> 
    <SplitPane dividerPositions="0.5" focusTraversable="true" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> 
     <items> 
     <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" /> 
     <VBox fx:id="myvbox" prefHeight="398.0" prefWidth="421.0" /> 
     </items> 
    </SplitPane> 
    </children> 
</AnchorPane> 

Tôi muốn biết:
1. Tại sao phương pháp tra cứu trả lại SplitPaneSkin$Content và không phải là VBox?
2. Cách tôi có thể nhận được VBox theo cách khác?

Cảm ơn trước

Trả lời

7
  1. SplitPane đặt tất cả các mục trong khung ngăn xếp riêng biệt (tưởng tượng như SplitPaneSkin$Content). Vì lý do không xác định, FXMLLoader gán cho họ cùng một id là con gốc. Bạn có thể nhận VBox bạn cần bằng phương pháp hữu ích tiếp theo:

    public <T> T lookup(Node parent, String id, Class<T> clazz) { 
        for (Node node : parent.lookupAll(id)) { 
         if (node.getClass().isAssignableFrom(clazz)) { 
          return (T)node; 
         } 
        } 
        throw new IllegalArgumentException("Parent " + parent + " doesn't contain node with id " + id); 
    } 
    

    và sử dụng nó theo cách sau:

    VBox myvbox = lookup(page, "#myvbox", VBox.class); 
    myvbox.getChildren().add(new Button("Hello world !!!")); 
    
  2. bạn có thể sử dụng Controller và thêm lĩnh vực autopopulated:

    @FXML 
    VBox myvbox; 
    
+0

Tôi đã cập nhật của tôi đăng với một ví dụ đơn giản. Tôi biết chú thích '@ FXML' nhưng tôi không thể sử dụng nó vì các id được tạo tự động. –

+0

được cập nhật với một giải pháp khác –

+0

Tuyệt vời, nó hoạt động tốt. Tôi đã không cho rằng FXMLoader đã gán cho họ cùng một id là con gốc. Tôi rất vui khi thấy khách hàng tiềm năng của công nghệ QA trong nhóm giao diện người dùng JavaFX tại Oracle trả lời các câu hỏi về stackoverflow. ** Rất cám ơn ** –

9

Cách dễ nhất để có được một tham chiếu đến VBox là bằng cách gọi FXMLLoader # getNamespace(). Ví dụ:

VBox myvbox = (VBox)fxmlLoader.getNamespace().get("myvbox"); 

Lưu ý rằng bạn sẽ cần phải tạo một thể hiện của FXMLLoader và gọi phiên bản không tĩnh tải() để cho tiện làm việc:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("test.fxml")); 
AnchorPane page = (AnchorPane) fxmlLoader.load();