3

I have created a custom TableModel using AbstractTableModel. I am able to populate my JTable. But my JTable has a button column say "Button1". So I am using CellRenderer method to add buttons to column and CellEditor to add actions, but I am getting exception at LINE:3.

CustomModelForTable customTableModel = new CustomModelForTable(colNames, data);
tableA = new JTable(customTableModel);

**LINE:3** 
tableA.getColumn("Button1").setCellRenderer(new JButtonRendererClass());
tableA.getColumn("Button1").setCellEditor(new ButtonEditor(new JCheckBox()));

I am getting the following error.

java.lang.IllegalArgumentException: Identifier not found
at javax.swing.table.DefaultTableColumnModel.getColumnIndex(DefaultTableColumnModel.java:265)

I am getting this error because I am not able to get the Column from my custom Table. But can some one help me out with this issue.

I am using the following source to perform this task. In this source they are using DefaultTableModel where as in my case I am using AbstractTableModel.

Amarnath
  • 8,736
  • 10
  • 54
  • 81

2 Answers2

3

In order to retrieve columns by identifier, you have to set one using TableColumn.setIdentifier().

EDIT:

Note that according to specs of TableColumn.getIdentifier():

If the identifier is null, getIdentifier() returns getHeaderValue as a default.

That is how it works in the linked example.

EDIT:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.GridLayout;

public class TableDemo extends JPanel {
    public TableDemo() {
        super(new GridLayout(1,0));

        JTable table = new JTable(new MyTableModel());

        JScrollPane scrollPane = new JScrollPane(table);

        add(scrollPane);

        table.getColumn("Column1").setCellRenderer(new TestCellRenderer());
        table.getColumn("Column2").setCellRenderer(new TestCellRenderer());
    }

    class TestCellRenderer extends DefaultTableCellRenderer{ }

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = { "Column1", "Column2" };
        private Object[][] data = { { "1", "1" }, { "2", "2" } };

        public int getColumnCount() {
            return columnNames.length;
        }

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

        public String getColumnName(int col) {
            return columnNames[col];
        }

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

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("TableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        TableDemo newContentPane = new TableDemo();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
tenorsax
  • 21,123
  • 9
  • 60
  • 107
  • @Che What is the header value for that column? See my last edit. – tenorsax Sep 12 '12 at 05:47
  • Column header value is Button1 which is of type JButton class – Amarnath Sep 12 '12 at 05:48
  • @Che Make sure you implement getColumnName() in your model. See my last edit for a simple example of a model. – tenorsax Sep 12 '12 at 06:00
  • Awesome. Works like a champ. Thank you. But just one explanation regarding this. How getColumnName(int col) method helped to achieve this? – Amarnath Sep 12 '12 at 06:25
  • @Che When new column is created in `JTable`, column's name is used to set column's header name (unless this column already has a header value). Then during lookup by identifier, the column's header name is used in case its identifier is null (part of `getIdentifier()` method). – tenorsax Sep 12 '12 at 06:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16578/discussion-between-che-and-max) – Amarnath Sep 12 '12 at 06:41
  • @Che ditto, it turned to be an challenging question. – tenorsax Sep 13 '12 at 01:50
3

1.use Table Button Column by @camickr

2.JButton in JTable represents String value stored in XxxTableModel, then have to override the ColumnClass

     public Class getColumnClass(int column) {
        switch (column) {
            case 0:
                return Date.class;
            case 1:
                return Integer.class;
            case 2:
                return Long.class;
            case 3:
                return Double.class;
            case 4:
                return Boolean.class;
            case 5:
                return Icon.class;
            default:
                return String.class;
        }
    }

Cells in the Column should be editable

    public boolean isCellEditable(int row, int col) {
        switch (col) {
            case 0:
                return false;
            case 1:
                return false;
            default:
                return true;
        }
    }

3.everything is about your AbstractTableModel, maybe there no reason use that, use DefaultTableModel before, in the case that you understand How XxxTableModel works, then you can to override methods for JTable with AbstractTableModel

mKorbel
  • 109,525
  • 20
  • 134
  • 319