AbstractTabelModel e DefaultTableRenderer não funcionam com TableRowSorter. Help me

Bom dia.

Estou aprendendo melhor uso de JTable e bati em um problema que provavelmente eh bem simples e não estou encontrando a solucao. Acho que estou deixando passar um detalhe bobo e nao consigo enxergar o que exatamente. Estou a 4 dias procurando algo, alterando codigo e caio novamente no mesmo problema.

Agradeço qualquer ajuda.

Possuo um AbstractTabelModel e um DefaultTableRenderer que postarei abaixo. E estou tentando aplicar TableRowSorter para classificar dinamicamente a informação que aparece na JTable.

Porém, se eu não uso o renderer. O Sorter funciona. Mas se eu aplicar o renderer, o sorter para de funcionar. hehe

Nem todo codigo esta as mil maravilhas ja que eh um projeto para aprendizado mesmo. :wink:

Vou postar o codigo das partes que acho pertinentes para nao sobrecaregar o tamanho do post.

Classe basica modelo de dados Pais:


package model;

/**
 * Classe modelo de País.
 * @author Alex
 */
public class Pais implements Comparable <String>{
    
    private int pais;
    private String descricao;
    private String abreviado;
    private String icone;

    
    /**
     * Construtor para estado inicial.
     */
    public Pais() {
        this.pais = 0;
        this.descricao = "";
        this.abreviado = "";
        this.icone = "";
    }

    /**
     * Define o codigo internacional do pais
     * @param pais 
     */
    public void setPais(int pais) {
        this.pais = pais;
    }

    /**
     * Define a descricao do pais (nome)
     * @param descricao 
     */
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    /**
     * Define abreviacao do pais
     * @param abreviado 
     */
    public void setAbreviado(String abreviado) {
        this.abreviado = abreviado;
    }

    /**
     * Define caminho do icone
     * @param icone 
     */
    public void setIcone(String icone) {
        this.icone = icone;
    }

    /**
     * retorna codigo do pais
     * @return 
     */
    public int getPais() {
        return pais;
    }
    /**
     * retorna a descricao
     * @return 
     */
    public String getDescricao() {
        return descricao;
    }
    /**
     * Retorna abreviacao
     * @return 
     */
    public String getAbreviado() {
        return abreviado;
    }

    /**
     * Retorna caminho do icone
     * @return 
     */
    public String getIcone() {
        return icone;
    }

    /**
     * Representacao String
     * @return 
     */
    @Override
    public String toString() {
        return Integer.toString(getPais()) + getDescricao() +getAbreviado() + getIcone();
    }

    /**
     * Ordenacao padrao por nome.
     * @param s
     * @return 
     */
    @Override
    public int compareTo(String s) {
        return this.descricao.compareToIgnoreCase(s);
    }
    
    
    
}

Agora a TableModel:

package model;

import control.PaisDAO;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

/**
 *
 * @author X8
 */
public class PaisTableModel extends AbstractTableModel {

    private List<Pais> elements;
    private String [] columnNames={"Pais","Abrev","Descrição","Icone"};
   
    
    /**
     * Construtor recebe dados iniciais em formato de ArrayList Pais
     * @param elements 
     */
    public PaisTableModel(List <Pais> elements) {
                
        this.elements = elements;
        
    }
        
    /**
     * numero de linhas de sua tabela. Metodo obrigatorio herdado e reescrito.
     * @return 
     */
    @Override
    public int getRowCount() {
        //numero de linhas/elementos.
        return elements.size();
    }

    /**
     * Numero de colunas de nossa tabela. de 0 a 3 = 4 colunas.
     * @return 
     */
    @Override
    public int getColumnCount() {
        return 4; //numero de colunas da tabela
    }

    /**
     * Retorna o valor a ser preenchido na linha e coluna 
     * @param row
     * @param col
     * @return 
     */
    @Override
    public Object getValueAt(int row, int col) {
        //retornar os dados das linhas/celulas
        Pais p=elements.get(row);
        if (col==0)
            return p.getPais();
        if (col==1)
            return p.getAbreviado();
        if (col==2)
            return p.getDescricao();
        if (col==3)
            return p.getIcone();
        return null;
        
    }

    /**
     * Define o nome de cabecalho da coluna
     * @param col
     * @return 
     */
    @Override
    public String getColumnName(int col) {
        
        return columnNames[col];
    }

    /**
     * Apresenta a tabela qual tipo de dados ela deve desenhar
     * @param col
     * @return 
     */
    @Override
    public Class<?> getColumnClass(int col) {
        
        if (col==0)
            return Integer.class;
        if (col==1 || col==2 || col==3)
            return String.class;
        
        return String.class;
    }
    
    /**
     * Retorna o objeto inteiro para facilitar pegar uma linha inteira
     * @param row
     * @return 
     */
    public Pais get(int row){
        return elements.get(row);
    }
    /**
     * Permitir adicionar uma linha unica
     * @param p 
     */
    public void add(Pais p){
        elements.add(p);
        this.fireTableDataChanged();
    }
    
    /**
     * Adicionar colecao de itens ao final da lista.
     * @param itens 
     */
    public void addAll(List<Pais> itens){
        elements.addAll(itens);
        this.fireTableDataChanged();
    }

    
    
    /**
     * Limpa a tabela toda.
     */
    public void clear(){
        elements.clear();
        this.fireTableDataChanged();
    }

} //EOF

TableRenderer:

package model;

import java.awt.Color;
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author X8
 */
public class PaisesTableRenderer extends DefaultTableCellRenderer {

    public PaisesTableRenderer() {
        this.setOpaque(true);
    }

    
    @Override
    public Component getTableCellRendererComponent(JTable jtable, Object item, boolean isSelected, boolean hasFocus, int row, int col) {
        
        //usar get configurado no TableModel para pegar o objeto inteiro.
        PaisTableModel modelo=(PaisTableModel) jtable.getModel();
        Pais p=modelo.get(row);
        //colore linhas espacadas e selecionada
        
        if (isSelected ){
            this.setForeground(Color.WHITE);
            this.setBackground(Color.BLACK);
        } else {
            if (row % 2 == 0){
                this.setForeground(Color.BLACK);
                this.setBackground(Color.YELLOW);
            } else {
                this.setForeground(Color.WHITE);
                this.setBackground(Color.BLUE);
            }
        }
        
        //escreve texto, icone e define tamanho de cada coluna
        if (col==0){
            this.setText(Integer.toString(p.getPais()));
            this.setIcon(null);
            jtable.getColumnModel().getColumn(col).setPreferredWidth(100);
        }
        if (col==1){
            this.setText(p.getDescricao());
            this.setIcon(null);
            jtable.getColumnModel().getColumn(col).setPreferredWidth(400);
        }
        if (col==2){
            this.setText(p.getAbreviado());
            this.setIcon(null);
            jtable.getColumnModel().getColumn(col).setPreferredWidth(100);
        }
        if (col==3){
            this.setIcon(new ImageIcon(p.getIcone()));
            this.setText("");
            jtable.getColumnModel().getColumn(col).setPreferredWidth(100);
            //this.setText(p.getIcone());
        }
        
        return this;
    }

    @Override
    public void updateUI() {
        super.updateUI(); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void repaint() {
        super.repaint(); //To change body of generated methods, choose Tools | Templates.
    }
    
}

Codigo no JFrame onde adiciono o model, renderer e RowSorter.

 try {
            
            conexao=new Connect(); //Conexao ao BD
            
            dbPaises=new PaisDAO(); 
            dbPaises.startConnection(conexao.getConnection()); 
            dbPaises.startDataSet(); //Result set etc sao iniciados aqui
            dbPaises.first(); //move dataset para o primeiro registro apenas por desencargo de consciencia 
            preencheCampos(dbPaises.getCurrent()); //preenche campos do formulario (JtextField etc)
            tbPaises.setModel(new PaisTableModel(dbPaises.asArrayList()));  //define o TableModel
            tbPaises.setDefaultRenderer(Object.class, new PaisesTableRenderer()); //Define o Renderer
            
            // Aqui adiciono o TableRowSorter        
            TableRowSorter<TableModel> sorter = new TableRowSorter<>(tbPaises.getModel());  
            sorter.setRowFilter(null);
            tbPaises.setRowSorter(sorter);
        
        
        
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this,"<html>Erro na conexao ao banco de dados:<br>"+e.getMessage()+"</html>");
        }

Ainda estou pesquisando mais. Mas na net nao vi nenhum caso semelhante ao meu.Qualquer ajuda eh bem vinda.

Agradeço desde já.