如何让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
相关产品推荐
相关产品推荐

