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

如何在Java JTable中实现列数据求和行并随新增行更新?

解决JTable添加动态求和行并同步更新的问题

核心思路

  1. 单独维护求和行:将求和行作为表格最后一行,每次数据变化(新增行、修改数量/价格)时,先移除旧求和行,重新计算总和后添加新的求和行。
  2. 联动更新Total列:修改数量或价格时自动更新对应行的Total值,同时触发求和行更新。
  3. 禁止编辑求和行:避免用户误操作修改求和数据。

完整代码示例

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;

public class TableTotalDemo extends JFrame {
    private DefaultTableModel model;
    private JTable table;
    private JTextField quantityField;
    private JTextField priceField;

    public TableTotalDemo() {
        setTitle("Product Table with Total Sum");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 400);
        setLocationRelativeTo(null);

        // 初始化表格模型,列名:ID, Name, Quantity, Price, Total
        model = new DefaultTableModel(new String[]{"ID", "Product Name", "Quantity", "Price", "Total"}, 0);
        table = new JTable(model) {
            @Override
            public boolean isCellEditable(int row, int column) {
                // 最后一行是求和行,不可编辑;其他行仅Quantity和Price可编辑
                if (row == getRowCount() - 1 && "Total".equals(getValueAt(row, 0))) {
                    return false;
                }
                return column == 2 || column == 3;
            }
        };

        // 添加表格模型监听器,修改Quantity/Price时自动更新Total并同步求和行
        model.addTableModelListener(e -> {
            int row = e.getFirstRow();
            int column = e.getColumn();
            // 排除求和行的修改(如果有的话)
            if (row < model.getRowCount() - 1 && (column == 2 || column == 3)) {
                updateRowTotal(row);
                updateTotalRow();
            }
        });

        // 顶部输入面板
        JPanel inputPanel = new JPanel();
        inputPanel.add(new JLabel("Quantity:"));
        quantityField = new JTextField(5);
        inputPanel.add(quantityField);
        inputPanel.add(new JLabel("Price:"));
        priceField = new JTextField(5);
        inputPanel.add(priceField);
        JButton addBtn = new JButton("Add Product");
        addBtn.addActionListener(this::addProductRow);
        inputPanel.add(addBtn);

        // 组装界面
        add(inputPanel, BorderLayout.NORTH);
        add(new JScrollPane(table), BorderLayout.CENTER);
        setVisible(true);
    }

    // 添加商品行并计算当前行Total
    private void addProductRow(ActionEvent e) {
        try {
            int quantity = Integer.parseInt(quantityField.getText().trim());
            double price = Double.parseDouble(priceField.getText().trim());
            double total = quantity * price;
            // 生成ID和商品名(可根据实际需求修改)
            int id = model.getRowCount() + 1;
            String productName = "Product " + id;
            model.addRow(new Object[]{id, productName, quantity, price, total});
            // 更新求和行
            updateTotalRow();
            // 清空输入框
            quantityField.setText("");
            priceField.setText("");
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this, "请输入有效的数字!", "输入错误", JOptionPane.WARNING_MESSAGE);
        }
    }

    // 更新指定行的Total值
    private void updateRowTotal(int row) {
        try {
            int quantity = Integer.parseInt(model.getValueAt(row, 2).toString().trim());
            double price = Double.parseDouble(model.getValueAt(row, 3).toString().trim());
            double total = quantity * price;
            model.setValueAt(total, row, 4);
        } catch (NumberFormatException ex) {
            model.setValueAt(0.0, row, 4);
        }
    }

    // 更新求和行:先移除旧求和行,计算总和后添加新行
    private void updateTotalRow() {
        // 移除已存在的求和行
        int rowCount = model.getRowCount();
        if (rowCount > 0 && "Total".equals(model.getValueAt(rowCount - 1, 0))) {
            model.removeRow(rowCount - 1);
        }
        // 计算所有商品行的Total总和
        double sum = 0.0;
        for (int i = 0; i < model.getRowCount(); i++) {
            Object totalObj = model.getValueAt(i, 4);
            if (totalObj instanceof Double) {
                sum += (Double) totalObj;
            }
        }
        // 添加新的求和行
        model.addRow(new Object[]{"Total", "", "", "", sum});
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TableTotalDemo::new);
    }
}

关键代码说明

  • 求和行维护:updateTotalRow方法负责移除旧求和行、计算总和、添加新求和行,确保每次数据变化后求和结果准确。
  • Total列联动:通过TableModelListener监听表格数据变化,当修改Quantity或Price列时,调用updateRowTotal更新当前行的Total,再触发求和行更新。
  • 编辑权限控制:重写JTable的isCellEditable方法,禁止编辑求和行,同时限制普通行仅Quantity和Price列可编辑,避免误操作。

注意事项

  • 如果需要支持删除行操作,只需在删除行后调用updateTotalRow即可同步求和结果。
  • 处理输入异常时,可根据实际需求调整提示信息或默认值。
  • 若表格数据量较大,可优化求和计算逻辑(比如维护一个全局总和变量,新增/修改/删除时直接更新变量,避免遍历所有行)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:34:52