我需要在我的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;
}
}
对getValueAt
的每次调用都必须生成请求单元格的值,而不依赖于之前对getValueAt
的任何调用的结果,因为您无法控制何时以及多久调用getValueAt
。
每次请求时重新计算正确的总计,如@trashgod的示例所示。
也许您可以在rowIndex上检查零之后进行更改。
salarySum = (Integer)getValueAt(rowIndex-1, columnIndex)+ employee.getSalary();
并且在rowIndex=0的情况下;它应该如下所示。
salarySum = employee.getSalary();
如“如何使用表:排序和筛选”中所述,“使用排序器时,请始终记住转换单元格坐标。”由于<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列。 我目前正在把这些拿出来,按周分组,就像这样: 我试图做但无法完成的是: 这是我为第一次通过工作的查询,但之后的每一次通过都是错误的: 更新 更新代码由蒂姆提供,但返回错误: