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

如何在Java Swing中实现JTable数据刷新功能?

解决Java Swing JTable添加数据后不刷新的问题

问题背景

使用Java Swing开发GUI,以文本文件作为用户信息存储介质。JTable初始化时会加载文件中的现有数据,但添加新用户并更新文本文件后,JTable无法同步显示新数据。当前代码仅初始化一次JTable,需要在updateList函数或点击viewButton时触发JTable刷新,实现新旧数据同时展示。

核心原因

你直接使用静态字符串数组初始化JTable,没有绑定支持动态更新的TableModel。Swing组件的JTable依赖TableModel管理数据,直接修改底层数据不会自动触发界面刷新,必须通过TableModel的API更新数据才能同步到界面。

解决方案及代码修改

1. 调整类成员变量

添加JTable和DefaultTableModel作为类成员,方便后续在方法中调用:

private JTextField firstNameField, lastNameField, salaryField;
private JButton addButton, removeButton, viewButton, sortButton, getButton;
private JList<Employee> userList;
private ArrayList<Employee> users;
// 新增以下两个成员变量
private JTable userTable;
private DefaultTableModel tableModel;

2. 修改构造方法中的JTable初始化逻辑

用DefaultTableModel替代静态数组初始化JTable:

// 初始化表格Model和JTable
String[] columnNames = { "FName", "LName", "Salary" };
tableModel = new DefaultTableModel(columnNames, 0);
// 填充初始数据
for (ArrayList<String> row : databaseData) {
    tableModel.addRow(row.toArray());
}
userTable = new JTable(tableModel);
userTable.setPreferredScrollableViewportSize(new Dimension(700, 300)); // 设置表格首选大小

JScrollPane tableScrollPane = new JScrollPane(userTable);

3. 编写JTable刷新方法

创建通用的刷新方法,将users集合中的数据同步到TableModel:

private void refreshTable() {
    // 清空现有表格数据
    tableModel.setRowCount(0);
    // 重新填充数据
    for (Employee emp : users) {
        tableModel.addRow(new Object[]{
            emp.getFirstName(),
            emp.getLastName(),
            emp.getSalary()
        });
    }
}

4. 在指定位置调用刷新方法

  • 在updateList方法末尾添加调用,确保添加用户后自动刷新:
private void updateList() {
    userList.setListData(users.toArray(new Employee[0]));

    try {
        FileWriter fw = new FileWriter("db.txt", false);
        for (int i = 0; i < users.size(); i++) {
            fw.write(toString(users.get(i).getFirstName(), users.get(i).getLastName(), users.get(i).getSalary()));
        }
        fw.close();

        // 调用刷新表格方法
        refreshTable();
    } catch (IOException io) {
        io.printStackTrace(); // 建议添加异常打印,方便排查问题
    }
}
  • 在viewButton的点击事件中添加调用,支持手动触发刷新:
else if (e.getSource() == viewButton) {
    // 手动触发表格刷新
    refreshTable();
}

修改后的完整代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

class UserManager extends JFrame implements ActionListener {

    private JTextField firstNameField, lastNameField, salaryField;
    private JButton addButton, removeButton, viewButton, sortButton, getButton;
    private JList<Employee> userList;
    private ArrayList<Employee> users;
    // 新增表格相关成员变量
    private JTable userTable;
    private DefaultTableModel tableModel;

    public UserManager() {
        setTitle("Employee Manager");
        setSize(800, 600); // 调整窗口大小,避免表格被压缩
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        firstNameField = new JTextField(20);
        lastNameField = new JTextField(20);
        salaryField = new JTextField(20);
        addButton = new JButton("Add");
        addButton.addActionListener(this);
        removeButton = new JButton("Remove");
        removeButton.addActionListener(this);
        viewButton = new JButton("Refresh List");
        viewButton.addActionListener(this);
        sortButton = new JButton("Sort List");
        sortButton.addActionListener(this);

        // Pulling data from text file database
        ArrayList<ArrayList<String>> databaseData = ReadFile();

        users = new ArrayList<Employee>();

        // Adding existing databaseData to users
        for (int i = 0; i < databaseData.size(); i++) {
            Employee user = new Employee(databaseData.get(i).get(0), databaseData.get(i).get(1), Integer.valueOf(databaseData.get(i).get(2)));
            users.add(user);
        }

        userList = new JList<Employee>(users.toArray(new Employee[0]));
        userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        JPanel firstNamePanel = new JPanel();
        firstNamePanel.add(new JLabel("First Name:"));
        firstNamePanel.add(firstNameField);

        JPanel lastNamePanel = new JPanel();
        lastNamePanel.add(new JLabel("Last Name:"));
        lastNamePanel.add(lastNameField);

        JPanel salaryPanel = new JPanel();
        salaryPanel.add(new JLabel("Salary:"));
        salaryPanel.add(salaryField);

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(addButton);
        buttonPanel.add(removeButton);
        buttonPanel.add(viewButton);
        buttonPanel.add(sortButton);

        // 初始化表格Model和JTable
        String[] columnNames = { "FName", "LName", "Salary" };
        tableModel = new DefaultTableModel(columnNames, 0);
        // 填充初始数据
        for (ArrayList<String> row : databaseData) {
            tableModel.addRow(row.toArray());
        }
        userTable = new JTable(tableModel);
        userTable.setPreferredScrollableViewportSize(new Dimension(700, 300)); // 设置表格首选大小

        // adding it to JScrollPane
        JScrollPane tableScrollPane = new JScrollPane(userTable);

        JPanel mainPanel = new JPanel(new GridLayout(5, 1)); // 调整布局,避免组件重叠
        mainPanel.add(firstNamePanel);
        mainPanel.add(lastNamePanel);
        mainPanel.add(salaryPanel);
        mainPanel.add(buttonPanel);
        mainPanel.add(tableScrollPane);

        add(mainPanel);
        pack(); // 自动调整窗口大小以适应组件
    }

    public void actionPerformed(ActionEvent e) {
        // "Add" button is clicked
        if (e.getSource() == addButton) {
            String firstName = firstNameField.getText();
            String lastName = lastNameField.getText();
            int salary = 0;

            try {
                salary = Integer.parseInt(salaryField.getText());
            } catch (NumberFormatException nfe) {
                JOptionPane.showMessageDialog(this, "Please enter a valid salary", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            // Error check to see if full name and age is entered
            if (!firstName.equals("") && !lastName.equals("")) {
                Employee user = new Employee(firstName, lastName, salary);
                users.add(user);
                updateList();
                firstNameField.setText("");
                lastNameField.setText("");
                salaryField.setText("");

            } else {
                JOptionPane.showMessageDialog(this, "Please enter a valid full name", "Error", JOptionPane.ERROR_MESSAGE);
            }

        } else if (e.getSource() == viewButton) {
            // 手动触发表格刷新
            refreshTable();
        }
        // 可以补充其他按钮的逻辑,比如remove、sort
    }

    // Updates the list after a CRUD operation is called
    private void updateList() {
        userList.setListData(users.toArray(new Employee[0]));

        try {
            FileWriter fw = new FileWriter("db.txt", false);
            // Loop through each student and write to the text file
            for (int i = 0; i < users.size(); i++) {
                fw.write(toString(users.get(i).getFirstName(), users.get(i).getLastName(), users.get(i).getSalary()));
            }
            fw.close();

            // 刷新表格
            refreshTable();
        } catch (IOException io) {
            io.printStackTrace();
        }

    }

    // 刷新JTable的方法
    private void refreshTable() {
        tableModel.setRowCount(0);
        for (Employee emp : users) {
            tableModel.addRow(new Object[]{
                    emp.getFirstName(),
                    emp.getLastName(),
                    emp.getSalary()
            });
        }
    }

    // Combing multiple string and ints into a string
    public String toString(String firstName, String lastName, int salary) {
        return firstName + ", " + lastName + ", " + salary + "\n";
    }

    // Reading database
    public static ArrayList<ArrayList<String>> ReadFile() {
        try {
            File myObj = new File("db.txt");
            Scanner myReader = new Scanner(myObj);
            ArrayList<ArrayList<String>> combinedArr = new ArrayList<ArrayList<String>>();

            while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                ArrayList<String> temp = GetName(data);
                combinedArr.add(temp);
            }
            myReader.close();
            return combinedArr;
        } catch (IOException e) {
            System.out.println("An error occurred reading the file.");
            e.printStackTrace();
        }
        return new ArrayList<ArrayList<String>>();
    }

    // Parses name in db
    public static ArrayList<String> GetName(String data) {
        String first = "";
        String last = "";
        String sal = "";
        for (int i = 0; i < data.length(); i++) {
            if (data.charAt(i) == ',') {
                for (int j = i + 2; j < data.length(); j++) {
                    if (data.charAt(j) == ',') {
                        for (int n = j + 2; n < data.length(); n++) {
                            sal += data.charAt(n);
                        }
                        break;
                    }
                    last += data.charAt(j);
                }
                break;
            }
            first += data.charAt(i);
        }

        ArrayList<String> arr = new ArrayList<String>();
        arr.add(first);
        arr.add(last);
        arr.add(sal);
        return arr;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            UserManager frame = new UserManager();
            frame.setVisible(true);
        });
    }
}

class Employee {
    private String firstName;
    private String lastName;
    private int salary;

    public Employee(String firstName, String lastName, int salary) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.salary = salary;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getSalary() {
        return salary;
    }
}

额外优化点

  • 调整了窗口布局和大小,避免组件重叠或被压缩
  • 添加了SwingUtilities.invokeLater确保UI在EDT线程初始化,符合Swing规范
  • 补充了异常打印,方便排查文件读写问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:05:31