JavaFX 2.0 + FXML - strange lookup behaviour

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

I want to find a VBox node in a scene loaded with FXMLoader thanks to Node#lookup() but I get the following exception :

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

The code :

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

The fxml file:

I would like to know :
1. Why lookup method return a SplitPaneSkin$Content and not a VBox ?
2. How I can get the VBox in another manner ?

Thanks in advance

回答1:

  1. SplitPane puts all items in separate stack panes (fancied as SplitPaneSkin$Content). For unknown reason FXMLLoader assign them the same id as root child. You can get VBox you need by next utility method:

    public  T lookup(Node parent, String id, Class 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); } 

    and use it next way:

    VBox myvbox = lookup(page, "#myvbox", VBox.class); myvbox.getChildren().add(new Button("Hello world !!!")); 
  2. you can use Controller and add autopopulated field:

    @FXML VBox myvbox; 


回答2:

The easiest way to get a reference to the VBox is by calling FXMLLoader#getNamespace(). For example:

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

Note that you'll need to create an instance of FXMLLoader and call the non-static version of load() in order for this to work:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!