2012-04-21 34 views
4

我正在开发我的CapStone项目以完成本学期的学习,并且遇到了我正在编写的程序的一些问题。该代码适用于Serendipity书商计划。我将为虚构的书店设计一个销售点系统。CellEditorListener无法检测到单元格编辑的时间

目前,我试图让“Total”列(第5列)在用户编辑给定行的“Qty”单元格时更新。 “数量”字段还需要验证其单元格中的值不超过库存数量(第1列)。

我也读过了Java教程中的How to Use Tables,并且昨晚在Google上搜索了好几个小时,试图找到一些关于如何让CellEditorListener工作的有用代码。

我以前也试过具有CashierPanel类实现CellEditorListener,并通过注册它:

CellEditorListener listener = null; 
table.getDefaultEditor(String.class).addCellEditorListener(listener); 

这种方法也不能工作。

这里是我现在(217线)有代码:

/* Imported Dependencies */ 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.math.BigDecimal; 
import java.math.RoundingMode; 
import java.util.ArrayList; 

import javax.swing.DefaultCellEditor; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.event.CellEditorListener; 
import javax.swing.event.ChangeEvent; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableColumn; 

import net.miginfocom.swing.MigLayout; 

public class CashierPanel extends JFrame { 

    /** 
    * Serial Version UID 
    */ 
    private static final long serialVersionUID = 6922826100788686147L; 

    /* Private Fields */ 
    private JPanel searchPanel; 
    private JLabel isbn_lbl; 
    private JLabel title_lbl; 
    private JTextField isbn_tf; 
    private JTextField title_tf; 
    private JTextField currentCell; 
    private BookCollection myCollection; 
    private CashierTableModel tableData; 

    private CellEditorListener listener; 

    /** 
    * Constructor 
    */ 
    public CashierPanel() { 

     // Set window properties 
     setTitle("Testing this table"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(585, 300); 
     setLayout(new BorderLayout()); 

     tableData = new CashierTableModel(); 
     final JTable table = new JTable(tableData); 
     table.setRowHeight(25); 
     table.getTableHeader().setReorderingAllowed(false); 
     table.setCellSelectionEnabled(true); 
     table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 
     add(new JScrollPane(table), BorderLayout.CENTER); 

     // Define a cell renderer to render text to center of cell 
     DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer(); 
     centerRenderer.setHorizontalAlignment(JLabel.CENTER); 

     // Set column properties 
     int[] sizes = new int[] { 50, 50, 87, 275, 50, 50 }; 
     String[] columnNames = new String[] { "Qty", "Stock", "ISBN", "Title", 
       "Price", "Total" }; 
     TableColumn[] column = new TableColumn[columnNames.length]; 
     for (byte i = 0; i < columnNames.length; i++) { 
      column[i] = table.getColumnModel().getColumn(i); 
      column[i].setMinWidth(sizes[i]); 
      column[i].setHeaderValue(columnNames[i]); 
      if (i != 3) { 
       column[i].setMaxWidth(sizes[i]); 
       column[i].setCellRenderer(centerRenderer); 
      } 
     } 

     /* Make the quantity field only display digits */ 
     currentCell = new JTextField(); 
     column[0].setCellEditor(new DefaultCellEditor(currentCell)); 
     // Add a key listener to the current cell 
     currentCell.addKeyListener(new KeyAdapter() { 
      public void keyTyped(KeyEvent e) { 
       // if the key typed is not a digit or backspace 
       if (!Character.isDigit(e.getKeyChar()) 
         && e.getKeyChar() != KeyEvent.VK_BACK_SPACE) { 
        currentCell.setEditable(false); 
        currentCell.setBackground(Color.WHITE); 
       } else { 
        currentCell.setEditable(true); 
       } 
      } 
     }); 

     /* Search panel */ 
     searchPanel = new JPanel(); 
     myCollection = new BookCollection(); 

     isbn_lbl = new JLabel("Search by ISBN:"); 
     isbn_tf = new JTextField(); 
     isbn_tf.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       ArrayList<BookData> data = myCollection.select(isbn_tf.getText(), BookCollection.FIELD_ISBN); 
       tableData.addNewRow(); 
       table.setValueAt((new BigDecimal("1").toString()), tableData.getRowCount() - 1, 0); 
       table.setValueAt(Integer.toString(data.get(0).getQtyOnHand()), tableData.getRowCount() - 1, 1); 
       table.setValueAt(data.get(0).getIsbn(),tableData.getRowCount() - 1, 2); 
       table.setValueAt(data.get(0).getTitle(),tableData.getRowCount() - 1, 3); 
       table.setValueAt(data.get(0).getRetail().setScale(2, RoundingMode.HALF_UP).toString(), tableData.getRowCount() - 1, 4); 
       table.setValueAt(table.getValueAt(tableData.getRowCount() - 1, 4), tableData.getRowCount() - 1, 5); 
       isbn_tf.setText(""); 
      } 
     }); 

     title_lbl = new JLabel("Search by Title:"); 
     title_tf = new JTextField(); 
     title_tf.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       ArrayList<BookData> data = myCollection.select(title_tf.getText(), BookCollection.FIELD_TITLE); 
       tableData.addNewRow(); 
       table.setValueAt((new BigDecimal("1").toString()), tableData.getRowCount(), 0); 
       table.setValueAt(Integer.toString(data.get(0).getQtyOnHand()), tableData.getRowCount() - 1, 1); 
       table.setValueAt(data.get(0).getIsbn(), tableData.getRowCount(), 2); 
       table.setValueAt(data.get(0).getTitle(), tableData.getRowCount(), 3); 
       table.setValueAt(data.get(0).getRetail().setScale(2, RoundingMode.HALF_UP).toString(), tableData.getRowCount(), 4); 
       table.setValueAt(data.get(0).getRetail().setScale(2, RoundingMode.HALF_UP).toString(), tableData.getRowCount(), 5); 
       title_tf.setText(""); 
      } 
     }); 

     searchPanel.setLayout(new MigLayout("", "[78px][202px,grow]", "[24px][29px]")); 
     searchPanel.add(isbn_lbl, "cell 0 0, alignx left, aligny center"); 
     searchPanel.add(isbn_tf, "cell 1 0,growx, aligny center"); 
     searchPanel.add(title_lbl, "cell 0 1, alignx left, aligny center"); 
     searchPanel.add(title_tf, "cell 1 1, growx, aligny center"); 

     add(searchPanel, BorderLayout.SOUTH); 

    }; 

    public static void main(String[] args) { 
     CashierPanel myCashierPanel = new CashierPanel(); 
     myCashierPanel.setVisible(true); 
    } 
} 

class CashierTableModel extends AbstractTableModel implements CellEditorListener{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -1500952132717353189L; 
    private ArrayList<Object[]> data = new ArrayList<Object[]>(); 

    public void addNewRow() { 
     data.add(new String[] { null, null, null, null, null, null }); 
     fireTableDataChanged(); 
    } 

    public int getRowCount() { 
     return data.size(); 
    } 

    public int getColumnCount() { 
     return 6; 
    } 

    public Object getValueAt(int row, int col) { 
     return data.get(row)[col]; 
    } 

    public void setValueAt(Object value, int row, int col) { 
     data.get(row)[col] = value; 
     fireTableCellUpdated(row, col); 
    } 

    public boolean isCellEditable(int row, int col) { 
     if (col > 0) { 
      return false; 
     } else { 
      return true; 
     } 
    } 

    public void editingCanceled(ChangeEvent e) { 
     for (int i = 0; i <= getRowCount() - 1; i++) { 
      BigDecimal[] data = new BigDecimal[3]; 
      data[0] = data[0].add((BigDecimal) getValueAt(i, 1)); 
      data[1] = data[1].add((BigDecimal) getValueAt(i, 4)); 
      data[2] = data[2].add(calculateTotal(data[0], data[1])); 
      setValueAt(data[2], i, 5); 
     } 
    } 

    public void editingStopped(ChangeEvent e) { 
     for (int i = 0; i <= getRowCount() - 1; i++) { 
      BigDecimal[] data = new BigDecimal[3]; 
      data[0] = data[0].add((BigDecimal) getValueAt(i, 1)); 
      data[1] = data[1].add((BigDecimal) getValueAt(i, 4)); 
      data[2] = data[2].add(calculateTotal(data[0], data[1])); 
      setValueAt(data[2], i, 5); 
     } 
    } 

    public BigDecimal calculateTotal(BigDecimal qty, BigDecimal retail) { 
     BigDecimal total = new BigDecimal("0.00"); 
     total = total.add(qty.multiply(retail)); 
     return total; 
    } 
} 

由于这是家庭作业,我不想交给我的代码工作版本,具有了漏洞。我只想得到一些指导,说明我在做错误的事情,让编辑器侦听器实际被调用。

如果有任何其他信息可以帮助我指导解决方案,请告诉我。

感谢您花时间看这个!

+1

'CellEditorListener listener = null;'后面跟着'table.getDefaultEditor(String.class).addCellEditorListener(listener);''您将作为侦听器添加null,这当然是保证不起作用。 – 2012-04-21 22:54:25

+0

意识到这不是现在的确切代码,在指出我后。我只是尝试将侦听器添加为新的CellEditorListener,并将我的代码添加到了editStopped方法中。仍然没有工作。 – 2012-04-21 23:38:58

+0

+1现在你会投票 – mKorbel 2012-04-22 09:03:18

回答

5

在@ AKJ有用的answer上进行了扩展,该example讨论了单元编辑器的正常操作,而此example说明了更新编辑器相关数据的一种方法。

+0

如果我有15声望+1,我会的。你给我的第二个[示例](http://stackoverflow.com/a/7356518/230513)正是我正在寻找的东西,现在我的桌子正常工作。 – 2012-04-22 07:09:21

+0

很高兴帮助。如有可能,我敦促您声明@ AKJ的独到见解 – trashgod 2012-04-22 09:03:21

5

您不应该自己添加显式键监听器给单元编辑器并处理这些事件。

默认情况下,根据列类型(如果模型返回单元格为可编辑),jtable将自动选择适当的编辑器。如果你需要你自己的自定义编辑器(用于着色等),那么你也需要将它实现为单元编辑器,然后将其设置为列模型。

一旦您在jtable中安装了编辑器(无论何时修改值)(可能会在焦点丢失时触发),jtable将自动调用模型的setValueAt()。你所有的更新另一个依赖列的逻辑应该属于这里。