Já pesquisei no google e nos tópicos ... problema com JTable e Checkbox

6 respostas
gribeiro

:) Olá !
Bom dia a todos !

Sou iniciante em Java e estou com um projeto da faculdade em Swing pra concluir e tô ficando maluco já ... :(

Seguinte : no meu JFrame tenho duas tabelas. Uma para produtos e outro para serviços, pois trata-se de uma JFrame para CRUD de Ordem de Serviço para uma oficina mecânica. (projeto da facul mesmo !!! coisa acadêmica !!!)

Já populei as duas tabelas com dados do banco usando ArrayLists com generics para as duas classes (Produto e Serviço), sendo que a última coluna de cada tabela está como boolean para permitir marcar/desmarcar pelo usuário. Implementei as classes ServicoModel e ProdutoModel herdando de AbstractTableModel implementei também as classes Servico e ProdutoTableModelListener para capturar os evetos de clique na última coluna de cada tabela.

Agora vamos ao problema : tenho tentado implementar o método setValueAt(Object value,int row,int column) nas classes Model de Produto e Serviço, mas não estou conseguindo fazer com que seja modificado o status do checkbox de true para false e vice-e-versa.

Um dos problemas que encontrei é a questão do casting de objeto da classe serviço para Object, pois estou trabalhando com ArrayList usando generics como disse anteriormente.

Gostaria também que alguma caridosa alma me indicasse o caminho para efetuar a atualização no banco após efetuada alguma modificação do status da coluna da tabela que é boolean.

Agradeço antecipadamente a qualquer um que possa me ajudar nesta empreitada.

P.S.: Por favor, não me indiquem o tutorial da Sun, pq já o consultei e não foi capaz de sanar a minha dúvida.

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import br.com.entities.Servico;



public class ServicoModel extends AbstractTableModel {

	   private ArrayList <Servico> servicos;
           private ArrayList linhas=null;

	   public ServicoModel(ArrayList <Servico> servicos) {
	        this.servicos=servicos;
                setLinhas(servicos);
                
	   }

	   //Retorna a classe especifica (tipo) para cada coluna da tabela
	   //É usado pelo JTable para configurar a apresentação
    @Override
	   public Class<?> getColumnClass(int columnIndex) {
	        Class classe=null;
	        switch (columnIndex){
	        case 0 : classe = Integer.class; break;
	        case 1 : classe = String.class; break;
	        case 2 : classe = Double.class; break;
                case 3 : classe = Double.class; break;
                case 4 : classe = Double.class;break;
                case 5 : classe = Boolean.class;break;
	        }
	        return classe;
	    }

	    //Retorna o número de colunas no modelo
	    //JTable usa este método para determinar colunas criadas/exibidas
	    public int getColumnCount() {
	        return 6;
	    }

	    //Retorna o nome da coluna na posicao do indice recebido
	    //É usado para inicializar e exibir o nome de cada coluna da tabela
    @Override
	    public String getColumnName(int columnIndex) {
	        String columnName = null;
	        switch (columnIndex){
	        case 0 : columnName = "Cod"; break;
	        case 1 : columnName = "Descrição"; break;
	        case 2 : columnName = "Duração"; break;
                case 3 : columnName = "Vlr Hora/Fração"; break;
                case 4 : columnName = "Vlr Total"; break;
                case 5 : columnName = "Selecão";break;
	        }
	        return columnName;
	    }

	    //Retorna o número de linhas no modelo
	    //JTable usa este método para determinar quantas linhas devem ser exibidas
	    public int getRowCount() {
	        return servicos.size();
	    }

	  //Retorna o valor a ser preenchido em cada célula da tabela de acordo
	    //   com o indice dado para linha e indice dado para a coluna
	    public Object getValueAt(int rowIndex, int columnIndex) {
	        Servico serv = servicos.get(rowIndex); //obtem um objeto da lista de objetos
	        Object retorno = null;  //prepara um objeto para retorno no método
	        switch (columnIndex){   //seleciona e retorno o objeto de acordo com valor coluna
	        case 0 : retorno = serv.getIdservico(); break;
	        case 1 : retorno = serv.getDescricao(); break;
	        case 2 : retorno = serv.getDuracao(); break;
                case 3 : retorno = serv.getVlrhora();break;
                case 4 : retorno = serv.getVlrtotservico();break;
                case 5 : retorno = serv.isSelecserv();break;
                 
	        }
	        return retorno;
	    }

    @Override
	    public boolean isCellEditable(int rowIndex, int columnIndex) {
                if (columnIndex>4) {
                    return true;
                } else {
                    return false;
                }
	        
	    }

    @Override
            public void setValueAt(Object valor, int r, int c){
                String[] linha = (String[]) getLinhas().get(r);
                linha[c] = (String) valor;
                fireTableCellUpdated(r,c);
             
             
            }

    /**
     * @return the linhas
     */
    public ArrayList getLinhas() {
        return linhas;
    }

    /**
     * @param linhas the linhas to set
     */
    public void setLinhas(ArrayList linhas) {
        this.linhas = linhas;
    }

    
}

6 Respostas

ViniGodoy

O seu setValueAt deve fazer a atualização do valor:

public void setValueAt(Object valor, int r, int c){ Servico servico = linhas.get(r); switch (c) { case 5: servico.setSelectServ(((Boolean)valor).booleanValue()); break; } }

Não é necessário usar o fireTableCellUpdated. Você só chama os métodos “fire” se você mesmo fez a atualização. Quando a Table chama o model, ela já sabe que o valor ali foi alterado.

ViniGodoy

Aliás, tem muita coisa que poderia ser simplificada no seu model:

import java.util.Collection;
import java.util.List;
import java.util.ArrayList;  
import javax.swing.table.AbstractTableModel;  
import br.com.entities.Servico;  

public class ServicoModel extends AbstractTableModel {  
   private List &lt;Servico&gt; servicos;  
   private String[] colunas = {&quot;Cod&quot;, &quot;Descrição&quot;, &quot;Duração&quot;, &quot;Vlr Hora/Fração&quot;, &quot;Vlr Total&quot;, &quot;Selecão&quot;};
   private Class&lt;?&gt;[] tipoColunas = {Integer.class, String.class, Double.class, Double.class, Double.class, Boolean.class};

   public ServicoModel(Collection&lt;Servico&gt; servicos) {  
      assert (colunas.length == tipoColunas.length);
      this.servicos = new ArrayList&lt;Servicor&gt;(servicos);
   }  
   
   //Retorna a classe especifica (tipo) para cada coluna da tabela  
   //É usado pelo JTable para configurar a apresentação  
   @Override  
   public Class&lt;?&gt; getColumnClass(int columnIndex) {  
      return tipoColunas[columnIndex];
   }

   //Retorna o número de colunas no modelo  
   //JTable usa este método para determinar colunas criadas/exibidas  
   public int getColumnCount() {  
      return colunas.length;  
   }  

   //Retorna o nome da coluna na posicao do indice recebido  
   //É usado para inicializar e exibir o nome de cada coluna da tabela  
   @Override  
   public String getColumnName(int columnIndex) {        
      return colunas[columnIndex];
   }

   //Retorna o número de linhas no modelo  
   //JTable usa este método para determinar quantas linhas devem ser exibidas  
   public int getRowCount() {  
      return servicos.size();  
   }  

   //Retorna o valor a ser preenchido em cada célula da tabela de acordo  
   //   com o indice dado para linha e indice dado para a coluna  
   public Object getValueAt(int rowIndex, int columnIndex) {  
      Servico serv = servicos.get(rowIndex); //obtem um objeto da lista de objetos  
      switch (columnIndex){   //seleciona e retorno o objeto de acordo com valor coluna  
         case 0 : return serv.getIdservico();
         case 1 : return serv.getDescricao(); 
         case 2 : return serv.getDuracao(); 
         case 3 : return serv.getVlrhora();
         case 4 : return serv.getVlrtotservico();
         case 5 : return serv.isSelecserv();  
      }  
      throw new IllegalArgumentException(&quot;Coluna inválida &quot; + c);  
   }  

   @Override  
   public boolean isCellEditable(int rowIndex, int columnIndex) {  
      return columnIndex == 5;
   }  
   @Override  
   public void setValueAt(Object valor, int r, int c){    
      Servico servico = linhas.get(r);  
      switch (c) {  
         case 5: servico.setSelectServ(((Boolean)valor).booleanValue()); break;  
      }  
   }  

   /** 
   * @return the linhas 
   */  
   public List&lt;Servico&gt; getLinhas() {  
      return Collections.unmodifiableList(linhas);  
   }  
}
gribeiro

:slight_smile: Obrigado mesmo , Vini !

O código tava “sobrecarregado” pois boa parte dele foi recebida como 'receita de bolo" do professor e como o prazo pra entrega do projeto tá quase estourando e eu fui premiado por ficar com a parte mais “pesada” do projeto deu nisso !!! :frowning:

Só fiquei com uma dúvida ainda : @Override public void setValueAt(Object valor, int r, int c){ Servico servico = linhas.get(r); switch (c) { case 5: servico.setSelecserv(((Boolean)valor).booleanValue()); break; } }

Esse objeto “linhas” ficou de fora do seu código né ? Pq o procurei em todo lugar e nada de achá-lo, então aproveitei o List servicos e fiz a atribuição : Servico servico = servicos.get®; Era essa a sua idéia ? Por favor, me corrija se eu estiver errado ! :smiley:

Valeu também pela dica do método “fireCellUpdated” ! Newbie no assunto é assim mesmo ! :smiley:

Mais uma vez : Muito obrigado pela rapidez na resposta e pelas orientações !

Sds,

Gribeiro

ViniGodoy

É isso mesmo. Não tem pq ter duas listas, basta uma só. No meu código aquele “linhas” ficou sobrando pq fiz copy&paste do tópico anterior, ehehehehe. Mas pode substituir por servicos sem problemas.

gribeiro

:smiley: Grande,Vini !

Tá tudo funfando belezinha agora ! hehehe
Só me tira mais uma dúvida, se possível !

Já implementei tbm o listener para capturar os cliques nas duas tables (produto e serviço) e já fiz com que a aplicação efetue a soma dos produtos e serviços selecionados e atribua ao valor total da ordem de serviço !

Agora a dúvida : quero que à medida que eu vá selecionando produtos e serviços seja atualizado no textfield que contém o valor total da ordem de serviço o valor total da OS de forma automática. Para isso vou precisar de um listener para o textfield ? Onde devo colocar esse código na aplicação ?

Agradeço antecipadamente por sua imensa colaboração ! :slight_smile:

[]'s

Gribeiro

gribeiro

:smiley: Mais um detalhe …

Como e onde faço a inserção do código para formatar valores double a serem exibidos nas jtables ???

[]'s

Gribeiro

Criado 10 de novembro de 2009
Ultima resposta 11 de nov. de 2009
Respostas 6
Participantes 2