修改通过 FXML 文件加载的 JavaFX 场景?

问题描述 投票:0回答:1

我正在尝试修改我正在运行的应用程序的 Java 代码中通过 FXML 文件加载的 JavaFX 场景。

我有以下使用 SceneBuilder 创建的测试 FXML 文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.shape.Line?>


<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" xmlns="" xmlns:fx="">
   <top>
      <TabPane prefHeight="100.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
        <tabs>
          <Tab text="Untitled Tab 1">
            <content>
              <AnchorPane prefHeight="100.0" prefWidth="200.0" />
            </content>
          </Tab>
          <Tab text="Untitled Tab 2">
            <content>
              <AnchorPane prefHeight="100.0" prefWidth="200.0" />
            </content>
          </Tab>
        </tabs>
      </TabPane>
   </top>
   <center>
   </center>
</BorderPane>

这只是一个

BorderPane
,其中
Top
部分有两个空选项卡,还有一个空的
Center
部分。我希望能够在
Center
部分绘制一些形状。我使用 以下示例代码
Canvas
窗口中绘制一些随机形状,并确保示例代码本身可以工作:

然后,我想将完全相同的绘制的

Canvas
(具有完全相同的形状)插入到上面显示的 FXML 文件中声明的
Center
BorderPane
部分中。

但是,我对如何正确引用 FXML 加载器加载的场景的各个子项有点困惑。如果我在我的

start
函数中尝试以下代码:

public void start(Stage stage) throws IOException 
{
    stage.setTitle("Drawing Operations Test");
    Scene scene = new Scene(loadFXML("primary"), 1280, 720);
        
    Canvas canvas = new Canvas(300, 250);
    GraphicsContext gc = canvas.getGraphicsContext2D();
    drawShapes(gc);
    scene.getRoot().getChildrenUnmodifiable().get(0).getChildren().add(canvas);
        
    stage.setScene(scene);
    stage.show();
}

其中

drawShapes
是在
Canvas
上绘制形状的函数,线:

scene.getRoot().getChildrenUnmodifiable().get(0).getChildren().add(canvas);

被列为错误,因为在

getChildren
类中找不到类函数
Node

现在,我对该错误原因的最初假设是因为我应该将

Node
对象类型转换到我想要添加
canvas
的相应类中,在我的例子中是
BorderPane
类。然而,我想澄清
getChildren
类函数将在这里返回给我什么。

getChildren
是否返回
BorderPane
对象,因为它是 FXML 文件中声明的第一个对象?或者该元素是否是其他元素的父元素?将我的
Canvas
添加到我的
Center
BorderPane
部分的正确方法是什么?

感谢您阅读我的帖子,感谢任何指导。

java javafx fxml
1个回答
0
投票
scene.getRoot()

将返回场景的根,您可以通过调用

Scene
构造函数来设置该根:

Scene scene = new Scene(loadFXML("primary"), 1280, 720);

换句话说,

scene.getRoot()
是从
load.FXML(...)
返回的对象。您没有向我们展示该方法定义,因此我们无法确定,但可以合理地假设它返回调用
FXMLLoader.load(...)
的结果,这将是
BorderPane
(根元素,在 XML 意义上, FXML 文件的一部分)。

因此,您可以将

scene.getRoot()
的结果转换为
BorderPane
,然后调用
setCenter(...)
(或者,显然更好,首先保留对
loadFXML(...)
结果的引用)。

代码

scene.getRoot().getChildrenUnmodifiable()

将返回

BorderPane
的子节点列表,即仅包含
TabPane
的列表,所以

scene.getRoot().getChildrenUnmodifiable().get(0)

是对

TabPane
的引用,并且

scene.getRoot().getChildrenUnmodifiable().get(0).getChildren()

(添加了适当的转换)是

TabPane
的子节点列表。该列表的内容基本上是
TabPane
及其皮肤的实现细节。


但这都不是 API 设计者想要使用的方式。相反,为 FXML 定义一个控制器类,并将

BorderPane
注入其中:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.shape.Line?>


<BorderPane 
    maxHeight="-Infinity" maxWidth="-Infinity" 
    minHeight="-Infinity" minWidth="-Infinity" 
    prefHeight="720.0" prefWidth="1280.0" 
    xmlns="" xmlns:fx=""
    fx:controller="my.package.MyController"
    fx:id="borderPane" 
>

    <!-- ... -->

</BorderPane>

然后定义控制器,并在

initialize()
方法中修改边框窗格(如果您想立即添加画布),或在事件处理程序中(如果您想修改场景图以响应用户操作):

package my.package;

// imports ...

public class MyController {

    @FXML
    private BorderPane borderPane;

    @FXML
    private void initialize() {
        
        Canvas canvas = new Canvas(300, 250);
        GraphicsContext gc = canvas.getGraphicsContext2D();
        drawShapes(gc);
        borderPane.setCenter(canvas);

    }

    private void drawShapes(GraphicsContext gc) {
        // ...
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.