如何在Java JTable中实现列数据求和行并随新增行更新?
解决JTable添加动态求和行并同步更新的问题
核心思路
- 单独维护求和行:将求和行作为表格最后一行,每次数据变化(新增行、修改数量/价格)时,先移除旧求和行,重新计算总和后添加新的求和行。
- 联动更新Total列:修改数量或价格时自动更新对应行的Total值,同时触发求和行更新。
- 禁止编辑求和行:避免用户误操作修改求和数据。
完整代码示例
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
相关产品推荐
相关产品推荐

