Question

I have added the following JTable.

public final class EmployeeApp extends JPanel implements ActionListener, TableModelListener
{
    private static JTable myTable;
    private static JButton btnDelete;

    public EmployeeApp()
    {
        CountryDAO countryDAO=new CountryDAO();
        myTable = new JTable(new CountryAbstractTableModel(countryDAO.getList()));
        JScrollPane myPane = new JScrollPane(myTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        add(myPane);
        myTable.setPreferredScrollableViewportSize(new Dimension(1000, 200));

        ((CountryAbstractTableModel)myTable.getModel()).addTableModelListener(this);//<---
        //Added TableModelListener.                 
    }

    @Override
    public void tableChanged(TableModelEvent e)
    {
        int row = e.getFirstRow();
        int column = e.getColumn();
        CountryAbstractTableModel model = (CountryAbstractTableModel)e.getSource();
        Object data = model.getValueAt(row, column);

        System.out.println("The tableChanged() method called."); // This is never be seen on the console.            
    }
}

When a cell is edited, the tableChanged() method should be invoked but it never gets called.


I have extended AbstractTableModel as follows.

package admin.model;

import entity.Country;
import java.util.Iterator;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public final class CountryAbstractTableModel extends AbstractTableModel
{
    private List<Country> countries;

    public CountryAbstractTableModel(List<Country> countries)
    {
        this.countries = countries;
    }

    @Override
    public void setValueAt(Object value, int rowIndex, int columnIndex)
    {
        if(value instanceof Country)
        {
            Country newCountry=(Country) value;
            Country oldCountry = countries.get(rowIndex);
            switch (columnIndex)
            {
                case 2:
                    oldCountry.setCountryName(newCountry.getCountryName());
                    break;
                case 3:
                    oldCountry.setCountryCode(newCountry.getCountryCode());
                    //break;
            }
            fireTableCellUpdated(rowIndex, columnIndex);
        }
    }


    @Override
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        Country country = countries.get(rowIndex);
        switch (columnIndex)
        {
            case 0:
                return rowIndex+1;
            case 1:
                return country.getCountryId();
            case 2:
                return country.getCountryName();
            case 3:
                return country.getCountryCode();
        }
        return "";
    }       

    @Override
    public int getRowCount()
    {
        return countries.size();
    }

    @Override
    public int getColumnCount()
    {
        return 4;
    }

    public void add(Country country)
    {
        int size = countries.size();
        countries.add(country);
        fireTableRowsInserted(size, size);
    }

    public void remove(List<Long>list)
    {
        Iterator<Country> iterator = countries.iterator();
        while(iterator.hasNext())
        {
            Country country = iterator.next();
            Iterator<Long> it = list.iterator();

            while(it.hasNext())
            {
                if(country.getCountryId().equals(it.next()))
                {
                    iterator.remove();
                    int index = countries.indexOf(country);
                    fireTableRowsDeleted(index, index);
                    break;
                }
            }
        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex)
    {
        return columnIndex>1?true:false;
    }    
}

In which the setValueAt() method is called when the return key is pressed after editing a cell. Therefore, the tableChanged() method should be called after fireTableCellUpdated() gets called.

Since the first two columns are not editable, there is no need to set the values for them.

Why isn't the tableChanged() method invoked?

Was it helpful?

Solution

Unless you have specifically set a dedicated Country editor for that column, your test value instanceof Country is likely to be false. Most likely value is actually a String. Your setValueAt method should rather look like this:

@Override
public void setValueAt(Object value, int rowIndex, int columnIndex)
{
    if(value instanceof String)
    {
        Country country = countries.get(rowIndex);
        String newValue = (String) value;
        switch (columnIndex)
        {
            case 2:
                country.setCountryName(newValue); break;
            case 3:
                country.setCountryCode(newValue); break;
        }
        fireTableCellUpdated(rowIndex, columnIndex);
    }
}

Of course, if the type of countryName and countryCode is not String, you should return appropriate values for the method TableModel.getColumnClass and test for appropriate types in setValueAt

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top