gpt4 book ai didi

java - 计算 JTable 中的运行总计

转载 作者:行者123 更新时间:2023-11-30 02:53:43 24 4
gpt4 key购买 nike

我需要在 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;
}
}

*****Employee实体类*****

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

最佳答案

How to Use Tables: Sorting and Filtering 中所述,“使用排序器时,请始终记住翻译单元格坐标。”由于 JTable 排序发生在 View 中,因此在 getValueAt() 实现中计算 COLUMN_SUM 的部分总和时使用 View 坐标,并禁用排序对于该列,如图所示 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;
}

image

经测试:

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

关于java - 计算 JTable 中的运行总计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37872229/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com