RowFilter.regexFilter does not filter columns of type Date in JTable

5

I have JTable with a TableModel custom, and I'm trying to run a search field using JTextField . However, columns of type Date and my class Cadastrante are not searched.

In my TableModel , I overwritten the getColumnClass() method like this:

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case OFICIO:
                return Integer.class;
            case PROTOCOLO:
                return Long.class;
            case ASSUNTO:
                return String.class;
            case DATA:
                return Date.class;
            case CADASTRANTE:
                //Cadastrante é minha custom class
                return Cadastrante.class;
            default:
                return super.getColumnClass(columnIndex);
        }
    }

And the getValueAt() method looks like this:

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    Oficio oficio = this.oficios.get(rowIndex);
    switch (columnIndex) {
        case OFICIO:
            return oficio.getCodigo();
        case PROTOCOLO:
            if (oficio.getProtocolo() == 0) {
                return null;
            }
            return oficio.getProtocolo();
        case ASSUNTO:
            return oficio.getAssunto();
        case DATA:
            // retorna um objeto do tipo util.Date  
            return oficio.getData();
        case CADASTRANTE:
            // retorna um objeto do tipo Cadastrante
            return oficio.getCadastrante();
        case SETOR:
            return oficio.getSetor().getNome();
    }
    return null;
}

On my home screen, where is JTable , I start a variable of type TableRowSorter , passing TableModel as argument, and seto this variable as RowSorter of my table:

    this.linhasFiltradas = new TableRowSorter<TableModel>(this.tabela.getModel());
    this.tabela.setRowSorter(linhasFiltradas);

I added a listener to the JTextField so that when ENTER is pressed, filter with the typed in this field:

private void fieldFiltroBarKeyReleased(java.awt.event.KeyEvent evt) {                                           
    if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
        JTextField field = (JTextField) evt.getSource();
        String busca = field.getText().trim();
        linhasFiltradas.setRowFilter(RowFilter.regexFilter("(?i)" + busca));
    }
}

In the columns that declare the type as Date.class and Cadastrante.class , the search seems to ignore, even if I type terms displayed in these columns, for the others, the search normally finds.

In the case of my Cadastrante class, by debugging the corresponding snippet, I found that RowSorter tries to invoke the toString() method, and since it does not find it, it seems to ignore my class because it does not know how to access its content . I want to be able to do this, but I do not know how to do this, but I'm not sure how to do this.

The table renderer follows:

public class OficioTableRenderer extends DefaultTableCellRenderer {

    private final int COLUNA_ASSUNTO = 2;
    private final int COLUNA_DATA = 3;
    private final int COLUNA_CADASTRANTE = 4;

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        switch (column) {
            case COLUNA_ASSUNTO:
                setHorizontalAlignment(SwingConstants.LEFT);
                setFont(new Font("Tahoma", 0, 11));
                break;
            case COLUNA_DATA:
                setText(new SimpleDateFormat("dd/MM/yyyy").format(value));
                setHorizontalAlignment(SwingConstants.CENTER);
                setFont(new Font(null, 0, 14));
                break;
            case COLUNA_CADASTRANTE:
                Cadastrante cad = (Cadastrante) value;
                setText(cad.getNome());
                setHorizontalAlignment(SwingConstants.CENTER);
                setFont(new Font(null, 0, 14));
                break;
            default:
                setHorizontalAlignment(SwingConstants.CENTER);
                setFont(new Font(null, 0, 14));
                break;
        } 
        setForeground(Color.black);
        return this;
    }

    @Override
    protected void setValue(Object value) {
        super.setValue(value); 
    }      
}

How do I make the Date column searchable too?

    
asked by anonymous 08.04.2016 / 15:27

1 answer

3

The solution would be to use a custom class to encapsulate Date :

public class DateHelper implements Comparable<DateHelper> {
    private final Date date;

    private DateHelper(Date date) {
        this.date = date;
    }

    public static DateHelper of(Date date) {
        return date == null ? null : new DateHelper(date);
    }

    @Override
    public int compareTo(DateHelper other) {
        return date.compareTo(other.date);
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof DateHelper)) return false;
        return date.equals(((DateHelper) other).date);
    }

    @Override
    public int hashCode() {
        return date.hashCode();
    }

    @Override
    public String toString() {
        return new SimpleDateFormat("dd/MM/yyyy").format(date);
    }

    public Date getDate() {
        return date;
    }
}

This will lead to some changes in your TableModel :

@Override
public Class<?> getColumnClass(int columnIndex) {
    switch (columnIndex) {
        case OFICIO:
            return Integer.class;
        case PROTOCOLO:
            return Long.class;
        case ASSUNTO:
            return String.class;
        case DATA:
            return DateHelper.class;
        case CADASTRANTE:
            //Cadastrante é minha custom class
            return Cadastrante.class;
        default:
            return super.getColumnClass(columnIndex);
    }
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    Oficio oficio = this.oficios.get(rowIndex);
    switch (columnIndex) {
        case OFICIO:
            return oficio.getCodigo();
        case PROTOCOLO:
            if (oficio.getProtocolo() == 0) {
                return null;
            }
            return oficio.getProtocolo();
        case ASSUNTO:
            return oficio.getAssunto();
        case DATA:
            // retorna um objeto do tipo DateHelper 
            return DateHelper.of(oficio.getData());
        case CADASTRANTE:
            // retorna um objeto do tipo Cadastrante
            return oficio.getCadastrante();
        case SETOR:
            return oficio.getSetor().getNome();
    }
    return null;
}

And finally, in your renderer:

        case COLUNA_DATA:
            setHorizontalAlignment(SwingConstants.CENTER);
            setFont(new Font(null, 0, 14));
            break;
    
08.04.2016 / 16:20