当前位置: 首页 > 知识库问答 >
问题:

在JTable中计算运行总数

黄涵畅
2023-03-14

我需要在我的JTable中填充一列,该列计算一个运行总计,如下所示。

ID   Name   Position   Salary    Total
===  ====== ========== =======   ======
1.   Peter  Programmer  40,000   40,000
2.   Paul   Manager     25,000   65,000
3.   Mary   Designer    25,000   90,000

我有4个类——每个员工一个实体类,一个表模型类,一个扩展JFrame以显示输出的主类,以及一个用于格式化最后两列中的数字。代码如下所示。我遇到的问题是运行总数没有正确计算。由于当前编写的代码,第一个总数太高了80,000,这让我认为它在移动到第二个员工之前添加了第一个员工三次。每个后续总数都被正确添加,但当然最终总数相差80,000。这是输出现在的样子:

ID   Name   Position   Salary   Total
===  ====== ========== =======   ======
1.   Peter  Programmer  40,000   120,000
2.   Paul   Manager     25,000   145,000
3.   Mary   Designer    25,000   170,000

请注意,在下面的代码中,该表可以按列重新排序,并包含一个侦听器来重新计算运行总数。在重新排序之前,此函数需要归零,现在它没有这样做。如果有人能告诉我为什么会发生这种情况以及如何修复它,我会非常感激。

public class JTableRunningTotalExample extends JFrame
{
    private static final long serialVersionUID = 1L;
    private JTable table;
    private TableModel tableModel;
    private NumberCellFormatter numberCellFormatter = new NumberCellFormatter();
    private int salarySum = 0;
    private List<Employee> listEmployees;
    private Employee employee;

    public JTableRunningTotalExample()
    {
        super("JTable Sorting Example");
        createListEmployees();
        tableModel = new EmployeeTableModel(listEmployees);
        table = new JTable(tableModel);
        for (int j=3; j<5; j++)
        {
            table.getColumnModel().getColumn(j).setCellRenderer(numberCellFormatter);
        }

        TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());
        table.setRowSorter(sorter);
        List<RowSorter.SortKey> sortKeys = new ArrayList<>();

        int columnIndexToSort = 0;
        sortKeys.add(new RowSorter.SortKey(columnIndexToSort, SortOrder.ASCENDING));

        sorter.setSortKeys(sortKeys);
        sorter.sort();
        sorter.addRowSorterListener(new RowSorterListener()
        {
            public void sorterChanged(RowSorterEvent evt)
            {
                int columnIndex = 0;
                salarySum = 0;
                for (int i = 0; i < table.getRowCount(); i++)
                {
                    table.setValueAt(i + 1, i, columnIndex);
                }
            }
        });
        add(new JScrollPane(table), BorderLayout.CENTER);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void createListEmployees()
    {
        listEmployees = new ArrayList<>();
        listEmployees.add(new Employee("Peter", "Manager", 40000));
        listEmployees.add(new Employee("Paul", "Programmer", 25000));
        listEmployees.add(new Employee("Mary", "Designer", 25000));
        listEmployees.add(new Employee("Donald", "Leader", 30000));
        listEmployees.add(new Employee("Tom", "Designer", 28000));
        listEmployees.add(new Employee("Samantha", "Analyst", 50000));
        listEmployees.add(new Employee("Jerome", "Programmer", 32000));
        listEmployees.add(new Employee("Jonathon", "Developer", 29000));
        listEmployees.add(new Employee("Kevin", "Programmer", 23000));
        listEmployees.add(new Employee("Anthony", "Programmer", 23000));
        listEmployees.add(new Employee("John", "Designer", 33000));
        listEmployees.add(new Employee("David", "Developer", 28000));
        listEmployees.add(new Employee("Harry", "Designer", 31000));
        listEmployees.add(new Employee("Charles", "Programmer", 26000));
        listEmployees.add(new Employee("Joseph", "Manager", 40000));
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JTableRunningTotalExample frame = new JTableRunningTotalExample();
                frame.setVisible(true);
                frame.setLocationRelativeTo(null);
            }
        });
    }
}

*****表格模型类* * * * *

public class EmployeeTableModel extends AbstractTableModel
{
    private static final long serialVersionUID = 1L;
    private static final int COLUMN_NUM = 0;
    private static final int COLUMN_NAME = 1;
    private static final int COLUMN_JOB = 2;
    private static final int COLUMN_SALARY = 3;
    private static final int COLUMN_SUM = 4;

    private String[] columnNames = { "No #", "Name", "Job", "Salary", "Total Payroll" };
    private List<Employee> listEmployees;
    private int salarySum = 0;
    private Employee employee;

    public EmployeeTableModel(List<Employee> listEmployees)
    {
        this.listEmployees = listEmployees;
        int indexCount = 1;
        for (Employee employee : listEmployees)
        {
            employee.setIndex(indexCount++);
        }
    }

    @Override
    public int getColumnCount()
    {
        return columnNames.length;
    }

    @Override
    public int getRowCount()
    {
        return listEmployees.size();
    }

    @Override
    public String getColumnName(int columnIndex)
    {
        return columnNames[columnIndex];
    }

    @Override
    public Class<?> getColumnClass(int columnIndex)
    {
        if (listEmployees.isEmpty())
        {
            return Object.class;
        }
        return getValueAt(0, columnIndex).getClass();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        employee = listEmployees.get(rowIndex);
        Object returnValue = null;
        switch (columnIndex)
        {
            case COLUMN_NUM:
                returnValue = employee.getIndex();
                break;
            case COLUMN_NAME:
                returnValue = employee.getName();
                break;
            case COLUMN_JOB:
                returnValue = employee.getJob();
                break;
            case COLUMN_SALARY:
                returnValue = employee.getSalary();
                break;
            case COLUMN_SUM:
                salarySum = salarySum + employee.getSalary();
                returnValue = salarySum ;
                break;
            default:
                throw new IllegalArgumentException("Invalid column index");
        }
        return returnValue;
    }
}

*****Empoloyee实体类*****

public class Employee
{
    private int index;
    private String name;
    private String job;
    private int salary;

    public Employee(String name, String job, int salary) 
    {
        this.name = name;
        this.job = job;
        this.salary = salary;
    }

    public int getIndex()
    {
        return index;
    }

    public void setIndex(int index)
    {
        this.index = index;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getJob()
    {
        return job;
    }

    public void setJob(String job)
    {
        this.job = job;
    }

    public int getSalary()
    {
        return salary;
    }

    public void setSalary(int age)
    {
        this.salary = age;
    }
}

单元格渲染器类*****

public class NumberCellFormatter extends DefaultTableCellRenderer
{
    private static final long serialVersionUID = 1L;
    private NumberFormat numberFormat = new DecimalFormat("#,###,###");
    private double formattedNumber;

    public double setNumberFormat(String number)
    {
        formattedNumber = Double.parseDouble(numberFormat.format(number));
        return formattedNumber;
    }
    @Override
    public Component getTableCellRendererComponent(JTable jTable, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        Component c = super.getTableCellRendererComponent(jTable, value, isSelected, hasFocus, row, column);
        if (c instanceof JLabel && value instanceof Number)
        {
            JLabel label = (JLabel) c;
            label.setHorizontalAlignment(JLabel.RIGHT);
            Number num = (Number) value;
            String text = numberFormat.format(num);
            label.setText(text);
            label.setForeground(num.doubleValue() < 0 ? Color.RED : Color.BLACK);
        }
        return c;
    }
}

共有3个答案

锺功
2023-03-14

getValueAt的每次调用都必须生成请求单元格的值,而不依赖于之前对getValueAt的任何调用的结果,因为您无法控制何时以及多久调用getValueAt

每次请求时重新计算正确的总计,如@trashgod的示例所示。

太叔昆
2023-03-14

也许您可以在rowIndex上检查零之后进行更改。

salarySum = (Integer)getValueAt(rowIndex-1, columnIndex)+ employee.getSalary();

并且在rowIndex=0的情况下;它应该如下所示。

salarySum =  employee.getSalary();
拓拔弘扬
2023-03-14

如“如何使用表:排序和筛选”中所述,“使用排序器时,请始终记住转换单元格坐标。”由于<code>JTable</code>排序发生在视图中,因此在实现<code>getValueAt()</code>中计算<code>COLUMN_sum</code>的部分和时,请使用视图坐标,并禁用该列的排序,如下所示。

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    Employee employee = listEmployees.get(rowIndex);
    switch (columnIndex) {
        …
        case COLUMN_SUM:
            return partialSum(rowIndex);
        …
    }
}

private int partialSum(int row) {
    int viewRow = table.convertRowIndexToView(row);
    int viewCol = table.convertColumnIndexToView(COLUMN_SALARY);
    int sum = (int) table.getValueAt(viewRow, viewCol);
    for (int i = 0; i < viewRow; i++) {
        sum += (int) table.getValueAt(i, viewCol);
    }
    return sum;
}

经测试:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultRowSorter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;

/** @see https://stackoverflow.com/a/37892395/230513 */
public class JTableRunningTotalExample extends JFrame {

    private final NumberCellFormatter numberCellFormatter = new NumberCellFormatter();

    public JTableRunningTotalExample() {
        super("JTable Sorting Example");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTable table = new JTable() {
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(500, getRowCount() * getRowHeight());
            }
        };
        List<Employee> listEmployees = createListEmployees();
        TableModel model = new EmployeeTableModel(table, listEmployees);
        table.setModel(model);
        table.setAutoCreateRowSorter(true);
        DefaultRowSorter sorter = (DefaultRowSorter) table.getRowSorter();
        sorter.setSortable(4, false);
        for (int j = 3; j < 5; j++) {
            table.getColumnModel().getColumn(j).setCellRenderer(numberCellFormatter);
        }
        add(new JScrollPane(table), BorderLayout.CENTER);
        pack();
    }

    private List<Employee> createListEmployees() {
        List<Employee> listEmployees = new ArrayList<>();
        listEmployees.add(new Employee("Peter", "Manager", 40000));
        listEmployees.add(new Employee("Paul", "Programmer", 25000));
        listEmployees.add(new Employee("Mary", "Designer", 25000));
        listEmployees.add(new Employee("Donald", "Leader", 30000));
        listEmployees.add(new Employee("Tom", "Designer", 28000));
        listEmployees.add(new Employee("Samantha", "Analyst", 50000));
        listEmployees.add(new Employee("Jerome", "Programmer", 32000));
        listEmployees.add(new Employee("Jonathon", "Developer", 29000));
        listEmployees.add(new Employee("Kevin", "Programmer", 23000));
        listEmployees.add(new Employee("Anthony", "Programmer", 23000));
        listEmployees.add(new Employee("John", "Designer", 33000));
        listEmployees.add(new Employee("David", "Developer", 28000));
        listEmployees.add(new Employee("Harry", "Designer", 31000));
        listEmployees.add(new Employee("Charles", "Programmer", 26000));
        listEmployees.add(new Employee("Joseph", "Manager", 40000));
        return listEmployees;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JTableRunningTotalExample frame = new JTableRunningTotalExample();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private static class EmployeeTableModel extends AbstractTableModel {

        private static final int COLUMN_NUM = 0;
        private static final int COLUMN_NAME = 1;
        private static final int COLUMN_JOB = 2;
        private static final int COLUMN_SALARY = 3;
        private static final int COLUMN_SUM = 4;

        private String[] columnNames = {"No", "Name", "Job", "Salary", "Total Payroll"};
        JTable table;
        private List<Employee> listEmployees;

        public EmployeeTableModel(JTable table, List<Employee> listEmployees) {
            this.table = table;
            this.listEmployees = listEmployees;
            int indexCount = 1;
            for (Employee employee : listEmployees) {
                employee.setIndex(indexCount++);
            }
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return listEmployees.size();
        }

        @Override
        public String getColumnName(int columnIndex) {
            return columnNames[columnIndex];
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return getValueAt(0, columnIndex).getClass();
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Employee employee = listEmployees.get(rowIndex);
            switch (columnIndex) {
                case COLUMN_NUM:
                    return employee.getIndex();
                case COLUMN_NAME:
                    return employee.getName();
                case COLUMN_JOB:
                    return employee.getJob();
                case COLUMN_SALARY:
                    return employee.getSalary();
                case COLUMN_SUM:
                    return partialSum(rowIndex);
                default:
                    throw new IllegalArgumentException("Invalid column index");
            }
        }

        private int partialSum(int row) {
            int viewRow = table.convertRowIndexToView(row);
            int viewCol = table.convertColumnIndexToView(COLUMN_SALARY);
            int sum = (int) table.getValueAt(viewRow, viewCol);
            for (int i = 0; i < viewRow; i++) {
                sum += (int) table.getValueAt(i, viewCol);
            }
            return sum;
        }
    }

    private static class Employee {

        private int index;
        private String name;
        private String job;
        private int salary;

        public Employee(String name, String job, int salary) {
            this.name = name;
            this.job = job;
            this.salary = salary;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getJob() {
            return job;
        }

        public void setJob(String job) {
            this.job = job;
        }

        public int getSalary() {
            return salary;
        }

        public void setSalary(int age) {
            this.salary = age;
        }
    }

    private static class NumberCellFormatter extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;
        private NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
        private double formattedNumber;

        public double setNumberFormat(String number) {
            formattedNumber = Double.parseDouble(numberFormat.format(number));
            return formattedNumber;
        }

        @Override
        public Component getTableCellRendererComponent(JTable jTable, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(jTable, value,
                isSelected, hasFocus, row, column);
            if (c instanceof JLabel && value instanceof Number) {
                JLabel label = (JLabel) c;
                label.setHorizontalAlignment(JLabel.RIGHT);
                Number num = (Number) value;
                String text = numberFormat.format(num);
                label.setText(text);
                label.setForeground(num.doubleValue() < 0 ? Color.RED : Color.BLACK);
            }
            return c;
        }
    }
}
 类似资料:
  • 问题内容: 我有这个MySQL查询: 返回如下内容: 我真正想要的是末尾的另一列显示运行总计: 这可能吗? 问题答案: 也许这对您来说是一个更简单的解决方案,并且可以防止数据库不得不执行大量查询。这仅执行一个查询,然后在一次通过中对结果进行一点数学运算。 这将为您提供一个额外的RT(运行总计)列。不要错过顶部的SET语句来首先初始化运行的total变量,否则您将只获得一列NULL值。

  • 问题内容: 我有这个MySQL查询: 返回如下内容: 我真正想要的是末尾的另一列以显示运行总计: 这可能吗? 问题答案: 也许对您来说是一个更简单的解决方案,并且可以防止数据库不得不执行大量查询。这仅执行一个查询,然后在一次通过中对结果进行一些数学运算。 这将为您提供一个额外的RT(运行总计)列。不要错过顶部的SET语句来首先初始化运行中的total变量,否则您将只获得一列NULL值。

  • 问题内容: 想象一下下表(称为): 我想要一个按日期顺序返回运行总计的查询,例如: 我知道在SQL Server 2000/2005/2008中可以通过多种方式进行此操作。 我对使用aggregating-set-statement技巧的这种方法特别感兴趣: …这是非常有效的,但是我听说周围存在一些问题,因为您不一定能保证该语句将以正确的顺序处理行。也许我们可以获得有关该问题的明确答案。 但是,人

  • 我创建了一个应用程序,在我的计算机中,这个jar运行没有任何问题。我试着在另一台电脑上运行它,它什么都做不到。然后,我在另一台pc上尝试了同样的jar(如果你想这样看的话,是第三台),在那里,jar运行没有问题。所以我回到第二个,试着从命令行运行它,它给了我这个错误: “main”java.lang.UnsatisfiedLinkError头出现异常:无法加载库:C:\users\hectlr\l

  • 问题内容: 在没有应用任何条件的情况下,对表中的行总数进行计数的最佳MySQL命令是什么?我正在通过php执行此操作,所以也许有一个php函数可以为我执行此操作?我不知道。这是我的php的示例: 问题答案:

  • 对于这个问题,我找到了一些不同的答案,但似乎无法使查询正常工作。 这是我的表,其中包含user、weekNo、salesTotalYTD列。 我目前正在把这些拿出来,按周分组,就像这样: 我试图做但无法完成的是: 这是我为第一次通过工作的查询,但之后的每一次通过都是错误的: 更新 更新代码由蒂姆提供,但返回错误: