[resolvido] Duvida referente AO MEU tableModel

Gente criei um table model… E ele vai gerenciar TOTALMENTE a minha tabela… vou colocar o código e vocês verem e depois eu explico o problema… Obs: ocultei alguns métodos que não vem ao caso…

[...]

public class ProdConsumidosTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;

    private List<Produto> linhas;

    private String[] colunas = new String[]{
        "Código", "Nome", "Preço Unit.", "Quantidade"};
    int quantidade2[] = new int[10000];
    int pos, countPos = 0;

    [...]

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Produto Produto = linhas.get(rowIndex);

        switch (columnIndex) {
            case 0: 
                return Produto.getCodigo();
            case 1:
                return Produto.getNome();
            case 2:
                return Produto.getPreco();
            case 3: 
                return quantidade2[rowIndex];  
                //aki é a quantidade que o produto tem... voce vera mais sobre isso quando for "addProduto"
            default:
               throw new IndexOutOfBoundsException("columnIndex out of bounds");
        }
    }


    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {

        Produto p = linhas.get(rowIndex);

        quantidade2[rowIndex] = (Integer.parseInt(aValue.toString()));
        
        fireTableDataChanged();

    }

    ;

    //método que eu fiz para retornar o total consumido até o momento
    public double getTotal() {
        int i;
        double total = 0;

       //enquanto houver linhas...
        for (i = 0; i < this.getRowCount(); i++) {
            total += linhas.get(i).getPreco() * quantidade2[i];
            //soma a multiplicação do preço por sua quantidade... (a posição [i] da quantidade é referente ao produto na posição i
        }
        return total;
    }



    //agora as coisas ficam interessantes...
    public void addProduto(Produto Produto, int quantidade) {
        int i;
        int posis = 0;
        boolean achou = false;

         //faço este for para verificar se o produto ja existe na tabela
        for (i = 0; i < this.getRowCount() && achou == false; i++) {
            Object prod2 = this.getValueAt(i, 0); //na linha i, na coluna 0, que é exatamente o código...

            if (prod2.equals(Produto.getCodigo())) {
                posis = i;
                achou = true;
            }
        }

        //se encontrei o produto, ou seja, ele ja estava na tabela, eis o que eu faço:
        if (achou) {
            Object prod2 = this.getValueAt(posis, 3);
            int ant = Integer.parseInt(prod2.toString());
            //nas duas linhas ACIMA eu pego a quantidade que ja estava na tabela...
            //e na linha ABAIXO somo 1 (ja q vou adicionar produtos 1 a 1)
            ant += 1;
            prod2 = ant;         
            //faço as modificações...
            this.setValueAt(prod2, posis, 3);
            fireTableDataChanged();
        } else {
            //OPA o produto nao foi encontrado na tabela...
           //então eu adiciono ele
            linhas.add(Produto);

            quantidade2[countPos] = quantidade;
            countPos++;

            int ultimoIndice = getRowCount() - 1;

            fireTableRowsInserted(ultimoIndice, ultimoIndice);
        }

    }

    // O ERRO ESTA AQUI (acredito eu)...

    public void removeProduto(int indiceLinha) {
        //vou diminuir a quantidade do produto no indice no qual ele foi clicado....
        quantidade2[indiceLinha]--;

        //se for 0, entao vou remover a linha
        if (quantidade2[indiceLinha] == 0) {
            linhas.remove(indiceLinha);
            countPos--;
            fireTableRowsDeleted(indiceLinha, indiceLinha);           
        }else{
         //se nao, havia a tabela que os dados mudaram... 
        fireTableDataChanged();
        }
    }

    [...]

agora vou descrever o problema… Na verdade funciona assim: eu tenho a minha GUI de gerenciar mesa, com duas tabelas… a primeira tabela contem todos os produtos cadastrados… a segunda tabela contem os itens dos objetos consumidos pela mesa (que é essa tabela que utilizo o modelo que mostrei acima)…

tudo bem, quando o cara clica em uma linha da 1 tabela, ele vai adicionar esse produto na tabela de consumidos (funciona perfeitamente)…

Quando eu clico na linha de um item da tabela de CONSUMIDOS ele vai retirar esse produto da lista…
Ta funcionando bem, se eu tiver APENAS um produto… agora vejam a situação problema:

-> Cliquei em um produto “Abacaxi” por exemplo, 3 vezes e depois cliquei em um produto “Maça” 1 vez (na minha tabela que lista os produtos cadastrados, logico…)
-> A tabela que contem os itens consumidos ficará assim:

Codigo Nome Preço Quantidade
0 Abacaxi 2.00 3
1 Maça 1.50 1

Perfeito certo? Agora se eu clicar 1 vez no “Abacaxi” na lista de itens consumidos, ele irá mudar sua quantidade para “2” e ira modificar o total (TAMBÉM perfeito)…

Agora o erro: se eu clicar 2x no Abacaxi eu O ELIMINO da tabela, assim a “Maça” que tava na posição “1” da tabela, agora vai ocupar a posição “0”… e assim, eis a m3rd@ que da:


Codigo Nome Preço Quantidade
1 Maça 1.50 0

Além disso, o valor total também zera ! e se eu clicar na Maça, começa a ficar negativo a “Quantidade”, e o “total” também fica negativo…

eitaaa!!

Alguma luz gente?

Cara… ficou confuso de entender seu Problema…

O que eu não entendi é quando estás removendo… O que é passado indiceLinha ??? É a linha Selecionada ???

Se for… o que o fireTableDataChanged() espera como parametro ?? é mesmo o índice da Linha ???

To tentando entender o ocorrido ainda…

Sim é o índice da tabela selecionada…

o fireDataChanged apenas avisa que algum dado mudou… ai ele “atualiza a tabela”…
É o que eu entendo pelo menos…

meu problema ta osso de entender mesmo… mas tentei explicar da melhor forma possível…
… vamos de novo

vamos supor que eu tenho 3 elementos na tabela…
abacaxi, que tem quantidade 2 //posicao 0 da tabela
maça, que tem quantidade 1 //posicao 1 da tabela
pera, que tem quantida de 10 //posicao 2 da tabela

se vc clicar na “maça” para eliminar ela da tabela, o elemento ‘pera’ vai assumir o seu lugar na tabela, ou seja, vai passar da posição 2 para posição 1… quando a pera faz isso, a sua quantidade muda de “10” para “0”, isso nao deveria acontecer… deveria continuar 10

sabia que o erro era ali …

Descobri…

sabe qual o problema? esqueci de atualizar a variavel quantidade2[]…

… vou tentar arrumar =x

[code]
public void removeProduto(int indiceLinha) {

    quantidade2[indiceLinha]--;

    if (quantidade2[indiceLinha] == 0) {
        linhas.remove(indiceLinha);

        int i;
        for(i=indiceLinha;i<this.getRowCount();i++){ //enquanto houver linhas 'depois' da que eu estou excluindo
            quantidade2[i] = quantidade2[i+1]; //atualiza o valor 1 casa
        }
        countPos--;  //variavel q controla a 'quantidade2' é decrementada
        fireTableRowsDeleted(indiceLinha, indiceLinha);           
    }else{
    fireTableDataChanged();
    }
}[/code]

Marco, concordo com o adriano_si, ficou confuso o jeito que você está tratando o problema. E perigosamente trabalhoso dar manutenção neste TableModel. Vou dar uma idéia (que eu fiz uma vez e funcionou muito bem):

Crie uma entidade que representa os produtos consumidos. Tipo: ProdutosConsumidos ? :slight_smile: Nela você tem uma referência ao produto e a quantidade de itens comprados daquele produto específico. Porque o que o seu TableModel guarda são produtos consumidos e não produtos. Então, você está tendo que manter duas listas separadas para fazer o controle do produto e das quantidades de cada um e é aí que está sua fonte de bugs: você tem que manter as duas listas sincronizadas.

Se tivesse uma entidade separada manteria apenas uma lista de ProdutosConsumidos e quando clicasse em remover, olha como ficaria mais simples e claro:

public void removeProduto(int linha) {
   ProdutosConsumidos consumidos = linhas.get(linha);
   consumidos.setQuantidade(consumidos.getQuantidade() - 1);

   // Verifica se ainda tem itens deste produto
   if (consumidos.getQuantidade() == 0) {
      linhas.remove(linha);
      fireTableRowsDeleted(linha, linha);
   } else {
      fireTableDataChanged();
   }
}

E o addProduto ficaria ainda mais simples:

public void addProduto(Produto produto, int quantidade) {
   boolean encontrou = false;
   int indice = 0;
   for (ProdutoConsumido consumido : linhas) {
      // Verifica se o produto já está na lista
      if (consumido.getProduto().getId() == produto.getId()) {
         encontrou = true;
         consumido.setQuantidade( consumido.getQuantidade() + quantidade );
         break; // sai do for porque já achei
      }
      indice++;
   }

   // Se não estiver na lista, adiciona
   if (!encontrou) {
      ProdutoConsumido consumido = new ProdutoConsumido(produto, quantidade);
      linhas.add(consumido);
      indice = linhas.size() - 1;
   }

   fireTableRowsInserted(indice, indice);
}

Uma idéia bem simples para a sua entidade seria algo como:

public class ProdutoConsumido {

   private Produto produto;
   private int quantidade;

   public ProdutoConsumido (Produto produto, int quantidade) {
      this.produto = produto;
      this.quantidade = quantidade;
   }

   // getters e setters aqui embaixo
}

Espero ter ajudado.
*EDIT algumas correções do código que não foi testado, é só para dar uma idéia

Obrigado visona…

na verdade o meu tableModel existe apenas para controlar os itens consumidos… Ele é um tableModel especifico para isso…

Mas a sua ideia é muitoooooooo mais elegante… Muito mais trivial…
obrigado