You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免重新加载.fxml时清空JavaFX的taskListView数据?

解决JavaFX场景切换时ListView数据丢失问题

问题根源

你的代码存在两个核心问题导致数据丢失:

  1. UI实例不统一:启动时HelloApplication加载了scene2.fxml并创建了一个UI实例,但HelloController里的scene2Root是在第一次调用switchToScene2时重新加载的,这是两个完全独立的scene2实例,你添加的任务只存在于启动时的那个实例中,切换回去时用的是新实例,自然看不到数据。
  2. 场景切换方式错误:切换时直接替换整个Scene,不仅丢失了原来的UI状态,还把启动时添加的鼠标跟随Circle也替换掉了。

修复方案

我们通过统一缓存所有场景根节点,并替换容器内的子节点而非整个Scene来解决问题,同时保证UI状态和数据的一致性。

步骤1:修改HelloApplication.java

将场景根节点的缓存和管理移到Application类中,保留外层Pane结构,切换时仅替换Pane内的内容:

package com.example.newapp;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.Objects;

public class HelloApplication extends Application {
    private static HelloApplication instance;
    private Pane mainPane;
    private Parent scene1Root;
    private Parent scene2Root;

    @Override
    public void start(Stage primaryStage) throws Exception {
        instance = this;
        // 初始化所有场景根节点并缓存
        scene1Root = loadFXML("scene1.fxml");
        scene2Root = loadFXML("scene2.fxml");

        mainPane = new Pane(scene2Root); // 默认显示scene2

        // 添加鼠标跟随Circle
        Circle circle = new Circle(8, Color.BLACK);
        circle.setMouseTransparent(true);
        mainPane.getChildren().add(circle);

        mainPane.setOnMouseMoved(event -> {
            circle.setCenterX(event.getX());
            circle.setCenterY(event.getY());
        });

        // 加载样式
        String cssFile = Objects.requireNonNull(getClass().getResource("style.css")).toExternalForm();
        scene1Root.getStylesheets().add(cssFile);
        scene2Root.getStylesheets().add(cssFile);

        primaryStage.setTitle("To-Do List");
        primaryStage.setScene(new javafx.scene.Scene(mainPane));
        primaryStage.setResizable(false);
        primaryStage.show();
    }

    private Parent loadFXML(String fxmlPath) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlPath));
        return loader.load();
    }

    // 提供切换场景的方法
    public void switchScene(Parent targetRoot) {
        mainPane.getChildren().set(0, targetRoot); // 替换第一个子节点(原场景根)
    }

    // 获取缓存的场景根节点
    public Parent getScene1Root() {
        return scene1Root;
    }

    public Parent getScene2Root() {
        return scene2Root;
    }

    // 提供获取Application实例的方法
    public static HelloApplication getInstance() {
        return instance;
    }

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

步骤2:修改HelloController.java

移除Controller内的根节点缓存,改为调用Application的方法切换场景:

package com.example.newapp;

import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;

public class HelloController {

    @FXML
    private ListView<String> taskListView;

    @FXML
    private TextField taskTextField;

    @FXML
    private void addTask() {
        String task = taskTextField.getText();
        if (!task.isEmpty()) {
            taskListView.getItems().add(task);
            taskTextField.clear();
        }
    }

    @FXML
    private void removeTask() {
        ObservableList<String> selectedTasks = taskListView.getSelectionModel().getSelectedItems();
        taskListView.getItems().removeAll(selectedTasks);
    }

    public void switchToScene1(ActionEvent event) {
        HelloApplication.getInstance().switchScene(HelloApplication.getInstance().getScene1Root());
    }

    public void switchToScene2(ActionEvent event) {
        HelloApplication.getInstance().switchScene(HelloApplication.getInstance().getScene2Root());
    }
}

额外优化建议

如果后续需要多个Controller共享数据,可以将ObservableList<String> taskList提取为全局单例,比如放在HelloApplication中,然后在Controller的initialize方法中将taskListView.setItems(taskList),这样即使不小心重新加载FXML,也能绑定到同一个数据源,数据不会丢失。

内容的提问来源于stack exchange,提问作者Raghav Pottabathini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:12:01