Добавление строки в Jtable с помощью AbstractTableModel

Я пытаюсь добавить строку в Jtable, которая расширяет AbstractTableModel, как показано в следующем коде:

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

Здесь я реализую кнопку, которая пытается добавить строку в модель Jtable после нажатия, но она не работает и генерирует исключение:

java.lang.ClassCastException: AbstractTable нельзя преобразовать в 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.");
    }

Как я могу правильно добавить строку в этот код?


person Cohen    schedule 13.08.2016    source источник


Ответы (3)


Как я могу правильно добавить строку в этот код?

Вам нужно переделать модель. В настоящее время вы жестко кодируете данные в массивах фиксированного размера, что ограничивает вашу способность добавлять данные. Вместо:

  • Используйте List<RowType> для ядра вашей модели, а не двухмерный массив объектов. Обратите внимание, что RowType — это созданный вами класс, который содержит все данные, хранящиеся в строке.
  • Используйте этот RowType, чтобы легко получать и устанавливать элементы из каждой ячейки. Это означает изменение ваших методов getValueAt и setValue at для размещения ваших объектов RowType.
  • Дайте вашей модели метод public void addRow(RowType rowData), который позволит вам добавить новый объект в список. Вы не можете использовать метод DefaultTableModel, так как ваша модель не расширяет его, поэтому вам придется написать свой собственный.
  • Внутри этого метода вызовите соответствующий метод fireXxxx(...) суперкласса.

В качестве альтернативы: не расширяйте модель AbstractTableModel, а расширяйте DefaultTableModel и используйте ее методы. Если вы пойдете по этому пути, ваш класс не будет содержать 2D-массив, а скорее будет использовать собственное ядро ​​данных по умолчанию, которое вы можете заполнять и изменять с помощью суперконструкторов и методов по умолчанию. Также было бы неплохо создать перегрузку метода addRow, которая принимает параметр класса RowType.

Например, предполагая, что класс RowData с полями и сеттерами и геттерами соответствует столбцам, вы можете расширить DefaultTableModel, чтобы он выглядел примерно так:

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
}

Затем вы можете использовать либо метод super addRow(Vector data), либо вашу перегрузку выше.

person Hovercraft Full Of Eels    schedule 13.08.2016
comment
Если я реализую вектор вместо двумерного массива, он может работать так же, как и список RowType? - person Cohen; 13.08.2016
comment
@Коэн: я не понимаю, о чем ты спрашиваешь. Лично я бы использовал ArrayList, а не Vector, но какая у вас проблема? - person Hovercraft Full Of Eels; 13.08.2016
comment
В своем ответе вы говорите мне изменить двумерный массив фиксированного размера на List‹rowType›, вместо этого могу ли я реализовать вектор для хранения данных Jtable в новый метод addRow в модели абстрактной таблицы? - person Cohen; 13.08.2016
comment
@Cohen: да, вы можете использовать вектор, опять же, если вы внесете соответствующие изменения, указанные выше. Но опять же, боги Java рекомендуют избегать использования Vector и использовать вместо него ArrayList, но вы можете использовать все, что душе угодно. - person Hovercraft Full Of Eels; 13.08.2016

Вам просто нужно правильно реализовать getValueAt(int, int). Ниже приведен пример:

public class PersonTableModel extends AbstractTableModel {

    String[] columnNames  = new String[] {"Name","Age","Address", "Employeement Status"};


    List<Person> data = new ArrayList<Person>();

    public PersonTableModel() {
       //(Proper way to use a setter method to set the Person)
       data.add(new Person("Sampath", "+94765154345", "34", "male", "Galle", "Contract")); 
    }

    //Abstract method implementation
    public int getRowCount() {
       return data.size();
    }

    //Abstract method implementation
    public int getColumnCount() {
       return columnNames.length;
    }

    //Abstract method implementation
    public Object getValueAt(int row, int colum) {
      Person personObj = data.get(row);

      switch(colum){
        case 0: return personObj.getName();
        case 1: return personObj.getAge();
        case 2: return personObj.getAddress();
        case 3: return personObj.getEmpStatus();
        default : return null;
      }
    }

    @Override
    public String getColumnName(int column) {
        return columnNames[column];
    }

    public void addData(Person person){
        data.add(person);
    }
}
person Lakshan Vithana    schedule 12.07.2017

В AbstractTableModel есть методы для обновления таблицы для вставки. после того, как вы добавили данные в список, вам нужно перекрасить (fireTable) таблицу

list.add(data);
fireTableRowsInserted(list.size() - 1, list.size() - 1);

если вы хотите вставить одну строку, вы должны указать начальную и конечную строки одинаково. существуют другие методы обновления и удаления в AbstractTableModel даже для обновления одной ячейки

Для получения дополнительной информации посетите

person Dinuka Hettiarachchi    schedule 12.07.2017