Cohen Cohen - 3 months ago 31
Java Question

Adding a Row in a Jtable with AbstractTableModel

I'm trying to add a row into the Jtable that extends AbstractTableModel as the following code show.

class AbstractTable extends AbstractTableModel
{
String[] columNames = {"name", "cc", "age", "phone", "date", "amoun"};

Object[][] dataRow = {{"harry", "1234","21","23594","13/3/2","3000"} };

@Override
public int getColumnCount()
{
return columNames.length;
}

@Override
public int getRowCount()
{
return dataRow.length;
}
public String getColumnName(int col)
{
return columNames[col];//cast from object to string.

}

@Override
public Object getValueAt(int row, int col)
{
return dataRow[row][col];
}

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


Here i implement a button wih once pressed try to add a row into the Jtable model , but no works, print a :
java.lang.ClassCastException: AbstractTable cannot be cast to javax.swing.table.DefaultTableModel


public void actionPerformed(ActionEvent e)
{

if(e.getActionCommand().equals("add client"))
{
Object[] dataList = {"", "", "", "", "", ""};


AbstractTableModel defaut = (AbstractTableModel) table.getModel();

((DefaultTableModel) defaut).addRow(dataList);

labelStatus.setText("Cliente Agregado.");
}


How can i add a row in this code properly ?

Answer

How can i add a row in this code properly ?

You need to re-do your model. Currently you're hard-coding the data in fixed-sized arrays which will hamstring your ability to add data. Instead:

  • Use a List<RowType> for the nucleus of your model, not a 2-d array of object. Note that RowType is a class that you create that holds all the data held in a row.
  • Use this RowType to easily get and set items from each cell. This means changing your getValueAt and setValue at methods to accommodate your RowType objects.
  • Give your model an public void addRow(RowType rowData) method that allows you to add a new object to the list. You can't use DefaultTableModel's method since your model doesn't extend this, and so you will have to write you're own.
  • Inside this method, call the appropriate fireXxxx(...) method of the super class.

Alternatively: don't have your model extend AbstractTableModel but rather have it extend DefaultTableModel and use its methods. If you go this route, you'd not have your class hold a 2D array but rather would use the Default's own data nucleus, one that you can fill and modify via the Default's super constructors and methods. You'd also do well to create an addRow method overload, one that accepts a parameter of class RowType

For example assuming a RowData class with fields and setters and getters to match the columns, you could extend DefaultTableModel to look something like this:

public class MyTableModel extends DefaultTableModel {
    public static final String[] COLUMN_NAMES = { "name", "cc", "age", "phone", "date", "amount" };

    public MyTableModel() {
        super(COLUMN_NAMES, 0);
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        if (getRowCount() > 0 && getValueAt(0, columnIndex) != null) {
            return getValueAt(0, columnIndex).getClass();
        }
        return super.getColumnClass(columnIndex);
    }


    public void addRow(RowData rowData) {
        if (rowData == null) {
            throw new IllegalArgumentException("rowData cannot be null");
        }
        Vector<Object> rowVector = new Vector<>();
        rowVector.add(rowData.getName());
        rowVector.add(rowData.getCc());
        rowVector.add(rowData.getAge());
        rowVector.add(rowData.getPhone());
        rowVector.add(rowData.getDate());
        rowVector.add(rowData.getAmount());
        rowVector.add(rowData.getCc());

        super.addRow(rowVector);
    }

    // TODO: methods to return a row as a RowData object
}

Then you could use either the super's addRow(Vector data) method or your overload above.

Comments