【问题标题】:JavaFX unable to find node declared in FXML at runtime using IDJavaFX 无法在运行时使用 ID 找到在 FXML 中声明的节点
【发布时间】:2015-01-27 02:37:24
【问题描述】:

我无法找到在 FXML 中声明的 ID 为“#mainScrollPaneVbox”的节点“VBox”。

这是我的 FXML:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.conuretech.video_assembler.FXMLController">
   <top>
      <MenuBar prefHeight="16.0" prefWidth="600.0" BorderPane.alignment="CENTER">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" onAction="#handleNewAction" text="New" />
              <MenuItem mnemonicParsing="false" onAction="#handleOpenProjectAction" text="Open Project" />
              <MenuItem mnemonicParsing="false" onAction="#handleSaveAsAction" text="Save As..." />
              <MenuItem mnemonicParsing="false" onAction="#handleSaveAction" text="Save..." />
              <MenuItem mnemonicParsing="false" onAction="#handleCovertImagesToVideoAction" text="Convert Project To video" />
              <MenuItem mnemonicParsing="false" onAction="#handleImportLocalAction" text="Import Local Images" />
              <MenuItem mnemonicParsing="false" onAction="#handleImportRemoteAction" text="Import Remote Images" />
              <MenuItem mnemonicParsing="false" onAction="#handleExitAction" text="Exit" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Add New Frame From" />
               <MenuItem mnemonicParsing="false" text="Delete Current Frame" />
               <MenuItem mnemonicParsing="false" text="Edit Frame Properties" />
               <MenuItem mnemonicParsing="false" text="Video Properties" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </top>
   <left>
      <ScrollPane id="#mainScrollPane" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <content>
            <VBox id="#mainScrollPaneVbox" prefHeight="200.0" prefWidth="200.0" />
         </content></ScrollPane>
   </left>
   <center>
      <GridPane BorderPane.alignment="CENTER">
        <columnConstraints>
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
      </GridPane>
   </center>
</BorderPane>

这是 Java 代码,它试图在运行时找到“Vbox”:

VBox vbox = (VBox) MainApp.scene.lookup("#mainScrollPaneVbox");

我也试过了:

VBox vbox = (VBox) MainApp.scene.lookup("mainScrollPaneVbox");

但这仍然返回 null。

有什么想法吗?

谢谢

【问题讨论】:

  • 什么时候执行查找?仅在应用 CSS 后查找才起作用(并且通常不是很健壮)。推荐的方法是使用控制器类和fx:id 属性将控件注入到该类中。
  • @James_D,我在场景已经渲染后尝试查找。我想动态地将 ImageViews 添加到 VBox,因此我试图先找到 VBox。
  • @Aryan 为什么不给 VBox 一个 fx:id 并用它来添加 ImageViews?

标签: javafx fxml


【解决方案1】:

为什么您的代码不起作用

FXML 中的id 属性应该只包含节点的id,而不是id 的CSS 查找。换句话说,你有

<VBox id="#mainScrollPaneVbox" ... >

当你需要时

<VBox id="mainScrollPaneVbox" ... >

查找应该有 CSS 查找:

VBox vbox = (VBox) MainApp.scene.lookup("#mainScrollPaneVbox");

但无论如何我都不建议这样做,特别是因为您已经有一个控制器类。

推荐方法

CSS 查找不是很健壮。它们依赖于字符串绑定,并且不是类型安全的。此外,在实际执行查找之前不会捕获任何错误,这可能在应用程序启动之后(例如,当用户执行某些操作时)。

更好的方法是使用@FXML 注入。虽然这些仍然依赖于字符串绑定并且没有编译时类型检查,但在加载 FXML 文件时会捕获错误,因此任何失败都会更早发生。这使得检测和修复错误变得更加容易。

要使用@FXML 注入,您会这样做

<VBox fx:id="mainScrollPaneVbox"

然后在你的控制器类中:

public class FXMLController {

    @FXML
    private VBox mainScrollPaneVbox ; // same field name as the fx:id

    // ...

    public void initialize() {
        // popuplate mainScrollPaneVbox ...
        // can similarly be accessed in event handlers

        // ...
    }

    // ...
}

【讨论】:

    猜你喜欢
    • 2023-01-24
    • 2016-02-29
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 2017-05-27
    • 2014-02-03
    相关资源
    最近更新 更多