JTable com coluna em String usando ordenação de BigDecimal

Tenha uma classe que extende de AbstractTableModel

package br.com.systech.classes.tablemodel;

import static br.com.systech.classes.utilitario.Biblioteca.*;
import br.com.systech.classes.beans.Produto;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class ProdutoTableModel extends AbstractTableModel {

    private List<Produto> pList = new ArrayList<>();
    private final String[] colunas = {"", "ID", "Descricao", "Preço", "Saldo"};
    Class[] types = new Class[]{Boolean.class, Integer.class, String.class, BigDecimal.class, BigDecimal.class};

    @Override
    public Class<?> getColumnClass(int i) {
        return types[i];
    }

    @Override
    public boolean isCellEditable(int linha, int coluna) {
        return coluna == 0;
    }

    @Override
    public String getColumnName(int i) {
        return colunas[i];
    }

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

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        switch (coluna) {
            case 0:
                return pList.get(linha).isStatus();
            case 1:
                return pList.get(linha).getCodigo();
            case 2:
                return pList.get(linha).getDescricao();
            case 3:
                return bigDecimalToString((BigDecimal) pList.get(linha).getPreco_venda());
            case 4:
                return isFracaoIgualZero(pList.get(linha).getSaldo()) ? pList.get(linha).getSaldo().setScale(0, RoundingMode.HALF_UP).toString() : bigDecimalToString(pList.get(linha).getSaldo());
        }
        return null;
    }

    @Override
    public void setValueAt(Object c, int linha, int coluna) {
        switch (coluna) {
            case 0:
                pList.get(linha).setStatus((boolean) c);
                break;
        }
    }

    public void addRow(Produto iv) {
        this.pList.add(iv);
        this.fireTableDataChanged();
    }

    public void addList(List<Produto> ivList) {
        this.pList = ivList;
        this.fireTableDataChanged();
    }

    public List<Produto> getList() {
        return this.pList;
    }
}

Tenha uma JTable que usa essa classe e exibe os produtos na tela. Mas a ordenação da coluna 3 e 4 não funcionam pois o valor deles é BigDecimal porem para exibir eu uso um metodo bigDecimalToString() que formata em “real” em vez de aparecer 1.00 aparece 1,00.

O correto para ordenação seria

1,00
2,60
10,40

Alguém sabe alguma solução? Já procurei em vários lugares mas não achei algo parecido.

Fiz o seguinte teste:

BigDecimal a = new BigDecimal("1.00");
BigDecimal b = new BigDecimal("10.40");
BigDecimal c = new BigDecimal("2.60");

Stream.of(a, b, c).sorted().forEach(System.out::println);
// 1.00
// 2.60
// 10.40

Foi usado o sort default (pelo compareTo) e a ordenação ficou de acordo.

Para apresentar ordenado na tabela, vc deve realizar o sort da lista utilizada nesse table model.

1 curtida

Muito obrigado! Vou tentar :smiley:

Nesse caso vou precisar pegar o evento de click na coluna? Como seria pra disparar esse evento?

Ao criar o ProdutoTableModel, já passe a lista ordenada num construtor dessa classe.

1 curtida

Mas o intuito é ordenar pela coluna, o usuario clica em ID ai ordena pelo ID, ele clica em Descricao ordena em ordem alfabética, clica em Preço…

Entendi. Veja esse exemplo: http://www.java2s.com/Tutorial/Java/0240__Swing/SampleSortingTableModel.htm

1 curtida

Eu fiz o teste com essa classe mas na hora que eu adicionei tableSorted.setRowSorter(new TableRowSorter<>(model)); essa linha no codigo pra dar ação ao clique na coluna, ele não ordena corretamente.

Pior é que não da pra reescrever esse método “setRowSorter”! Mas vou estudar melhor o codigo e ver se consigo adaptá-lo. Valeu :v:

Não converta para String, use o valor em BigDecimal mesmo no modelo da tabela. Já que você quer ordenar pelo click na coluna mesmo, utilize o método setAutoCreateRowSorter() da JTable, que ela já se encarrega de arrumar esse Sorter pra você. A classe utilizada pra fazer o Sorting da maneira correta vai ser a que você definir no método getColumnClass do seu modelo.

Então na sua JTable habilite o RowSorter automático:
table.setAutoCreateRowSorter(true);

E no seu modelo, sobrescreva o método getColumnClass, pra fazer a ordenação de acordo com a classe utilizada em cada coluna:

@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Boolean.class;
case 1:
return Integer.class;
case 2:
return String.class;
case 3:
return BigDecimal.class;
case 4:
return BigDecimal.class;
default:
throw new IndexOutOfBoundsException(“Index out of Bounds”);
}
}

A classe era assim, não havia conversão mas o cliente só queria se fosse com “,” em vez de “.”. Vai entender :man_facepalming:

Então, essas mudanças como formatação devem ser feitas na camada da View, não no Modelo. O ideal é colocar um Renderer na coluna da JTable para formatar da forma que você deseja ser renderizado na tela. Com ou sem virgula, ponto, casas decimais, cor…

1 curtida