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

JavaFX ListView控制器通信问题及MySQL数据存储、列表填充求解

问题解答

一、JavaFX列表不更新、对象覆盖问题修复

你现在的核心错误是在添加学生的副控制器中重新加载了Main.fxml,拿到的是全新的主控制器实例,不是当前正在运行的主窗口的控制器,所以修改不会反应到原有界面上,打印语句能执行是因为你确实调用了新实例的方法,只是这个实例没有对应展示的窗口。
修复步骤如下:

  1. 修改主控制器Events的窗口跳转方法,把当前主控制器实例传给副控制器
public void switchToStudentAdd(ActionEvent e) throws IOException {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("AddStud.fxml"));
    Parent root = (Parent) fxmlLoader.load();
    // 获取副控制器实例,传入当前主控制器
    AddStudEvents addController = fxmlLoader.getController();
    addController.setMainController(this);
    Stage stage = new Stage();
    stage.setScene(new Scene(root));  
    stage.show();
}
  1. 修改副控制器AddStudEvents,不要重复加载主界面
public class AddStudEvents{
    @FXML
    private TextField firstName;
    @FXML
    private TextField lastName;
    @FXML
    private Button addStudent;
    // 新增成员变量存储主控制器引用
    private Events mainController;
    // 新增set方法接收主控制器
    public void setMainController(Events mainController) {
        this.mainController = mainController;
    }

    public void addNameToList(ActionEvent e) throws IOException {
        String name = firstName.getText();
        String lastname = lastName.getText();
        Student student = new Student(name, lastname);
        // 直接用传入的主控制器调用方法
        mainController.addToNames(student);
        // 添加完成后关闭当前添加窗口
        ((Stage) addStudent.getScene().getWindow()).close();
    }
}
  1. 修正主控制器的addToNames方法,你当前固定添加了字符串xd,替换成学生的真实姓名
public void addToNames(Student student) {
    nameslist.getItems().add(student.getName() + " " + student.getSurname());
    // 同步存入你定义的学生数组
    for (int i = 0; i < Students.length; i++) {
        if (Students[i] == null) {
            Students[i] = student;
            break;
        }
    }
    System.out.println(student.getName() + " " + student.getSurname());
}

二、MySQL存储学生数据(含成绩数组)实现

1. 表结构调整

MySQL 5.7及以上版本原生支持JSON类型,你可以直接给student表新增JSON类型的字段存储成绩数组,在SQL Workbench中执行以下SQL即可:

-- 如果还没有建student表执行这个
CREATE TABLE ia.student (
    id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键唯一标识',
    name VARCHAR(50) NOT NULL COMMENT '姓名',
    surname VARCHAR(50) NOT NULL COMMENT '姓氏',
    scores JSON NULL COMMENT '学生成绩数组'
);
-- 如果已经建了表只需要加字段执行这个
ALTER TABLE ia.student ADD COLUMN scores JSON NULL COMMENT '学生成绩数组';

2. 改造数据库操作类

import com.alibaba.fastjson2.JSON; // 引入JSON转换工具,也可以用Jackson、Gson等
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DatabaseControl {
    static String url = "jdbc:mysql://localhost:3306/ia?useUnicode=true&characterEncoding=utf8";
    static String username = "root";
    static String password = "sifra123";

    // 插入单条学生数据的公共方法
    public static int insertStudent(Student student) throws SQLException, ClassNotFoundException {
        Class.forName("com.mysql.jdbc.Driver");
        // try-with-resources自动关闭连接,避免资源泄漏
        try(Connection connection = DriverManager.getConnection(url, username, password)) {
            String sql = "INSERT INTO ia.student (name, surname, scores) VALUES (?, ?, ?)";
            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setString(1, student.getName());
            ps.setString(2, student.getSurname());
            // 把成绩数组转成JSON字符串存入数据库
            ps.setString(3, JSON.toJSONString(student.getScores()));
            return ps.executeUpdate();
        }
    }

    // 查询所有学生数据的公共方法,用来填充ListView
    public static List<Student> queryAllStudents() throws SQLException, ClassNotFoundException {
        List<Student> studentList = new ArrayList<>();
        Class.forName("com.mysql.jdbc.Driver");
        try(Connection connection = DriverManager.getConnection(url, username, password)) {
            String sql = "SELECT name, surname, scores FROM ia.student";
            ResultSet rs = connection.createStatement().executeQuery(sql);
            while (rs.next()) {
                Student student = new Student(rs.getString("name"), rs.getString("surname"));
                // 把数据库存储的JSON字符串转回Java成绩数组
                List<Integer> scores = JSON.parseArray(rs.getString("scores"), Integer.class);
                student.setScores(scores); // 对应你Student类的setScores方法
                studentList.add(student);
            }
        }
        return studentList;
    }
}

3. 实现先存库再加载数据到列表的逻辑

修改副控制器的添加逻辑:

public void addNameToList(ActionEvent e) throws IOException, SQLException, ClassNotFoundException {
    String name = firstName.getText();
    String lastname = lastName.getText();
    Student student = new Student(name, lastname);
    // 先把学生数据存入数据库
    DatabaseControl.insertStudent(student);
    // 调用主控制器方法重新加载全量学生数据刷新列表
    mainController.refreshStudentList();
    ((Stage) addStudent.getScene().getWindow()).close();
}

在主控制器中新增刷新列表的方法,主界面初始化时也可以调用这个方法加载历史存储的学生数据:

public void refreshStudentList() throws SQLException, ClassNotFoundException {
    nameslist.getItems().clear();
    List<Student> allStudents = DatabaseControl.queryAllStudents();
    for (Student stu : allStudents) {
        nameslist.getItems().add(stu.getName() + " " + stu.getSurname());
    }
    // 同步更新本地的学生数组
    Students = allStudents.toArray(new Student[0]);
}

补充说明

JSON是一种轻量级的结构化数据格式,数组形式为[90,88,95],把成绩数组转成JSON字符串存储,既可以方便地和Java数组互转,也可以直接用MySQL自带的JSON函数对成绩做统计、查询操作,不需要单独拆分成绩表的情况下是存储数组属性的最优方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:36:07