JTable的TableModelListener在编辑单元格时不会触发事件

时间:2013-09-13 21:22:30

标签: swing jtable tablemodel

我添加了以下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.            
    }
}

编辑单元格时,应调用tableChanged()方法,但永远不会调用它。


我已将AbstractTableModel扩展如下。

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

在编辑单元格后按下返回键时调用setValueAt()方法。因此,应在调用fireTableCellUpdated()之后调用tableChanged()方法。

由于前两列不可编辑,因此无需为它们设置值。

为什么不调用tableChanged()方法?

1 个答案:

答案 0 :(得分:1)

除非您专门为该列设置了专用的Country编辑器,否则您的测试value instanceof Country可能是错误的。最有可能value实际上是String。您的setValueAt方法应该如下所示:

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

当然,如果countryName和countryCode的类型不是String,则应该为方法TableModel.getColumnClass返回适当的值,并在setValueAt

中测试相应的类型