我最近遇到了问题,我需要从我的窗口中使用的节点获取特定节点(最好是通过 id)。我正在使用 FXMLLoader,所以第一个想法是搜索 FXMLLoader 返回的树结构。
root|
|
|--some_container |- child1
| |- child2
|
|--other_container |-child3
...
进一步的研究使我在 Scene 类中找到了方法 lookup ,但官方文档 ( https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html#lookup-java.lang.String- ) 缺乏对这种方法工作原理的描述,在我看来是不准确的(我费了很大力气才让事情顺利进行)。
如此处所述 ( How to find an element with an ID in JavaFX? ) 方法 lookup 的调用必须在 方法 show 之后,为什么?
第二个问题是为什么节点 id 必须以“#”(井号)开头?而官方文件说明它应该是“...CSS选择器...”? (我在这里有点困惑,因为 Node 类只包含一个类似 id 的属性)
Edi1 - @kleopatra 的简单示例 尽管严格来说问题不在于代码,而在于理解。
具有场景内容的示例 fxml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="display.windows.ConsoleForBoard">
<children>
<SplitPane fx:id="mainSplitPane" dividerPositions="0.7" layoutX="277.0" layoutY="100.0" prefHeight="160.0" prefWidth="200.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="398.0" prefWidth="404.0">
<children>
<SplitPane dividerPositions="0.8" layoutX="150.0" layoutY="53.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.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="100.0" prefWidth="160.0">
<children>
<Canvas fx:id="drawBoard" height="313.0" layoutX="125.0" layoutY="43.0" width="413.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextArea layoutX="107.0" layoutY="-86.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ToggleButton layoutX="35.0" layoutY="62.0" mnemonicParsing="false" text="ToggleButton" />
<TextField alignment="CENTER" layoutX="2.0" layoutY="14.0" promptText="Main Menu" text="Main Menu" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
注意: Canvas 有 fx:id="drawBoard"
创建此场景的示例类:
public class BoardWithMenu extends Application {
Scene mainScene;
AnchorPane root;
FXMLLoader loader;
public static void start() {launch("start");}
@Override
public void start(Stage stage) throws Exception {
loader = new FXMLLoader(this.getClass().getResource("scene_definition.fxml"));
root = loader.load();
mainScene = new Scene(root, 500, 500);
stage.setScene(mainScene);
stage.setTitle("Space map");
stage.show();
Canvas board = (Canvas) mainScene.lookup("drawBoard");
System.out.println(board.getId());
}
}
问题:
线
Canvas 板 = (Canvas) mainScene.lookup("#drawBoard");
之前不能调用
stage.show();
它会产生空指针错误。为什么?
最佳答案
您引用的评论:
As mentioned here (How to find an element with an ID in JavaFX?) invocation of method lookup must be after method show?
作为一般性陈述是错误的。加载后是否可以立即查找节点取决于它是如何添加的:
- 作为子节点注入(inject)的所有节点在加载器之后直接可用(例如“#mainSplitPane”作为根节点的子节点)
- 所有由皮肤插入的节点仅在附加皮肤后可用,即在显示后(例如注入(inject)到 splitPane 的项目的“#drawBoard”)
关于JavaFX,通过 Id 查找节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68475291/