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?
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