JavaFx: parent.lookup returns null

2020-04-11 18:38发布

I use osgi+cdi and I have the following code:

Parent parent=null;
FXMLLoader fxmlLoader=getFxmlLoader();
try {
    parent = (Parent)fxmlLoader.load(getFxmlStream("tasklist.fxml"));
} catch (IOException ex) {
    Logger.getLogger(TestGoView.class.getName()).log(Level.SEVERE, null, ex);
}
ComboBox comboBox=(ComboBox) parent.lookup("#testComboBox");
if (comboBox==null){
    System.out.println("COMBOBOX NULL");
}else{
    System.out.println("COMBOBOX NOT NULL");
}

And I have the following tasklist.fxml

<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="440.0" prefWidth="757.0" xmlns="http://javafx.com/javafx/8.0.60-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.techsenger.testgo.core.adm.task.list.TaskDirListController">
   <children>
      <HBox>
         <children>
            <ToolBar maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" nodeOrientation="RIGHT_TO_LEFT" HBox.hgrow="SOMETIMES">
               <items>
                  <ComboBox fx:id="testComboBox" maxWidth="1.7976931348623157E308" nodeOrientation="LEFT_TO_RIGHT" />
               </items>
            </ToolBar>
         </children>
      </HBox>
   </children>
</VBox>

However parent.lookup("#testComboBox") returns null. How to explain it? I've checked the name of ID several times.

标签: java javafx
2条回答
男人必须洒脱
2楼-- · 2020-04-11 19:20

It is because you are trying to use lookup before showing the parent on the screen.

Pane root = FXMLLoader.load(getClass().getResource("tasklist.fxml"));

System.out.println(root.lookup("#testComboBox")); //returns  null
primaryStage.setScene(new Scene(root));
primaryStage.show();
System.out.println(root.lookup("#testComboBox")); //returns 
// ComboBox[id=testComboBox, styleClass=combo-box-base combo-box]
查看更多
相关推荐>>
3楼-- · 2020-04-11 19:26

Instead of using a lookup, which will only work after the scene has been rendered, you can put the logic you need in your controller class. You can inject elements from the FXML file into the controller class by annotating them @FXML.

public class TaskDirListController {

    @FXML
    private ComboBox<...> testComboBox ;

    public void initialize() {
        System.out.println(testComboBox);
    }

    // ...
}

Lookups are generally not robust, and I would recommend avoiding using them. If you really need to access something defined in the FXML file from a class other than the controller, the first thing to do is to consider reorganizing things so that you don't need to do this: it really indicates that your overall design is wrong.

If you really need this for some reason, it's better to use the FXMLLoader's namespace than a lookup:

Parent parent=null;
FXMLLoader fxmlLoader=getFxmlLoader();
try {
    parent = (Parent)fxmlLoader.load(getFxmlStream("tasklist.fxml"));
    ComboBox<?> comboBox = (ComboBox<?>) fxmlLoader.getNamespace().get("testComboBox");
    System.out.println(comboBox);
} catch (IOException ex) {
    Logger.getLogger(TestGoView.class.getName()).log(Level.SEVERE, null, ex);
}
查看更多
登录 后发表回答