2016-06-17 25 views
1

JTableの中に、以下に示すように合計を計算する列を設定する必要があります。各従業員のための1つのエンティティクラス、1つのテーブルモデルクラス、出力を表示するためのJFrameを拡張する一つのメインクラス、および最後の2列に数字をフォーマットする - 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つのクラスを持っています。コードを以下に示します。私が抱えている問題は、実行中の合計が正しく計算されていないということです。コードが現在書かれているように、最初の合計は80,000と高すぎます。これは、最初の従業員を3回追加してから2番目の従業員に移ると思うようにします。それ以降の合計は正しく追加されますが、最終的な合計は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 

注意してください。この関数は、再ソートする前に0にする必要があります。誰がなぜこれが起こっているのか、それをどう修正するのか教えていただけたら、とても感謝しています。

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

はのsetValueAtを見ているが、これはコンピューティングのための右の場所である、または何 – mKorbel

+0

@mKorbelを設定します。私は、一般的getValueAt 'でこれを行います() '、[example](http://stackoverflow.com/a/37892395/230513)については、どのようなガイダンスも歓迎します。 – trashgod

+0

は私のオリジナルのアイデアは、後でXxxTableCellEditorから変更が – mKorbel

答えて

2

How to Use Tables: Sorting and Filteringで説明したように、「ソーターを使用する場合は、必ずセルの座標を変換することを忘れないでください。」 JTableビュー内で並べ替えが発生するため、getValueAt()の実装でCOLUMN_SUMの部分和を計算するときはビュー座標を使用し、その列の並べ替えは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; 
     } 
    } 
} 
+0

それをしました。ヘルプとあなたの有益なコメントをありがとう! – user5991980

0

getValueAtへの各呼び出しはな生産しなければなりません先にgetValueAtを呼び出した結果に依存せずに要求されたセルの値。getValueAtが呼び出される時期と頻度を制御できないためです。

@ trashgodの例のように要求されるたびに正しい合計を再計算します。

+0

この[例](HTTPを量(plus_1)のセットを再計算することができ、代わりにXxxTableCellRendererからかなり集中的な計算を、モデルに格納された値として、この量を保持することでした@trashgod:// stackoverflow.com/a/37892395/230513) 'getValueAt()は'オーバーライド。どの回帰の報告も歓迎します。 – trashgod

0

rowIndexの値が0であるかのように変更することができます。

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

rowIndex = 0の場合。それは以下のようになるはずです。

salarySum = employee.getSalary(); 
関連する問題