2012-09-07 10 views
5

vorrei trovare un nodo VBox in una scena carica di FXMLoader grazie a Node#lookup() ma ottengo la seguente eccezione:JavaFX 2.0 + FXML - strano comportamento di ricerca

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

Il codice:

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 !!!")); 
    } 
} 

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

Vorrei sapere:
1. Perché metodo di ricerca restituiscono un SplitPaneSkin$Content e non un VBox?
2. Come posso ottenere il VBox in un altro modo?

Grazie in anticipo

risposta

7
  1. SplitPane mette tutti gli elementi in riquadri separati dello stack (recarci come SplitPaneSkin$Content). Per ragioni sconosciute FXMLLoader assegna loro lo stesso id di root child. È possibile ottenere VBox è necessario entro il prossimo metodo di utilità:

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

    e usarlo modo seguente:

    VBox myvbox = lookup(page, "#myvbox", VBox.class); 
    myvbox.getChildren().add(new Button("Hello world !!!")); 
    
  2. è possibile utilizzare Controller e aggiungere il campo autopopulated:

    @FXML 
    VBox myvbox; 
    
+0

Ho aggiornato il mio pubblicare con un semplice esempio. Conosco l'annotazione '@ FXML', ma non posso usarla perché gli ID sono generati automaticamente. –

+0

aggiornato con una soluzione alternativa –

+0

Ottimo, funziona correttamente. Non pensavo che FXMLoader assegnasse loro lo stesso id di root child. Sono contento di vedere il responsabile della tecnologia QA nel team di interfaccia utente JavaFX di Oracle per rispondere alle domande StackOverflow. ** Molte grazie ** –

9

Il modo più semplice per ottenere un riferimento al VBox è chiamando FXMLLoader # getNamespace(). Per esempio:

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

Si noti che è necessario creare un'istanza di FXMLLoader e chiamare la versione non-statico del carico() in modo che questo funzioni:

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