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

如何让JavaFX的MainWindow.fxml显示列表中的历史条目?

JavaFX 历史分数列表展示问题

我正在为计算机科学学士学位的问卷制作第一个JavaFX窗口,目前能正确显示用户名和分数,但希望在程序运行期间展示列表中的其他历史条目。我尝试通过以下代码实现:

返回主窗口的Controller类代码

public void clickMainMenuBtn(ActionEvent actionEvent) throws IOException
{
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/MainWindow.fxml"));
    Parent mainSceneRoot = loader.load();
    MainController mainController = loader.getController();
    UserScore userScore = new UserScore(SecondController.getUserNameInput(), ScoreCalculated);

    mainController.initialize(userScore);
    Stage currentStage = (Stage) Score.getScene().getWindow();
    currentStage.setScene(new Scene(mainSceneRoot));
}

主窗口Controller的initialize方法

public void initialize(UserScore userScore)
{
    userNameLabel.setText(userScore.getUserName());
    scoreLabel.setText(String.valueOf(userScore.getScore()));

    NameAndScoreList.add(userScore);

    displayNameAndScoreList();
}

displayNameAndScoreList方法

public void displayNameAndScoreList()
{
    StringBuilder NameAndScoreListText = new StringBuilder("Tidligere Score:\n");

    for(UserScore userScore : NameAndScoreList)
    {
        NameAndScoreListText.append(userScore.getUserName()).append(": ").append(userScore.getScore()).append("\n");
    }
    System.out.println(NameAndScoreListText.toString());
    EarlierScores.setText(NameAndScoreListText.toString());
}

问题分析与修复方案

1. 核心问题:历史记录丢失

每次返回主窗口时,你通过FXMLLoader重新加载MainWindow.fxml,会创建全新的MainController实例。如果NameAndScoreList是该类的普通成员变量,每次都会被重新初始化,导致之前的历史记录全部丢失。

2. 缺失代码与规范问题

  • NameAndScoreList定义缺失:需要将其定义为静态成员变量或全局共享数据源,保证程序运行期间唯一。
  • 不符合JavaFX Controller初始化规范:标准的initialize方法应该是无参的,自定义带参initialize会导致JavaFX无法自动调用,且逻辑耦合。
  • 重复创建Scene:每次返回都新建Scene会浪费资源,应该复用已有实例或直接更新数据。

修改后的代码示例

MainController 修正版
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import java.util.ArrayList;
import java.util.List;

public class MainController {
    // 静态集合保存历史分数,全局唯一
    private static List<UserScore> NameAndScoreList = new ArrayList<>();

    @FXML
    private Label userNameLabel;
    @FXML
    private Label scoreLabel;
    @FXML
    private TextArea EarlierScores;

    // JavaFX标准无参初始化方法,启动时加载已有历史
    @FXML
    public void initialize() {
        displayNameAndScoreList();
    }

    // 单独方法用于更新用户分数并添加到历史
    public void updateUserScore(UserScore userScore) {
        userNameLabel.setText(userScore.getUserName());
        scoreLabel.setText(String.valueOf(userScore.getScore()));

        NameAndScoreList.add(userScore);
        displayNameAndScoreList();
    }

    public void displayNameAndScoreList() {
        StringBuilder NameAndScoreListText = new StringBuilder("Tidligere Score:\n");

        for(UserScore userScore : NameAndScoreList) {
            NameAndScoreListText.append(userScore.getUserName()).append(": ").append(userScore.getScore()).append("\n");
        }
        System.out.println(NameAndScoreListText.toString());
        EarlierScores.setText(NameAndScoreListText.toString());
    }
}
返回主窗口的Controller修正版
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;

public class SecondController {
    // 假设Score是当前窗口的某个控件,SecondController.getUserNameInput()已实现
    public void clickMainMenuBtn(ActionEvent actionEvent) throws IOException {
        Stage currentStage = (Stage) Score.getScene().getWindow();
        Scene mainScene = currentStage.getScene();
        MainController mainController;

        // 判断是否已加载过主窗口Scene,避免重复加载
        if (mainScene == null || !(mainScene.getRoot().getUserData() instanceof MainController)) {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/MainWindow.fxml"));
            Parent mainSceneRoot = loader.load();
            mainController = loader.getController();
            mainScene = new Scene(mainSceneRoot);
            // 将Controller绑定到Scene的userData,方便后续获取
            mainSceneRoot.setUserData(mainController);
            currentStage.setScene(mainScene);
        } else {
            // 直接复用已有的Controller
            mainController = (MainController) mainScene.getRoot().getUserData();
        }

        UserScore userScore = new UserScore(SecondController.getUserNameInput(), ScoreCalculated);
        mainController.updateUserScore(userScore);
    }
}
补充UserScore类定义(若缺失)
public class UserScore {
    private String userName;
    private int score; // 可根据需求改为double类型

    public UserScore(String userName, int score) {
        this.userName = userName;
        this.score = score;
    }

    public String getUserName() {
        return userName;
    }

    public int getScore() {
        return score;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:45:54