gpt4 book ai didi

JavaFX - 将 FXML 包装到 Java 类 Controller

转载 作者:搜寻专家 更新时间:2023-10-31 19:29:00 25 4
gpt4 key购买 nike

我有一个包含 TreeView 控件的 FXML 文件:

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="500.0" xmlns:fx="http://javafx.com/fxml" fx:controller="test.MyControllerClass">

<TreeView fx:id="locationTreeView" layoutX="12.0" layoutY="158.0" prefHeight="193.0" prefWidth="471.0" />

然后我的 Java 类 Controller 需要用这个 TreeView 包装并动态添加 TreeItem。这就是问题所在,它没有加载那些 TreeItem。这是下面的测试代码,来 self 的 Controller :

public class MyControllerClass extends Application {

@FXML
private TreeView<String> locationTreeView;

@Override
public void start(Stage stage) throws Exception {

stage.initStyle(StageStyle.TRANSPARENT);
stage.getIcons().add(new Image(getClass().getResourceAsStream("myIcon.png")));

Parent root = FXMLLoader.load(getClass().getResource("myInterface.fxml"));

Scene scene = new Scene(root);
stage.setScene(scene);

loadTreeItems();

stage.show();
}

// Just a simple example that still doesn't works
private void loadTreeItems() {

try {
TreeItem<String> root = new TreeItem<String>("Root Node");
root.setExpanded(true);
root.getChildren().addAll(
new TreeItem<String>("Item 1"),
new TreeItem<String>("Item 2"),
new TreeItem<String>("Item 3")
);

locationTreeView = new TreeView<String>(root);

} catch (Exception exc) {
System.out.println("Error: " + exc.getMessage());
}
}

public static void main(String[] args) {
launch(args);
}
}

知道为什么它不起作用吗?

最佳答案

您的应用程序无法运行的原因有几个:

  1. 您需要将 Controller 和应用程序分开。
  2. 您应该允许 FXML 系统注入(inject) TreeView 实例而不是创建一个新实例(正如 Aaron 在他的回答中指出的那样)。

您当前构建应用程序的方式将会发生什么:

  1. Java 系统将在启动时创建一个 MyControllerClass 实例(并调用它的 start 方法)。
  2. FXMLLoader 将创建 MyControllerClass另一个实例 每次 myInterface.fxml 文件已加载。
  3. FXMLLoader 将创建一个新的 TreeView 实例,并在 newlocationTreeView 成员上执行 FXML 注入(inject)> MyControllerClass 它创建的实例。
  4. FXMLLoader 将尝试在新的 MyControllerClass(您没有)上调用 initialize 方法。
  5. FXMLLoader不会调用 MyControllerClass 上的start 方法.
  6. 您对原始 MyControllerClass 的原始 start 方法调用将继续处理并创建另一个 TreeView 实例,该实例它将 old MyControllerClass 实例的 locationTreeView 成员设置为。

我更新了您的代码以进行我上面建议的修改,并且代码现在可以工作了。更新的code is available .

运行代码的示例屏幕截图是: dynamictreeview

MyApplicationClass.java

import javafx.animation.*;
import javafx.application.Application;
import javafx.event.*;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.stage.*;
import javafx.util.Duration;

/** Sample application to demonstrate programming an FXML interface. */
public class MyApplicationClass extends Application {
@Override public void start(final Stage stage) throws Exception {
// load the scene fxml UI.
// grabs the UI scenegraph view from the loader.
// grabs the UI controller for the view from the loader.
final FXMLLoader loader = new FXMLLoader(getClass().getResource("myInterface.fxml"));
final Parent root = (Parent) loader.load();
final MyControllerClass controller = loader.<MyControllerClass>getController();

// continuously refresh the TreeItems.
// demonstrates using controller methods to manipulate the controlled UI.
final Timeline timeline = new Timeline(
new KeyFrame(
Duration.seconds(3),
new TreeLoadingEventHandler(controller)
)
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();

// close the app if the user clicks on anywhere on the window.
// just provides a simple way to kill the demo app.
root.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent t) {
stage.hide();
}
});

// initialize the stage.
stage.setScene(new Scene(root));
stage.initStyle(StageStyle.TRANSPARENT);
stage.getIcons().add(new Image(getClass().getResourceAsStream("myIcon.png")));
stage.show();
}

/** small helper class for handling tree loading events. */
private class TreeLoadingEventHandler implements EventHandler<ActionEvent> {
private MyControllerClass controller;
private int idx = 0;

TreeLoadingEventHandler(MyControllerClass controller) {
this.controller = controller;
}

@Override public void handle(ActionEvent t) {
controller.loadTreeItems("Loaded " + idx, "Loaded " + (idx + 1), "Loaded " + (idx + 2));
idx += 3;
}
}

// main method is only for legacy support - java 8 won't call it for a javafx application.
public static void main(String[] args) { launch(args); }
}

MyControllerClass.java

import javafx.fxml.FXML;
import javafx.scene.control.*;

/** Sample controller class. */
public class MyControllerClass {
// the FXML annotation tells the loader to inject this variable before invoking initialize.
@FXML private TreeView<String> locationTreeView;

// the initialize method is automatically invoked by the FXMLLoader - it's magic
public void initialize() {
loadTreeItems("initial 1", "initial 2", "initial 3");
}

// loads some strings into the tree in the application UI.
public void loadTreeItems(String... rootItems) {
TreeItem<String> root = new TreeItem<String>("Root Node");
root.setExpanded(true);
for (String itemString: rootItems) {
root.getChildren().add(new TreeItem<String>(itemString));
}

locationTreeView.setRoot(root);
}
}

myInterface.fxml

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns:fx="http://javafx.com/fxml" fx:controller="test.MyControllerClass">
<TreeView fx:id="locationTreeView" layoutX="0" layoutY="0" prefHeight="193.0" prefWidth="471.0" />
</AnchorPane>

关于JavaFX - 将 FXML 包装到 Java 类 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15439894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com