Calculate running total in JTable

前端 未结 3 1194
日久生厌
日久生厌 2020-12-11 12:22

I need to populate a column in my JTable that computes a running total as is shown below.

ID   Name   Position   Salary    Total
===  ====== ========== ====         


        
相关标签:
3条回答
  • 2020-12-11 12:39

    May be you can change like after having a check for zero on rowIndex.

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

    And in the case of rowIndex = 0; it should be like below.

    salarySum =  employee.getSalary();
    
    0 讨论(0)
  • 2020-12-11 12:40

    Each call to getValueAt must produce the value for the requested cell without relying on the result of any previous call to getValueAt, because you have no control over when and how often getValueAt will be called.

    Recompute the correct total each time it is requested as in @trashgod's example.

    0 讨论(0)
  • 2020-12-11 12:45

    As discussed in How to Use Tables: Sorting and Filtering, "When using a sorter, always remember to translate cell coordinates." Because JTable sorting occurs in the view, use view coordinates when calculating the partial sum for COLUMN_SUM in your implementation of getValueAt(), and disable sorting for that column as shown here.

    @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;
    }
    

    As tested:

    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;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题