web-dev-qa-db-fra.com

JTable: Détecter les changements de données de cellule

Dans Netbeans, j'ai utilisé le GUI Builder pour insérer un JTable dans mon application.

Je n'ai pour l'instant qu'une seule classe (CustomerDB) qui est:

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

}

Chaque fois qu'un utilisateur modifie des données dans le tableau, je veux obtenir l'ancienne valeur (facultative) et la nouvelle valeur de cette cellule.

Afin d'obtenir ces données, j'ai essayé d'implémenter un écouteur d'événements:

    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.");
        }
    };

Ensuite j'attribue ce CellEditorListener au tableau (son éditeur de cellule):

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

Cela fonctionne jusqu'à présent. Mais cela ne me permet pas encore de détecter l'ancienne et la nouvelle valeur de cette cellule. Que dois-je faire d'autre?

Merci beaucoup d'avance!

20
caw

Mais cela ne me permet pas encore de détecter l'ancienne et la nouvelle valeur de cette cellule. Que dois-je faire d'autre?

Il est plus facile d'utiliser un TableModelListener pour écouter les modifications mais il a toujours le problème de ne pas pouvoir accéder à l'ancienne valeur.

Consultez List Cell Listener pour une solution qui vous donne accès à "l'ancienne valeur" ainsi qu'à la "nouvelle valeur".

19
camickr

ou TableModelLister avec ListSelectionListener, fist retourne si TableCell a changé, deuxième par rapport à l'appel sélectionné, puis il suffit de comparer l'index de ligne et de colonne de TableModelLister avec ListSelectionListener

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<String> tbl = new Vector<String>();
                Vector<Object> tbl1 = new Vector<Object>();
                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<Object>();
                    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<Vector<Object>> data;
        private Vector<String> colNames;
        private boolean[] _columnsVisible = {true, true, true, true, true};

        myTableModel() {
            this.colNames = new Vector<String>();
            this.data = new Vector<Vector<Object>>();
        }

        myTableModel(Vector<String> colnames) {
            this.colNames = colnames;
            this.data = new Vector<Vector<Object>>();
        }

        public void resetTable() {
            this.colNames.removeAllElements();
            this.data.removeAllElements();
        }

        public void setColumnNames(Vector<String> colNames) {
            this.colNames = colNames;
            this.fireTableStructureChanged();
        }

        public void addRow(Vector<Object> 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<Object> value = this.data.get(row);
            return value.get(col);
        }

        @Override
        public void setValueAt(Object newVal, int row, int col) {
            Vector<Object> 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();
        }
    }
}
12
mKorbel

mKorbel est sur quelque chose. Et si vous créez votre propre éditeur de cellule qui étend 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();
     }
  });
5