Duplicando Cabeçalho TableModel

15 respostas
Alchemist

Bom dia amigos, estou com um pequeno problema que não consigo achar a solução.

Estou fazendo o meu proprio TableModel, porem quando ele joga os valores na tabela ele duplica o cabeçalho da tabela, ficando assim:

ITEM ID_USUARIO NM_PESSOA ID_PESSOA ID_PESSOAUSUARIO NR_CNPJCPF NR_RG DT_NASCIMENTO
ITEM ID_USUARIO NM_PESSOA ID_PESSOA ID_PESSOAUSUARIO NR_CNPJCPF NR_RG DT_NASCIMENTO

E logo abaixo os dados normais que a minha query carrega.

meu codigo:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.table.DefaultTableModel;

import POJO.PessoaUsuario;

public class TableModelPessoa extends DefaultTableModel { 
   
  private Map<Integer,PessoaUsuario> listaPessoas;  
  public String[] colunas;      
     
   public TableModelPessoa(Map<Integer,PessoaUsuario> lista){
       this.listaPessoas = lista;  
        
    }  
     
   public int getColumnCount(){  
      return 8;  
   }  
  
   public String getColumnName(int coluna) {     
       switch(coluna){  
         case  0:return "ITEM";  
         case  1:return "ID_USUARIO";  
         case  2:return "NM_PESSOA";  
         case  3:return "ID_PESSOA";  
         case  4:return "ID_PESSOAUSUARIO"; 
         case  5:return "NR_CNPJCPF"; 
         case  6:return "NR_RG"; 
         case  7:return "DT_NASCIMENTO"; 
         default:return "";  
       }  
    }  
   
   public Object getValueAt(int linha, int coluna) {
	   
	   if (linha == 0){ 
		   System.out.println("Entrada: "+linha+"º   Coluna:"+coluna);
         return getColumnName(coluna);
       }  
         
      List<PessoaUsuario> vetor = new ArrayList<PessoaUsuario>();        
      vetor.addAll(listaPessoas.values());
      System.out.println("Linha: "+linha+" Coluna: "+coluna+"   OBJETO: "+listaPessoas.values());
      PessoaUsuario pessoa = vetor.get(linha-1);              
      switch(coluna){  
         case  0:return new Boolean(true);  
         case  1:return pessoa.getIdUsuario();  
         case  2:return pessoa.getNmPessoa();  
         case  3:return pessoa.getIdPessoa();  
         case  4:return pessoa.getIdPessoaUsuario();  
         case  5:return pessoa.getNrCnpjcpf();  
         case  6:return pessoa.getNrRg();  
         case  7:return pessoa.getDtNascimento();  
         default:return "";  
       }  
         
   }  
  
   public Class<?> getColumnClass(int coluna) {  
       switch(coluna){  
       case  0:return getValueAt(0, coluna).getClass();    
       case  1:return String.class;  
       case  2:return String.class;  
       case  3:return String.class;  
       case  4:return String.class;
       case  5:return String.class; 
       case  6:return String.class; 
       case  7:return String.class; 
       
       default:return Object.class;  
       }  
    }  
   
    public int getRowCount() {  
      return listaPessoas != null ? listaPessoas.size() + 1  : 1;  
    }  
   
    public boolean isCellEditable(int linha, int coluna) {  
	    if (linha == 0){  
	         return false;     
	      }else{  
	         return true;  
	    }  
    }  
   
 }

Onde eu crio a tabela

modelo= new TableModelPessoa(listPessoa);
JTable jtable = new JTable(modelo);

listPessoa : é o MAP que a minha query me retorna com os resultados.

Bom espero que alguem possa me ajudar pq esta realmente dificil para mim.

15 Respostas

andreiribas

Primeiro de tudo, coloque entre cada instrução case um break no final, senão quando uma opção cair no case especificado, ele vaie executar todos os outros cases até achar um break ou o fim do comando.

B

Ola,

Seguinte, quando vc dá os nomes da coluna o jtable automaticamente já os coloca nos header, tá duplicando pq:
1-> vc tá retornando os nomes das colunas na linha 0, retire as linhas
2-> as linhas são apenas seus dados… naõ precisa retornar: 39 a 42

return listaPessoas != null ? listaPessoas.size() + 1 : 1; É só retornarreturn listaPessoas != null ? listaPessoas.size() : 0; e pronto.

B

Por ser apenas “return” não precisa de break não :wink:

Alchemist

colocando:

ele come a minha ultima linha adicionada, por exemplo

ANTES

DEPOIS

Ele acaba comendo a ultima linha, dos dados e o cabeçalho continua duplicado.

:S ta dificil de saber viu !

B

Alchemist:
colocando:

ele come a minha ultima linha adicionada, por exemplo

ANTES

DEPOIS

Ele acaba comendo a ultima linha, dos dados e o cabeçalho continua duplicado.

:S ta dificil de saber viu !

vamos de novo…
1-> Apague as linhas do metodo getValueAt if (linha == 0){ System.out.println("Entrada: "+linha+"º Coluna:"+coluna); return getColumnName(coluna); }
2-> tá sumindo com o seu ultimo registro por causa desta linha:

PessoaUsuario pessoa = vetor.get(linha-1);Tire este ‘-1’ dae…
3->Porque fazer a conversão do map para o vector toda vez que o metodo getValueAt é invocado??? faça no construtor, pq este getValueAt é invocado rowXcolumns vezes…

Alchemist

Opa muito obrigado BrunoCarlo… fiz e deu certo, vou colocar o codigo final aqui para quem precisar já ter a solução:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.table.DefaultTableModel;

import POJO.PessoaUsuario;

public class TableModelPessoa extends DefaultTableModel { 
   
	private static final long serialVersionUID = 1L;
	private Map<Integer,PessoaUsuario> listaPessoas;  
	private List<PessoaUsuario> vetor;
   
   public TableModelPessoa(Map<Integer,PessoaUsuario> lista){
       this.listaPessoas = lista;  
       vetor = new ArrayList<PessoaUsuario>(); 
    }  

   public int getColumnCount() {
	   return 8;
	 }   

   public String getColumnName(int coluna) {    
       switch(coluna){  
         case  0:return "ITEM";  
         case  1:return "ID_USUARIO";  
         case  2:return "NM_PESSOA";  
         case  3:return "ID_PESSOA";  
         case  4:return "ID_PESSOAUSUARIO"; 
         case  5:return "NR_CNPJCPF"; 
         case  6:return "NR_RG"; 
         case  7:return "DT_NASCIMENTO"; 
         default:return "";  
       }  
    }  
   
   public Object getValueAt(int linha, int coluna) {
	   
      vetor.addAll(listaPessoas.values());

      PessoaUsuario pessoa = vetor.get(linha);              
      switch(coluna){  
         case  0:return pessoa.getIdUsuario();  
         case  1:return pessoa.getIdUsuario();  
         case  2:return pessoa.getNmPessoa();  
         case  3:return pessoa.getIdPessoa();  
         case  4:return pessoa.getIdPessoaUsuario();  
         case  5:return pessoa.getNrCnpjcpf();  
         case  6:return pessoa.getNrRg();  
         case  7:return pessoa.getDtNascimento();  
         default:return "";
       }  
   }  
  
   public Class<?> getColumnClass(int coluna) {  
       switch(coluna){  
       case  0:return getValueAt(0, coluna).getClass();    
       case  1:return String.class;  
       case  2:return String.class;  
       case  3:return String.class;  
       case  4:return String.class;
       case  5:return String.class; 
       case  6:return String.class; 
       case  7:return String.class; 
       
       default:return Object.class;  
       }  
    }

    public int getRowCount() {  
      return listaPessoas != null ? listaPessoas.size(): 1;  
    } 
   
 }

Pessoal aproveitando gostaria que vcs me ajudasem em outra coisa:

1º Eu precisava que esta minha primeira coluna tive-se um checkbox dentro dela, como eu posso implementar no meu modelo isto, dei uma pesquisada e achei este codigo:

modelo = new DefaultTableModel(dados, colunas) { public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } };

para uma DefaultTableModel, então tentei colocar no modelo assim:

public Class<?> getColumnClass(int coluna) {  
       switch(coluna){  
       case  0:return getValueAt(0, coluna).getClass();    
       case  1:return String.class;  
       case  2:return String.class;  
       case  3:return String.class;  
       case  4:return String.class;
       case  5:return String.class; 
       case  6:return String.class; 
       case  7:return String.class; 
       
       default:return Object.class;  
       }  
    }

porem ela só retorna false ou true :S

Como posso fazer ?

E a minha 2º duvida é como colocar o scroll horizoltal, e deixar os campos da tabela sem contar o conteudo dentro dela, por exemplo aparecer o nome completo na celula da tabela :S

usei o metodo setAutoResizeMode(JTable.AUTO_RESIZE_OFF) ; na tabela mais ela fica cortando os dados igual eu citei acima :stuck_out_tongue:

B
Respostas: 1: só vc devolver Boolean.class no getColumnClass:
public Class<?> getColumnClass(int coluna) {  
       switch(coluna){  
       case  0:return Boolean.class;    
       case  1:return String.class;  
       case  2:return String.class;  
       case  3:return String.class;  
       case  4:return String.class;
       case  5:return String.class; 
       case  6:return String.class; 
       case  7:return String.class; 
       
       default:return Object.class;  
       }  
    }

2: vc deve setar o setAutoResizeMode(JTable.AUTO_RESIZE_OFF) ;, mas lembre-se de colocar a tabela dentro de u JScrollPane antes de adicionar no sua panel.
se a coluna estiver cortando o nome vc pode setar o preferedSize dela, só pega-la atraves do index no JTable.getColumnModel().getColumn(int columnIndex) e setar o setPreferredWidth(int preferredWidth).

Alchemist

Opa então fiz o que vc falou para colocar o checkbox

public Object getValueAt(int linha, int coluna) {
	   
      vetor.addAll(listaPessoas.values());

      PessoaUsuario pessoa = vetor.get(linha);              
      switch(coluna){  
         case  0:return new Boolean(false);  
         case  1:return pessoa.getIdUsuario();  
         case  2:return pessoa.getNmPessoa();  
         case  3:return pessoa.getIdPessoa();  
         case  4:return pessoa.getIdPessoaUsuario();  
         case  5:return pessoa.getNrCnpjcpf();  
         case  6:return pessoa.getNrRg();  
         case  7:return pessoa.getDtNascimento();  
         default:return "";
       }  
   }  
  
   public Class<?> getColumnClass(int coluna) {  
       switch(coluna){  
       case  0:return Boolean.class;    
       case  1:return String.class;  
       case  2:return String.class;  
       case  3:return String.class;  
       case  4:return String.class;
       case  5:return String.class; 
       case  6:return String.class; 
       case  7:return String.class; 
       
       default:return Object.class;  
       }  
    }

O check apareceu na minha table, porem quando eu vou clicar nela pela PRIMEIRA vez, eu consigo selecionar e des-selecionar o checkbox, então eu tento clicar em algum outro e não consigo ele da o seguinte erro:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 5 >= 1
	at java.util.Vector.elementAt(Unknown Source)
	at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
	at javax.swing.JTable.setValueAt(Unknown Source)
	at javax.swing.JTable.editingStopped(Unknown Source)
	at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source)
	at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(Unknown Source)
	at javax.swing.DefaultCellEditor.stopCellEditing(Unknown Source)
	at javax.swing.JTable.editCellAt(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI$Handler.adjustFocusAndSelection(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(Unknown Source)
	at java.awt.AWTEventMulticaster.mousePressed(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Esta dando erro de tamanho de array :S

B

Para fazer isto vc tem que implementar o metodo setValueAt(Object newValue, int row, int column) no seu modelo.

O erro ocorre pq como vc não implementou o metodo ele vai usar o vector do abstractTableModel… que está zerado… saca?

Fernando_Generoso_da

Extende AbstractTableModel, e não DefaultTableModel.

B

Isto faz muita diferença não…

Alchemist

o Bruno será que vc n tem nenhum exemplo legal para mandar, procurei na net mais achei varios complicados e todos com o codigo mais sujo do que sei la :S pelo menos uma diquinha, pq ai eu encontro o resto do caminho !

B

Ola, seria +/- isto aqui:
Aproveitando o seu model…

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.table.DefaultTableModel;

import POJO.PessoaUsuario;

public class TableModelPessoa extends DefaultTableModel {

	private static final long serialVersionUID = 1L;
	private Map<Integer, PessoaUsuario> listaPessoas;
	private List<PessoaUsuario> vetor;

	// esta lista aqui vai guardar o seu boolean....
	private List<Boolean> booleans;

	public TableModelPessoa(Map<Integer, PessoaUsuario> lista) {
		this.listaPessoas = lista;
		// vetor = new ArrayList<PessoaUsuario>(); substiuir por esta de baixo
		// desta forma vc cria um vector com as linhas e ja popula ele
		vetor = new Vector<PessoaUsuario>(listaPessoas.values());

		// iniica os booleans
		booleans = new Vector<Boolean>();
		// popula os booleans para ficarem com o mesmo numero de elementos que o
		// vetor... assim sera um por linha
		for (int x = 0; x < vetor.size(); x++) {
			booleans.add(false);
		}
	}

	public int getColumnCount() {
		return 8;
	}

	public boolean isCellEditable(int row, int column) {
		return column == 0; // so permite a edicao da coluna 0, ou seja onde
							// vamos
		// colocar o checkbox
	}

	public String getColumnName(int coluna) {
		switch (coluna) {
		case 0:
			return "ITEM";
		case 1:
			return "ID_USUARIO";
		case 2:
			return "NM_PESSOA";
		case 3:
			return "ID_PESSOA";
		case 4:
			return "ID_PESSOAUSUARIO";
		case 5:
			return "NR_CNPJCPF";
		case 6:
			return "NR_RG";
		case 7:
			return "DT_NASCIMENTO";
		default:
			return "";
		}
	}

	public Object getValueAt(int linha, int coluna) {

		/*
		 * tira esta linha daqui... pq senao toda vez que a table for
		 * renderizada vc vai pupolar vetor.addAll(listaPessoas.values());
		 */

		PessoaUsuario pessoa = vetor.get(linha);
		switch (coluna) {
		case 0:
			return booleans.get(row);
		case 1:
			return pessoa.getIdUsuario();
		case 2:
			return pessoa.getNmPessoa();
		case 3:
			return pessoa.getIdPessoa();
		case 4:
			return pessoa.getIdPessoaUsuario();
		case 5:
			return pessoa.getNrCnpjcpf();
		case 6:
			return pessoa.getNrRg();
		case 7:
			return pessoa.getDtNascimento();
		default:
			return "";
		}
	}

	public Class<?> getColumnClass(int coluna) {
		switch (coluna) {
		case 0:
			return Boolean.class;
		case 1:
			return String.class;
		case 2:
			return String.class;
		case 3:
			return String.class;
		case 4:
			return String.class;
		case 5:
			return String.class;
		case 6:
			return String.class;
		case 7:
			return String.class;

		default:
			return Object.class;
		}
	}

	/**
	 * metodo que sera chamado quando a edicao da celula acabar
	 */
	public void setValueAt(Object ob, int row, int column) {
		if (column != 0 || !Boolean.class.isInstance(ob)) {
			return;
		}
		booleans.remove(row);
		booleans.add(row, (Boolean) ob);
	}

	public int getRowCount() {
		return listaPessoas != null ? listaPessoas.size() : 0;
	}

}

Agora, vc ira perguntar a questao de editores… mas tabelas… para ja adiantar, vc pode dar uma olhada em http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

Alchemist

Opa bruno muito obrigado vc não tem noção do quanto vc me ajudou!

Eu já estava dando uma olhada neste tuto da sun :stuck_out_tongue: vou implementar umas coisas que estão nele !!

Para para finalizar o topico queria pedir a opnião de vcs sobre o meu metodo que cria a tabela e set o tamanho das colunas:

public void criaTabelaPessoa(Map<Integer,PessoaUsuario> lista){

	    modelo = new TableModelPessoa(listaPessoa);  
	    JTable jtable = new JTable(modelo);
	    jtable.getColumnModel().getColumn(0).setPreferredWidth(50);
	    jtable.getColumnModel().getColumn(1).setPreferredWidth(200);
	    jtable.getColumnModel().getColumn(2).setPreferredWidth(250);
	    jtable.getColumnModel().getColumn(3).setPreferredWidth(100);
	    jtable.getColumnModel().getColumn(4).setPreferredWidth(100);
	    jtable.getColumnModel().getColumn(5).setPreferredWidth(150);
	    jtable.getColumnModel().getColumn(6).setPreferredWidth(150);
	    jtable.getColumnModel().getColumn(7).setPreferredWidth(120);
	    
	    jtable.getTableHeader().setReorderingAllowed(false);
	    jtable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
	    
		scrollPane= new JScrollPane(jtable);
		scrollPane.setBounds(10,10,740,230);
		
		JdComparacao.removeAll();
		JdComparacao.updateUI();
		JdComparacao.add(scrollPane);
	}

Posso deixar assim ? Ou tem uma forma melhor de implementar ?

Abraços e muito obrigado a todos que me ajudaram ^^

B

Eu geralmente faço assim mesmo… pq estas configurações são muito específicas de tabela pra tabela… acho que ficou bom.

Criado 26 de março de 2009
Ultima resposta 27 de mar. de 2009
Respostas 15
Participantes 4