4 votes

L'utilisation d'un modèle de tableau personnalisé permet de rendre isCellEditable true pour une ligne particulière lors d'un clic sur un bouton.

MY Table

J'ai un tableau comme ci-dessus. Initialement, toutes les cellules, à l'exception de la colonne des boutons, ne sont pas modifiables. J'ai créé le tableau à l'aide de TableModel . Mon isCellEditable dans le domaine du sur-mesure TableModel ressemble à ceci :

public boolean isCellEditable(int rowIndex, int columnIndex) { 
    //System.out.println("isCellEditable: " + rowIndex + " " + columnIndex);
    if(getColumnClass(columnIndex) == JButton.class)
        return true;
    else
        return false;
}

Mais lorsque je clique sur le bouton Modifier de chaque ligne, un JDialog apparaîtra avec cette ligne (en construisant un JTable dans ce dialogue qui ne comporte qu'une seule ligne). Je peux mettre à jour les valeurs des cellules du tableau de ce JDialog, puis les mettre à jour dans les cellules respectives de cette ligne.

JDialog's Table

J'ai réussi à mettre à jour la ligne de la table principale après la mise à jour ici, seulement si mon isCellEditable retourner vrai . Mais cela ne devrait pas se produire. Ce n'est que lorsque je clique sur que je peux modifier les paramètres de l'application. isCellEditable de la ligne en tant que modifiable et mise à jour, puis la rendre non modifiable.

J'ai constaté ce qui suit poste mais n'a pas été en mesure de la mettre en œuvre.

6voto

mKorbel Points 90340

XxxTableModel magasins String.class para JButton como Renderer / Editor para JTable

et pour votre code (basé sur) également

EDITAR

Modèle de table par défaut

import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableButton3 extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTable table;

    public TableButton3() {
        String[] columnNames = {"Date", "String", "Decimal", "Remove"};
        Object[][] data = {
            {new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},
            {new Date(), "C", new Double(7.3), "Remove"}, {new Date(), "D", new Double(8.4), "Remove"},
            {new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},};
        DefaultTableModel model = new DefaultTableModel(data, columnNames){

            private static final long serialVersionUID = 1L;

            @Override//  Returning the Class of each column will allow different renderers to be used based on Class
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return Date.class;
                    case 2:
                        return Double.class;
                    default:
                        return String.class;
                }
                //return getValueAt(0, column).getClass();
            }
        };
        table = new JTable(model) ;
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        getContentPane().add(scrollPane);
        ButtonColumn buttonColumn = new ButtonColumn(table, delete, 3);
        buttonColumn.setMnemonic(KeyEvent.VK_D);
    }

    public static void main(String[] args) {
        TableButton3 frame = new TableButton3();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
    //
    private Action delete = new AbstractAction() {

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            JTable table = (JTable) e.getSource();
            int modelRow = Integer.valueOf(e.getActionCommand());
            ((DefaultTableModel) table.getModel()).removeRow(modelRow);
            table.clearSelection();
        }
    };
}

Modèle de table abstrait

import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableButton3 extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTable table;
    private MyTableModel myModel = new MyTableModel();

    public TableButton3() {
        String[] columnNames = {"Date", "String", "Decimal", "Remove"};
        Object[][] data = {
            {new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},
            {new Date(), "C", new Double(7.3), "Remove"}, {new Date(), "D", new Double(8.4), "Remove"},
            {new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},};
        DefaultTableModel model = new DefaultTableModel(data, columnNames){

            private static final long serialVersionUID = 1L;

            @Override//  Returning the Class of each column will allow different renderers to be used based on Class
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return Date.class;
                    case 2:
                        return Double.class;
                    default:
                        return String.class;
                }
                //return getValueAt(0, column).getClass();
            }
        };
        table = new JTable(model);
        table = new JTable(myModel);
        addTableDatas();
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
        ButtonColumn buttonColumn = new ButtonColumn(table, delete, 3);
        buttonColumn.setMnemonic(KeyEvent.VK_D);
    }

    public static void main(String[] args) {
        TableButton3 frame = new TableButton3();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private void addTableDatas() {
        Vector<String> columnNameS = new Vector<String>();
        columnNameS.add("Date");
        columnNameS.add("String");
        columnNameS.add("Decimal");
        columnNameS.add("Remove");
        myModel.setColumnNames(columnNameS);

        Vector<Object> row1 = new Vector<Object>();
        row1.add(new Date());
        row1.add("A");
        row1.add(new Double(5.1));
        row1.add("Remove");
        myModel.addRow(row1);

        row1 = new Vector<Object>();
        row1.add(new Date());
        row1.add("B");
        row1.add(new Double(6.2));
        row1.add("Remove");
        myModel.addRow(row1);

        row1 = new Vector<Object>();
        row1.add(new Date());
        row1.add("B");
        row1.add(new Double(8.4));
        row1.add("Remove");
        myModel.addRow(row1);

        row1 = new Vector<Object>();
        row1.add(new Date());
        row1.add("B");
        row1.add(new Double(5.1));
        row1.add("Remove");
        myModel.addRow(row1);

        row1 = new Vector<Object>();
        row1.add(new Date());
        row1.add("B");
        row1.add(new Double(6.2));
        row1.add("Remove");
        myModel.addRow(row1);
    }

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

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

        public 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.fireTableRowsInserted(data.size() - 1, data.size() - 1);
        }

        public void removeRowAt(int row) {
            this.data.removeElementAt(row);
            this.fireTableRowsDeleted(row - 1, data.size() - 1);
        }

        @Override
        public int getColumnCount() {
            return this.colNames.size();
        }

        @Override
        public Class<?> getColumnClass(int colNum) {
            switch (colNum) {
                case 0:
                    return Date.class;
                case 2:
                    return Double.class;
                default:
                    return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int row, int colNum) {
            switch (colNum) {
                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();
        }
    }
    //
    private Action delete = new AbstractAction() {

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            JTable table = (JTable) e.getSource();
            int modelRow = Integer.valueOf(e.getActionCommand());
            ((DefaultTableModel) table.getModel()).removeRow(modelRow);
            table.clearSelection();
        }
    };
}

les deux renvoient la même interface graphique, avec les mêmes ...

enter image description here

1voto

kleopatra Points 31585

J'étoffe mon commentaire à la question :

il n'est pas nécessaire de modifier la modifiabilité du modèle complet : créez un autre modèle alimenté par la ligne filtrée (dans le sens des colonnes) de l'original, rendez cet autre modèle modifiable et, lors de la validation, laissez-le écrire les valeurs modifiées dans l'original.

avec un peu de code :

public static class ButtonDialogEditor extends AbstractCellEditor 
     implements TableCellEditor {
    // the columns to present for editing, in model coordinates
    public final int lastColumn;
    public final int firstColumn;
    // the row to present for editing, in model coordinates
    private int row;

    private DefaultTableModel model;
    private JDialog dialog;
    private boolean committed;
    private JButton editingComponent;

    public ButtonDialogEditor(int firstColumn, int lastColumn) {
       this.firstColumn = firstColumn;
       this.lastColumn = lastColumn;

       model = new DefaultTableModel(1, lastColumn - firstColumn + 1);
       JTable table = new JTable(model);
       table.putClientProperty("terminateEditOnFocusLost",true);
       dialog = new JDialog();
       dialog.setModal(true);
       dialog.add(new JScrollPane(table));
       dialog.add(new JButton(createOkAction()), BorderLayout.SOUTH);
       dialog.pack();
       editingComponent = new JButton(createShowDialogAction());
    }

    /**
     * Returns the cell value at column. Note that column
     * is in the model coordinate system of the source model.
     */
    public Object getValueAt(int column) {
        return model.getValueAt(0, column - firstColumn);
    }

    /**
     * Returns the row index of the edited row in 
     * model coordinates of the source table.
     */
    public int getModelRow() {
        return row;
    }

    /**
     * Creates and returns the action used for 
     * the editing component button.
     * 
     * Implemented to show the modal dialog and fire 
     * editingSotpped/canceled depending on the committed
     * flag
     */
    private Action createShowDialogAction() {
        Action action = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // reset committed
                committed = false;
                dialog.setVisible(true);
                if (committed) {
                    fireEditingStopped();
                } else {
                    fireEditingCanceled();
                }
            }
        };
        return action;
    }

    /**
     * Creates and returns the action used for the dialog's
     * OK button.
     * 
     * Implemented to hide the dialog and set the
     * committed flag to true.
     */
    private Action createOkAction() {
        Action action = new AbstractAction("OK") {
            @Override
            public void actionPerformed(ActionEvent e) {
                dialog.setVisible(false);
                committed = true;
            }
        };
        return action;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        editingComponent.setText(value != null ? value.toString() : "");
        prepareDialog(table, row);
        return editingComponent;
    }

    /**
     * Update internal state to the row to edit. 
     */
    private void prepareDialog(JTable table, int row) {
        this.row = table.convertRowIndexToModel(row);
        for (int i = firstColumn; i <= lastColumn; i++) {
            model.setValueAt(table.getModel().getValueAt(this.row, i), 0, i - firstColumn);
        }
    }

    /**
     * Implemented to return the original value as 
     * given in the 
     */
    @Override
    public Object getCellEditorValue() {
        return editingComponent.getText();
    }

}

public static class ButtonRenderer implements TableCellRenderer {

    JButton button = new JButton();
    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column) {
        button.setText(value != null ? value.toString() : "");
        return button;
    }
}

// example usage
// source model is not editable except for the button column
final DefaultTableModel model = new DefaultTableModel(0, 3) {
    @Override
    public boolean isCellEditable(int row, int column) {
        return column == 0;
    }
};
for (int i = 0; i < 20; i++) {
    model.addRow(new Object[] {"Edit", i});
}
JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(new ButtonRenderer());
final ButtonDialogEditor cellEditor = new ButtonDialogEditor(1, model.getColumnCount() - 1);
// custom editor listener which writes back the edited values
// to the model on editingStopped.
CellEditorListener l = new CellEditorListener() {

    @Override
    public void editingStopped(ChangeEvent e) {
        for (int i = cellEditor.firstColumn; i <= cellEditor.lastColumn; i++) {
            model.setValueAt(cellEditor.getValueAt(i), cellEditor.getModelRow(), i);
        }
    }

    @Override
    public void editingCanceled(ChangeEvent e) {
        // nothing to do
    }
};
cellEditor.addCellEditorListener(l);
table.getColumnModel().getColumn(0).setCellEditor(
        cellEditor);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X