JTable:检测单元数据的变化

在Netbeans中,我使用GUI Builder将JTable插入到我的应用程序中。

到目前为止,我只有一个类(CustomerDB):

package CustomerDB; import [...]; public class CustomerDB extends javax.swing.JFrame { CellEditorListener ChangeNotification = new CellEditorListener() { public void editingCanceled(ChangeEvent e) { System.out.println("The user canceled editing."); } public void editingStopped(ChangeEvent e) { System.out.println("The user stopped editing successfully."); } }; public CustomerDB() { customerTable = new javax.swing.JTable(); customerTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null} }, new String [] { "ID", "Name", "Address", "Phone" } ) { Class[] types = new Class [] { java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class }; public Class getColumnClass(int columnIndex) { return types [columnIndex]; } }); customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification); } public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new CustomerDB().setVisible(true); } }); } // Variables declaration - do not modify [...] private javax.swing.JTable customerTable; [...] // End of variables declaration } 

每当用户更改表中的数据时,我想获取旧值(可选)和该单元格的新值。

为了获得这些数据,我试图实现一个事件监听器:

  CellEditorListener ChangeNotification = new CellEditorListener() { public void editingCanceled(ChangeEvent e) { System.out.println("The user canceled editing."); } public void editingStopped(ChangeEvent e) { System.out.println("The user stopped editing successfully."); } }; 

然后我将这个CellEditorListener分配给表(它的单元格编辑器):

  customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification); 

到目前为止这个工作。 但它还不能让我检测到这个细胞的旧值和新值。 还有什么我需要做的?

非常感谢你提前!

但它还不能让我检测到这个细胞的旧值和新值。 还有什么我需要做的?

使用TableModelListener监听更改更容易,但仍然存在无法访问旧值的问题。

查看表格单元侦听器以获取解决方案,该解决方案可让您访问“旧值”以及“新值”。

或具有ListSelectionListener的TableModelLister,如果TableCell发生更改,则返回第四个,从选定的调用返回第二个,然后仅使用ListSelectionListener比较TableModelLister中的行和列索引

 import java.awt.*; import java.util.Random; import java.util.Vector; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; public class Forum implements ListSelectionListener { private JFrame frame = new JFrame("Frame"); private JPanel fatherCenter = new JPanel(); private JScrollPane tableScroll = new JScrollPane(); private myTableModel tableModel; private JTable dialogTable; private ListSelectionModel lsDialog; private void addComponentsToPane(Container pane) { tableModel = new myTableModel(); dialogTable = new JTable(tableModel) { private static final long serialVersionUID = 1L; @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { Component comp = super.prepareRenderer(renderer, row, column); JComponent jc = (JComponent) comp;//for Custom JComponent if (!isRowSelected(row)) { int modelRow = convertRowIndexToModel(row); boolean type = (Boolean) getModel().getValueAt(modelRow, 2); boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3); boolean type2 = (Boolean) getModel().isCellEditable(row, column); comp.setForeground(Color.black); if ((type) && (!type1)) { comp.setBackground(Color.yellow); } else if ((!type) && (type1)) { comp.setBackground(Color.orange); } else if ((!type) || (!type1)) { comp.setBackground(Color.red); //} else if ((!type2)) { //comp.setForeground(Color.red); //comp.setBackground(Color.magenta); } else { comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker()); } dialogTable.convertRowIndexToView(0); } else { comp.setForeground(Color.blue); comp.setBackground(Color.lightGray); } if (!isCellEditable(row, column)) { comp.setForeground(Color.red); comp.setBackground(Color.magenta); } return comp; } }; tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); tableScroll.setBorder(null); dialogTable.getTableHeader().setReorderingAllowed(false); dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); lsDialog = dialogTable.getSelectionModel(); dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); dialogTable.setRowHeight(20); dialogTable.setRowMargin(2); ListSelectionModel rowSelMod = dialogTable.getSelectionModel(); //ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel(); rowSelMod.addListSelectionListener(this); //colSelMod.addListSelectionListener(this); fatherCenter = new JPanel(); fatherCenter.setLayout(new BorderLayout(10, 10)); fatherCenter.add(tableScroll, BorderLayout.CENTER); pane.add(fatherCenter); } private void addData() { Runnable doRun1 = new Runnable() { @Override public void run() { tableModel.resetTable(); Vector tbl = new Vector(); Vector tbl1 = new Vector(); Random rnd = new Random(); tbl.add("Integer"); tbl.add("Double"); tbl.add("Boolean"); tbl.add("Boolean"); tbl.add("String"); tableModel.setColumnNames(tbl); for (int row = 0; row < 30; row++) { tbl1 = null; tbl1 = new Vector(); tbl1.addElement(row + 1); tbl1.addElement(rnd.nextInt(25) + 3.14); tbl1.addElement((row % 3 == 0) ? false : true); tbl1.addElement((row % 5 == 0) ? false : true); if (row % 7 == 0) { tbl1.add(("Canc")); } else if (row % 6 == 0) { tbl1.add(("Del")); } else { tbl1.add(("New")); } tableModel.addRow(tbl1); } addTableListener(); } }; SwingUtilities.invokeLater(doRun1); } private void addTableListener() { tableModel.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent tme) { if (tme.getType() == TableModelEvent.UPDATE) { System.out.println(""); System.out.println("Cell " + tme.getFirstRow() + ", " + tme.getColumn() + " changed. The new value: " + tableModel.getValueAt(tme.getFirstRow(), tme.getColumn())); } } }); } public void valueChanged(ListSelectionEvent le) { int row = dialogTable.getSelectedRow(); int col = dialogTable.getSelectedColumn(); String str = "Selected Row(s): "; int[] rows = dialogTable.getSelectedRows(); for (int i = 0; i < rows.length; i++) { str += rows[i] + " "; } str += "Selected Column(s): "; int[] cols = dialogTable.getSelectedColumns(); for (int i = 0; i < cols.length; i++) { str += cols[i] + " "; } str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn(); System.out.println(str); Object value = dialogTable.getValueAt(row, col); System.out.println(String.valueOf(value)); } private void createAndShowGUI() { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout(10, 10)); addComponentsToPane(frame.getContentPane()); addData(); frame.setLocation(150, 150); frame.setPreferredSize(new Dimension(400, 647)); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { Forum osFrame = new Forum(); } public Forum() { javax.swing.SwingUtilities.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } private class myTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; private Vector> data; private Vector colNames; private boolean[] _columnsVisible = {true, true, true, true, true}; myTableModel() { this.colNames = new Vector(); this.data = new Vector>(); } myTableModel(Vector colnames) { this.colNames = colnames; this.data = new Vector>(); } public void resetTable() { this.colNames.removeAllElements(); this.data.removeAllElements(); } public void setColumnNames(Vector colNames) { this.colNames = colNames; this.fireTableStructureChanged(); } public void addRow(Vector data) { this.data.add(data); this.fireTableDataChanged(); this.fireTableStructureChanged(); } public void removeRowAt(int row) { this.data.removeElementAt(row); this.fireTableDataChanged(); } @Override public int getColumnCount() { return this.colNames.size(); } @Override public Class getColumnClass(int colNum) { switch (colNum) { case 0: return Integer.class; case 1: return Double.class; case 2: return Boolean.class; case 3: return Boolean.class; default: return String.class; } } @Override public boolean isCellEditable(int row, int colNum) { switch (colNum) { case 2: return false; default: return true; } } @Override public String getColumnName(int colNum) { return this.colNames.get(colNum); } @Override public int getRowCount() { return this.data.size(); } @Override public Object getValueAt(int row, int col) { Vector value = this.data.get(row); return value.get(col); } @Override public void setValueAt(Object newVal, int row, int col) { Vector aRow = data.elementAt(row); aRow.remove(col); aRow.insertElementAt(newVal, col); fireTableCellUpdated(row, col); } public void setColumnVisible(int index, boolean visible) { this._columnsVisible[index] = visible; this.fireTableStructureChanged(); } } } 

mKorbel正在做点什么。 如果您创建自己的扩展DefaultCellEditor的单元格编辑器,该怎么办:

  customerTable.setDefaultEditor(String.class, new DefaultCellEditor(new JTextField()){ @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { // code on line below is redundant but would be needed if need to see // other property of the value object than toString() String valueStr = (value == null) ? "null" : value.toString(); System.out.printf("[%d, %d]: %s%n", row, column, valueStr); return super.getTableCellEditorComponent(table, value, isSelected, row, column); } @Override public Object getCellEditorValue() { System.out.printf("cell editor value: %s%n", super.getCellEditorValue()); return super.getCellEditorValue(); } });