JTable Dinamica!

55 respostas
J

Olá pessoal, minha duvida é a seguinte eu gostaria de construir uma tela de consulta que funcionasse pra todo o
sistema. Mas para isso eu necessitaria criar uma JTable dinamica que funcionasse genericamente somente com passagem de parametros. Obs: eu trabalho beans. Isso é possivel? Alguem ja fez isso ou pode me ajudar?

grato.

55 Respostas

V

Dê uma olhada na implementação de TableModel presente nesse exemplo:
http://www.guj.com.br/posts/list/100793.java

Você só precisa passar uma lista de colunas para ele. Essa lista pode ser fornecida por parâmetro.

Aliás, você sabe exatamente como funciona o TableModel? Sabe construir um model próprio?
Sem saber isso, fica difícil fazer o que você quer.

Se não sabe, leia os seguintes artigos:
http://www.informit.com/articles/article.aspx?p=332278
http://www.informit.com/articles/article.aspx?p=333472

J

Obrigado amigo! vou analisar seu codigo. Entendo e sei criar um TableModel

L

Se vc quer algo bem dinamico vc pode usar annotation para ler o seu bean e montar a jtbale baseado nas propriedades do seu bean.
Eu tenho alguns códigos prontos aqui que eu implementei…se vc quiser eu posso postar ai pra vc.

Abraços.

J

Se vc postar o codigo ou me mandasse no e-mail [email removido] ficaria muito grato! O meu problema é exatamente pegar os valores dos beans dinamicamente.

M

Reflection também é interessante… já escrevi um tableModel assim e para construir uma tabela eu preciso fazer apenas algo assim

FieldResolverFactory resolvers = new FieldResolverFactory(Pessoa.class);
ObjectTableModel model = new ObjectTableModel(new FieldResolver[]{
resolvers.create("nome","Nome:"),//1° = nome do campo, 2° = nome da coluna na tabela
resolvers.create("rg"),//o nome do campo é assumido para o nome da coluna
resolvers.create("idade", Formatters.INT_FORMATTER)//Para campos que não sejam String(Se voce quiser apenas mostrar o valor não é nexessario um Formatter mas para atualizar o bean é.
});
JTable table = new JTable(model);
model.setData(dao.getList(Pessoa.class));

Com esse código voce teria uma JTable para a classe Pessoa que mostra o nome, rg e a idade na tabela.

Ainda implementei por Annotation um modo para marcar na classe os valores configuraveis para o FieldResolver.

L

E ai josimarsis, blz?
Então, eu já li todos esses posts que o ViniGodoy te passou e acho importante vc olhar...além disso seria legal vc entender Reflection(se não conhecer).Segue o exemplo: vamos considerar um exemplo simples:Clientes.

1º passo: vamos criar uma annotation - depois explico melhor sobre ela.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Coluna {
//vamos utilizar esta annotation para pegar o nome da coluna,posicao no jtable e o formato que queremos mostrar - vamos usar com uma data
//como exemplo.
	String nome();
	int posicao();
	String formato() default "%s";

}

2º passo:vamos criar o bean com as annotation:

import java.util.Calendar;


public class ClienteBean {
    private Integer codigoCliente;
    private String nomeCliente = "";
    private String cpf = "";
    private Calendar dataNascimento;

    public void setCodigoCliente(Integer codigoCliente) {
        this.codigoCliente = codigoCliente;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public void setDataNascimento(Calendar dataNascimento) {
        this.dataNascimento = dataNascimento;
    }

    public void setNomeCliente(String nomeCliente) {
        this.nomeCliente = nomeCliente;
    }

    @Coluna(posicao=0,nome="Código do Cliente")//posicao no jable e o nome para exibir na coluna
    public Integer getCodigoCliente() {
        return codigoCliente;
    }

    @Coluna(posicao=3,nome="CPF")//posicao no jable e o nome para exibir na coluna
    public String getCpf() {
        return cpf;
    }

    @Coluna(posicao=2,nome="Data de Nascimento", formato="%1$Td/%1$Tm/%1$TY") //posicao no jable, o nome para exibir na coluna e formato //para data, senão ele iria chamar toString de Calendar.
    public Calendar getDataNascimento() {
        return dataNascimento;
    }

    @Coluna(posicao=1,nome="Nome do Cliente")
    public String getNomeCliente() {
        return nomeCliente;
    }

}

3º passo e o mais importante: implementar TableModelPadraoParaBean

import java.lang.reflect.Method;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class TableModelPadraoParaBean extends AbstractTableModel {
  private Class<?> classe;
  private List<?> lista;

   public TableModelPadraoParaBean(List<?> linhas) {
      this.setLinhas(linhas);
      if (linhas != null)
        this.classe = linhas.get(0).getClass();
   }

   public int getRowCount() {
      if (lista != null) {
         return lista.size();
      } else {
         return 0;
      }
   }

   public int getColumnCount() {
       int colunas = 0;
       for(Method m : classe.getDeclaredMethods()){
           if(m.isAnnotationPresent(Coluna.class)){
               colunas++;
           }
       }
      return colunas;
   }

   public boolean isCellEditable(int row, int col) {
      return false;
    }

    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }

    public void setLinhas(List<?> linhas) {
      this.lista = linhas;
      fireTableDataChanged();
   }

   public Object getValueAt(int rowIndex, int columnIndex) {
       try{
           Object objeto = lista.get(rowIndex);
           for(Method m : classe.getDeclaredMethods()){
               Coluna c = m.getAnnotation(Coluna.class);
               if(c != null && c.posicao() == columnIndex){
                   return String.format(c.formato(), m.invoke(objeto));
               }
           }
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return "";
   }
    public String getColumnName(int coluna){
        for(Method m : classe.getDeclaredMethods()){
            Coluna c = m.getAnnotation(Coluna.class);
            if(c != null && c.posicao() == coluna ){
                return c.nome();
            }
        }
        return "";
    }
}

E para testar um exemplo usando o NetBeans:

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import resultadoonline.gui.ClienteBean;
import resultadoonline.gui.TableModelPadraoParaBean;

public class NewJFrame extends javax.swing.JFrame {


    public NewJFrame() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTable1.setModel(new TableModelPadraoParaBean(linhasClientes));
        jScrollPane1.setViewportView(jTable1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(28, 28, 28)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(34, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 303, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(139, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                linhasClientes = new ArrayList<ClienteBean>();
                ClienteBean cb1 = new ClienteBean();
                cb1.setCodigoCliente(1);
                cb1.setNomeCliente("Ronaldo");
                cb1.setDataNascimento(Calendar.getInstance());
                cb1.setCpf("[CPF removido]");

                ClienteBean cb2 = new ClienteBean();
                cb2.setCodigoCliente(2);
                cb2.setNomeCliente("Fernanda da Silva");
                cb2.setDataNascimento(Calendar.getInstance());
                cb2.setCpf("[CPF removido]");

                linhasClientes.add(cb1);
                linhasClientes.add(cb2);
                new NewJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration
    private static List<ClienteBean> linhasClientes;
}

Se ficar com dúvida no codigo me avisa...

Abraços

J

Entedi a logica do seu codigo, Vou dar uma olhadinha no Reflection pois eu confesso que não conheço.
So não entedi esse codigo abaixo:

private Class<?> classe;

(Method m : classe.getDeclaredMethods())

Alguem poderia me explicar o que é o Method e o classe.getDeclaredMethods()?
M

classe é a Classe do seu objeto que pode ser conseguido com objeto.getClass() ou NomeDaClasse.class.

Method é um método da classe. e Class.getDeclaredMethods retorna todos declarados nessa classe.

J

Entendi amigo! Andei lendo sobre o Reflection aqui o negocio é muito legal. com ele eu posso criar meus proprios annotations. Creio que a unica maneira de eu fazer uma unica tela so de consulta pra o meu sistema todo é mapear o bean. Desta forma pelo que eu pude entender no seu codigo so vou precisar prassar como modelo pra minha JTable a classe TableModelPadraoParaBean(List<?> linhas) certo?

L

Bom, eu não sabia que vc queria fazer isso em uma unica tela.Neste caso é melhor vc colocar + um metodo na classe TableModelPadraoParaBean para vc não ficar fazendo varias instancias na mesma tela.E ai vc atualiza o seu list… e em consequencia disso o jtabel ja vai ser avisado que houve mudança na lista.Segue o codigo:

public void atualiza(List<?> lista) {
        setLinhas(lista);
        
        if((lista != null))
        	this.classe = lista.get(0).getClass();
}
J

Lintz_net atraves do teu codigo eu montei um exemplo aqui com banco de dados e tudo mais quando eu consulto em uma tabela tudo certo, quando necessito mostrar na minha consulta um campo que faz Join com outra tabela não funciona! Eu estou usando JPA então quando populo meu bean na chave estrangeira eu tenho outro objeto. Vc já passou por isso?

L

Ixi… não tive este problema,não!!Como está criado o seu modelo?.
Como não tenho certeza como está seu modelo vou imaginar alguma situação como vc descreveu…

Mas te respondendo de imediato(e uma solução não muito elegante que tive agora) é vc criar um objeto que representa os dados do seu jtabel que junta todas as propriedades que vc precisa aprensentrar, dos dois objetos…

Me mostra um exemplo do seu código depois.

Abraços.

J

Olha o exemplo que fiz foi so pra testar se eu conseguia listar os dados na tabela mesmo quando eu tivesse um Join
Segue o exemplinho junto com o script do banco (mysql). Quanto ao modelo da classe eu usei o seu modelo a classe
TableModelPadraoParaBean. Esse exemplo foi feito no netbeans e utiliza JPA com Hibernate. Os dados foram inseridos manualmente nas tabelas do banco pra ser feita a consulta.

L

Olá josimarsis,

Como eu te falei antes, vc pode resolver criando um objeto que representa os dados do seu jtabel que junta todas as propriedades que vc precisa aprensentrar, dos dois objetos(clientes e empresa), ou vc pode criar um metodo no bean cliente que contém a informação da empresa que vc quer apresentar, p/exemplo:

@Coluna(posicao=4,nome="Empresa")//posicao no jable e o nome para exibir na coluna
    public Integer getEmprCodigo() {
        return emprCodigo.getEmprCodigo();
    }

Abraços.

7

Veja se isso lhe ajuda… E um exemplo utilizand ouma biblioteca de desenvolvimento pra J2SE…
http://grupodax.wordpress.com/2009/05/03/exemplo-de-jtable-com-daxcomponents/

http://grupodax.blogspot.com/2009/05/daxcomponents-jtable.html

Espero que ajude…

J

Olá 71C4700 eu dei uma olhada no daxcomponents e achei legal e vou estuda-ló melhor. mas eu ja estou bem
adiantado na construção desta tabela graças a ajuda de vcs aqui do Guj. Estou utilizando Reflection

Atualmente eu tenho o seguinte problema:
Eu criei um RowSorter onde o usuario pode classificar os dados de maneira Crescente e Decrescente. A Classificação não funciona
para numeros e ou valores R$, Creio eu que seja pq a JTable interpreta todos os dados que eu passei pra ela como se fossem String.
Como modelo para a JTable estou utilizando este modelo que encontrei na net. Ele Recebe um List de Beans com Reflection e consegue interpreta-los

package comum;

import java.lang.reflect.Method;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class TableModelPadraoParaBean extends AbstractTableModel {
  private Class<?> classe;
  private List<?> lista;

    public TableModelPadraoParaBean(List<?> linhas) {
      this.setLinhas(linhas);
      if (linhas != null)
        this.classe = linhas.get(0).getClass();
   }

   public void atualiza(List<?> lista) {
        setLinhas(lista);

        if((lista != null))
        	this.classe = lista.get(0).getClass();
}


   public int getRowCount() {
      if (lista != null) {
         return lista.size();
      } else {
         return 0;
      }
   }

   public int getColumnCount() {
       int colunas = 0;
       for(Method m : classe.getDeclaredMethods()){
           if(m.isAnnotationPresent(Coluna.class)){
               colunas++;
           }
       }
      return colunas;
   }

    @Override
   public boolean isCellEditable(int row, int col) {
      return false;
    }

    @Override
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }

    public void setLinhas(List<?> linhas) {
      this.lista = linhas;
      fireTableDataChanged();
   }

   public Object getValueAt(int rowIndex, int columnIndex) {
       try{
           Object objeto = lista.get(rowIndex);
           for(Method m : classe.getDeclaredMethods()){
               Coluna c = m.getAnnotation(Coluna.class);
               if(c != null && c.posicao() == columnIndex){
                   return String.format(c.formato(), m.invoke(objeto));
               }
           }
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return "";
   }
    @Override
    public String getColumnName(int coluna){
        for(Method m : classe.getDeclaredMethods()){
            Coluna c = m.getAnnotation(Coluna.class);
            if(c != null && c.posicao() == coluna ){
                return c.nome();
            }
        }
        return "";
    }
}

Como neste caso posso dizer à minha JTable que determinada coluna vai ser Integer ou Float?
Galera assim que eu acertar esses probleminhas e terminar esse exemplo que estou montando vou postar aqui no
forum devidamente comentado e explicado para ajudar amigos que lidam com esse problema.

M

Via Reflection também é possivel saber que tipo sera retornado.

public Object returnType(int col){
 for(Method m : classe.getDeclaredMethods()){  
             Coluna c = m.getAnnotation(Coluna.class);  
             if(c != null && c.posicao() == coluna ){  
                 return m.getReturnType();
             }  
         }  
return null;
}
L

Coloca isso aqui no seu TableModel para vê se resolve…

public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
7

Corrigam-me caso esteja errado, mais neste caso pra determinar se sua coluna vai ser Integer ou Float é no metodo

public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); }

No seu caso lá no método

public Object getValueAt(int rowIndex, int columnIndex) { try{ Object objeto = lista.get(rowIndex); for(Method m : classe.getDeclaredMethods()){ Coluna c = m.getAnnotation(Coluna.class); if(c != null && c.posicao() == columnIndex){ return String.format(c.formato(), m.invoke(objeto)); // Aqui vc ta declarando que todos os tipos serão transformados em String } } }catch(Exception ex){ ex.printStackTrace(); } return ""; }

Veja se é este caso, de vc está transformando todos os tipos em String.
Voce poderia retorna o c.formato().getClass, ou não? Pois o que importa pra vc não é o tipo? Poderia fazê-lo em outro metodo talvez…

L

É isso mesmo 71C4700… vc está certo.

Tem que implementar uma logica que já retorne com o tipo desejado, pois, hj ele retorna tipo String.Mas o método public Class getColumnClass(int c) deve continuar,pois, é ele que informa ao jtabel para qual tipo converter,já que o método getValuAt(int c) retorna Object…

Pense em alguma lógica para retornar com o tipo apropriado… vc pode utilizar o método que o nosso amigo Mark_Ameba te passou, para isso.

Se não conseguir avisa.

Abraços.

J

Galera creio que o problema esta aqui oh, na criação da minha annotation:

package comum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Coluna {
//vamos utilizar esta annotation para pegar o nome da coluna,posicao no jtable e o formato que queremos mostrar 
	String nome();
	int posicao();
	String formato() default "%s";  // Como eu faria para esse formato ser o formato que eu desejasse? onde eu encontro esses fomatos?
}
no meu bean eu faço assim oh:
package bean;

import comum.Coluna;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

/**
 *
 * @author rh
 */
@Entity
@Table(name = "cliente")
@NamedQueries({@NamedQuery(name = "Cliente.findAll", query = "SELECT c FROM Cliente c"), @NamedQuery(name = "Cliente.findByCliCodigo", query = "SELECT c FROM Cliente c WHERE c.cliCodigo = :cliCodigo"), @NamedQuery(name = "Cliente.findByCliNome", query = "SELECT c FROM Cliente c WHERE c.cliNome = :cliNome"), @NamedQuery(name = "Cliente.findByCliCpf", query = "SELECT c FROM Cliente c WHERE c.cliCpf = :cliCpf"), @NamedQuery(name = "Cliente.findByCliIdade", query = "SELECT c FROM Cliente c WHERE c.cliIdade = :cliIdade")})
public class Cliente implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "cli_codigo")
    private Integer cliCodigo;
    @Basic(optional = false)
    @Column(name = "cli_nome")
    private String cliNome;
    @Basic(optional = false)
    @Column(name = "cli_cpf")
    private String cliCpf;
    @Basic(optional = false)
    @Column(name = "cli_idade")
    private int cliIdade;
    @JoinColumn(name = "empr_codigo", referencedColumnName = "empr_codigo")
    @ManyToOne(optional = false)
    private Empresa emprCodigo;

    public Cliente() {
    }

    public Cliente(Integer cliCodigo) {
        this.cliCodigo = cliCodigo;
    }

    public Cliente(Integer cliCodigo, String cliNome, String cliCpf, int cliIdade) {
        this.cliCodigo = cliCodigo;
        this.cliNome = cliNome;
        this.cliCpf = cliCpf;
        this.cliIdade = cliIdade;
    }
    @Coluna(posicao=0,nome="Código")//posicao no jtable e o nome para exibir na coluna (Aqui eu deveria informar que é Integer)
    public Integer getCliCodigo() {
        return cliCodigo;
    }

    public void setCliCodigo(Integer cliCodigo) {
        this.cliCodigo = cliCodigo;
    }
    @Coluna(posicao=1,nome="Nome")//posicao no jtable e o nome para exibir na coluna
    public String getCliNome() {
        return cliNome;
    }

    public void setCliNome(String cliNome) {
        this.cliNome = cliNome;
    }
    @Coluna(posicao=2,nome="CPF")//posicao no jtable e o nome para exibir na coluna
    public String getCliCpf() {
        return cliCpf;
    }

    public void setCliCpf(String cliCpf) {
        this.cliCpf = cliCpf;
    }
    @Coluna(posicao=3,nome="Idade")//posicao no jable e o nome para exibir na coluna
    public int getCliIdade() {
        return cliIdade;
    }

    public void setCliIdade(int cliIdade) {
        this.cliIdade = cliIdade;
    }
    @Coluna(posicao=4,nome="Empresa")//posicao no jable e o nome para exibir na coluna
    public Empresa getEmprCodigo() {
        return emprCodigo;
    }

    public void setEmprCodigo(Empresa emprCodigo) {
        this.emprCodigo = emprCodigo;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (cliCodigo != null ? cliCodigo.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Cliente)) {
            return false;
        }
        Cliente other = (Cliente) object;
        if ((this.cliCodigo == null && other.cliCodigo != null) || (this.cliCodigo != null && !this.cliCodigo.equals(other.cliCodigo))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "bean.Cliente[cliCodigo=" + cliCodigo + "]";
    }

}
Eu comentei no primeiro codigo o que eu considero errado: mas no codigo abaixo eu tbm estou transformando o valor em String! e quando eu coloquei somente o
public Object getValueAt(int rowIndex, int columnIndex) {
       try{
           Object objeto = lista.get(rowIndex);
           for(Method m : classe.getDeclaredMethods()){
               Coluna c = m.getAnnotation(Coluna.class);
               if(c != null && c.posicao() == columnIndex){
//                   return String.format(c.formato(), m.invoke(objeto)); // Como eu faria pra ele mostrar na tabela o valor no formato que ele vier sem usar o String.format(c.formato(), m.invoke(objeto))?
                   return c.formato().getClass();  // Ele esta jogando os valores nas colunas assim oh: "class java.lang.String"
               }
           }
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return "";
   }
7
Uma solução seria adicionar outra tag a sua anottaion ai voce declararia o tipo e no metodo getClass() vc faria algo assim
public Class getColumnClass(int c) {  
   try{  
            Object objeto = lista.get(rowIndex);  
            for(Method m : classe.getDeclaredMethods()){  
                Coluna c = m.getAnnotation(Coluna.class);  
                if(c != null && c.posicao() == columnIndex){  
                    return c.classe(); 
                }  
            }  
        }catch(Exception ex){  
            ex.printStackTrace();  
        }  
        return "";  }
E na sua anotação
package comum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Coluna {
//vamos utilizar esta annotation para pegar o nome da coluna,posicao no jtable e o formato que queremos mostrar 
	String nome();
	int posicao();
	String formato() default "%s";  // Como eu faria para esse formato ser o formato que eu desejasse? onde eu encontro esses fomatos?
       Class classe();
}

Veja se resolve, mas acredito que da forma que o Mark postou seja a melhor maneira...

J
Salve Galera do Guj :-o : Eu fundi a ideia do Mark_Ameba com a do 71C4700 e deu certo. Já esta quase pronto! Ficou assim oh no meu modelo:
public Class getColumnClass(int c) {
        for (Method m : classe.getDeclaredMethods()) {
            Coluna col = m.getAnnotation(Coluna.class);
            if (col != null && col.posicao() == c) {
                return m.getReturnType();
            }
        }
        return null;
    }
e no metodo getValueAt observer o return
public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            Object objeto = lista.get(rowIndex);
            for (Method m : classe.getDeclaredMethods()) {
                Coluna c = m.getAnnotation(Coluna.class);
                if (c != null && c.posicao() == columnIndex) {
                    return m.invoke(objeto);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }
A minha Annotation ficou assim oh:
package comum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Coluna {


//vamos utilizar esta annotation para pegar o nome da coluna,posicao no jtable e o formato que queremos mostrar
	String nome();
	int posicao();
    Class formato();
}
dai no bean é so passar o tipo do dado que eu quero assim oh:
@Coluna(posicao=0,nome="Codigo", formato=Integer.class)//posicao no jtable e o nome para exibir na coluna
    public Integer getCliCodigo() {
        return cliCodigo;
    }

   
    @Coluna(posicao=1,nome="Nome", formato=String.class)//posicao no jtable e o nome para exibir na coluna
    public String getCliNome() {
        return cliNome;
    }
7

Observe que vc nao utiliza o formato() de sua anotação…Então VC ta seguindo a ideia do Mark_Ameba…

Que acho que seja melhor…

L

71C4700:
Observe que vc nao utiliza o formato() de sua anotação…Então VC ta seguindo a ideia do Mark_Ameba…

Que acho que seja melhor…

Então Josimarsis, acho melhor vc verificar o código novamente heim, pois, realmente o codigo não está usando a tag formato() e além disso vc testou este código quando o tipo retornado for uma Data(por exemplo Calendar)?. Por que quando eu criei este TableModel(e vc agora está adaptando as suas necessidades), eu não tinha necessidade de saber o tipo retornado, então, eu retornava tudo em String mesmo e usei esta linha String.format(c.formato(), m.invoke(objeto)); para retornar uma data formatada em String.Quando eu anotei no PessoaBean o formato de apresentação era com este objetivo:

@Coluna(posicao=5,nome="Data Nascimento", formato="%1$Td/%1$Tm/%1$TY ")
	public Calendar getDataNascimento()

E quando for número como está apresentando(está assim: ###.###,### ou assim: ###,###.###)?.

Abraços.

L

josimarsis, já que vc quer criar mais uma tag na annotetion, então faz assim: o que for string continua da mesma forma que estava antes e quando nao for retorna o valor direto. E o método getColumnClass(int c) saberá o tipo.

public Object getValueAt(int rowIndex, int columnIndex) { try{ Object objeto = lista.get(rowIndex); for(Method m : classe.getDeclaredMethods()){ Coluna c = m.getAnnotation(Coluna.class); if(c != null && c.posicao() == columnIndex){ if(c.type == String.class){ return String.format(c.formato(), m.invoke(objeto)); }else{ return m.invoke(objeto); } } }catch(Exception ex){ ex.printStackTrace(); } return ""; }

public Class getColumnClass(int c) {     
      return getValueAt(0, c).getClass();     
}
package comum;   
  
import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   
  
  
@Target(ElementType.METHOD)   
@Retention(RetentionPolicy.RUNTIME)   
public @interface Coluna {   
  
    String nome();   
    int posicao();   
    String formato();   
    Class type();
} 


Abraços.
M

Agora que esta quase pronto… se quiser pode dar uma olhada nesse TableModel que postei no CodeProject.

http://www.codeproject.com/KB/java/objecttablemodel.aspx

Postado como artigo… me desculpe mas não sei escrever artigos direito e esse ainda foi em inglês.

Quando tinha pensado parecia uma boa idéia e tava pensando em colocar um artigo no GUJ também. Se possivel queria que dessem um feedback ^^

J

Galera, estou tentando fazer o seguinte: Quero que quando uma coluna for selecionada ela mude de cor (mais somente ela).

estou utilizando este metodo:

public void AlteraCorColuna() {
          jtTabela.repaint();
          TableColumn coluna = jtTabela.getColumnModel().getColumn(jtTabela.getSelectedColumn());
          coluna.setCellRenderer(new ColorColumnRenderer(Color.orange, Color.blue));
}

Eu criei este TableCellRenderer:

class ColorColumnRenderer extends DefaultTableCellRenderer {

        Color bkgndColor, fgndColor;

        public ColorColumnRenderer(Color bkgnd, Color foregnd) {
            super();
            bkgndColor = bkgnd;
            fgndColor = foregnd;

        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                cell.setBackground(bkgndColor);
                cell.setForeground(fgndColor);
            return cell;
        }
    }

Mas esta ocorrendo o seguinte eu clico na coluna ela muda a cor, quando eu clico em outra ele pinta tbm e assim consecutivamente. Eu necessitaria que ficasse pintada so a coluna que eu selecionar.
A Tabela esta pronto e so falta eu acertar isso! Resolvendo isso vou preparar um artigo como Mark_Ameba me aconselhou e postar o codigo fonte.

M

Assim como o TableModel NÃO extenda DefaultTableCellRenderer. Implemente TableCellRenderer.

J

Mark_Ameba, eu confesso que não consegui entender o TableCellRenderer e creio que muita gente tem dificuldades
com ele. Seria possivel vc fazer uma breve explicação? Pois não estou conseguindo pintar somente a coluna selecionada e isso se deve creio eu à falta de entendimento da classe TableCellRenderer. Se vc tiver algum exemplo!

L

Coloca seu Jtabel para selecionar apenas uma linha:

jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

Se vc quiser colocar um efeito zebrado no grid usa este CellRenderer aqui:

class MyCellRenderer extends DefaultTableCellRenderer {
        private Color whiteColor = new Color(254, 254, 254);
        private Color alternateColor = new Color(204, 204, 204);
        private Color selectedColor = new Color(61, 128, 223);

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean selected, boolean focused, int row,
                int column) {

            super.getTableCellRendererComponent(table, value, selected, focused, row, column);

            Color bg;
            if (!selected)
                bg = (row % 2 == 0 ? alternateColor : whiteColor);
            else
                bg = selectedColor;

            setBackground(bg);
            setForeground(selected ? Color.white : Color.black);

          /*  if (value instanceof ImageIcon) {
                setIcon((ImageIcon) value);
                setText("");
            } else
                setIcon(null);
          */
            return this;
        }
    }

Abraços

L

Lintz_net:

Coloca seu Jtabel para selecionar apenas uma linha:

jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

Se vc quiser colocar um efeito zebrado no grid usa este CellRenderer aqui:

class MyCellRenderer extends DefaultTableCellRenderer {
        private Color whiteColor = new Color(254, 254, 254);
        private Color alternateColor = new Color(204, 204, 204);
        private Color selectedColor = new Color(61, 128, 223);

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean selected, boolean focused, int row,
                int column) {

            super.getTableCellRendererComponent(table, value, selected, focused, row, column);

            Color bg;
            if (!selected)
                bg = (row % 2 == 0 ? alternateColor : whiteColor);
            else
                bg = selectedColor;

            setBackground(bg);
            setForeground(selected ? Color.white : Color.black);
            /*
            if (value instanceof ImageIcon) {
                setIcon((ImageIcon) value);
                setText("");
            } else
                setIcon(null);
           */
            return this;
        }
    }

Abraços

Ahh esqueci… vc precisa setar o jtable com o seu renderer:

jTable.setDefaultRenderer(Object.class, new MyCellRenderer());
L
josimarsis:
Galera, estou tentando fazer o seguinte: Quero que quando uma coluna for selecionada ela mude de cor (mais somente ela).

estou utilizando este metodo:

public void AlteraCorColuna() {
          jtTabela.repaint();
          TableColumn coluna = jtTabela.getColumnModel().getColumn(jtTabela.getSelectedColumn());
          coluna.setCellRenderer(new ColorColumnRenderer(Color.orange, Color.blue));
}

Eu criei este TableCellRenderer:

class ColorColumnRenderer extends DefaultTableCellRenderer {

        Color bkgndColor, fgndColor;

        public ColorColumnRenderer(Color bkgnd, Color foregnd) {
            super();
            bkgndColor = bkgnd;
            fgndColor = foregnd;

        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                cell.setBackground(bkgndColor);
                cell.setForeground(fgndColor);
            return cell;
        }
    }

Mas esta ocorrendo o seguinte eu clico na coluna ela muda a cor, quando eu clico em outra ele pinta tbm e assim consecutivamente. Eu necessitaria que ficasse pintada so a coluna que eu selecionar.
A Tabela esta pronto e so falta eu acertar isso! Resolvendo isso vou preparar um artigo como Mark_Ameba me aconselhou e postar o codigo fonte.

Josimaris, vc precisa colocar uma lógica no seu método getTableCellRendererComponent.Quando for a linha selecionada vc pinta de uma cor, senão vc pinta de outra cor...

if (isSelected)//se estiver selecionado vc pinda de uma cor
     cell.setBackground("cor selecionada");
     cell.setForeground("cor selecionada");
else//se nao estiver selecionado vc pinta de outra cor.
    cell.setBackground("outra cor");
    cell.setForeground("outra cor");

Abraços.

J

E como eu faria caso eu queria pintar somente a coluna que eu clicar?

L

Ahhh desculpa cara, mas não tinha prestado atenção que era no click de uma unica celula. Mas é a mesma lógica: a coluna que vc selecionou vc pinta, senao for a celula que vc selecinou vc precisa voltar a cor que estava antes.

Isso aqui vai te ajudar: http://life.csu.edu.au/java-tut/uiswing/components/table.html e um exemplo de código do que Mark_Ameba falou(segue em anexo).

Abraços.

M

Nossa… quantas vezes eu vi Mark_Ameba escrito sendo comentado nesse tópico.

Eu ia implementar os exemplos do CellRendered mas não acho que precise mais.

7

O nosso caro amigo Lintz_net, solucionou o problema.

Na classe anexo ao seu post anterior, tem um exemplo que 'colori' a celula a qual o mouse esta por cima.

Para uma adaptação acredito que :

1. Ao inves de capturar a coluna selecionada, pois podem existir varias, usa
table.columnAtPoint(e.getPoint());
2. Quando for alterar o codigo da classe Estudos,substitui o metodo getTableCellRendererComponent, por esse.
public Component getTableCellRendererComponent(
                    JTable table, Object value,
                    boolean isSelected, boolean hasFocus,
                    int row, int column) {
                if (column == coluna) {
                    this.setBackground(Color.yellow);

                } else {
                    this.setBackground(table.getBackground());
                }

                this.setText(value.toString());
                return this;
            }

Agora é só observar e verificar como esta se comportando o codigo, veja que agora ele colore toda a linha a qual o mouse esta sobreposto. Altere o evento pro click e acredito que funcione

J

Galera Boa noite. Com as ideias e exemplos que vcs me deram eu consegui fazer o que eu queria que era zebrar a tabela e mudar a cor de uma celula quando selecionada e cheguei a pensar que enfim tinha concluido minha Tabela Dinamica. Porém realizando alguns testes percebi que quando minha tabela possui colunas de valores Integer, Float ou Double o CellRenderer que eu fiz simplismente não funciona. Se eu mando os dados para a Tabela como String o RowSorter não funciona corretamente para as colunas do tipo (Integer, Float e Double).

Annotation criada para mapear os campos que quero mostrar na consulta:
package comum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Coluna {
//vamos utilizar esta annotation para pegar o nome da coluna,posicao no jtable e o formato que queremos mostrar
	String nome();
	int posicao();
    Class formato();
}
Metodo do modelo "que pelo que eu entendi" é responsavel por preencher as colunas (classe: TableModelPadraoParaBean):
@Override
    public Class getColumnClass(int c) {
        for (Method m : classe.getDeclaredMethods()) {
            Coluna col = m.getAnnotation(Coluna.class);
            if (col != null && col.posicao() == c) {
                return m.getReturnType();
            }
        }
        return null;
    }
Bean definido a partir da view criada no banco de dados para ser mostrado na consulta. Classe: (ViewTeste). Segue a baixo o trecho do codigo onde eu seto os valores definidos na Annotation criada.
@Coluna(posicao=0,nome="Codigo", formato=Integer.class)//posicao no jable e o nome para exibir na coluna
    public Integer getCliCodigo() {
        return cliCodigo;
    }
Classe MyCellRenderer responsavel por zebar e permitir o efeito de seleção da Tabela. Essa Classe se encontra dentro da Classe FrmConsulta.
class MyCellRenderer extends DefaultTableCellRenderer {

        private Color whiteColor = new Color(254, 254, 254);
        private Color alternateColor = new Color(123, 193, 255);
        private Color selectedColor = new Color(61, 128, 223);

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean selected, boolean focused, int row,
                int column) {

            super.getTableCellRendererComponent(table, value, selected, focused, row, column);

            Color bg = null;
            // Testa se não existe celula selecionada, se não existir zebra a tabela
            if (!selected) {
                bg = (row % 2 == 0 ? alternateColor : whiteColor);
            } // Testa se existe celula selecionada, se exitir tambem zebra a tabela
            else {
//               bg = selectedColor;
                bg = (row % 2 == 0 ? alternateColor : whiteColor);
            }
            // Pinta a celula selecionada de amarelo
            if (row == table.getSelectedRow() && column == table.getSelectedColumn()) {
                bg = Color.YELLOW;
            }
            setBackground(bg);
//            setForeground(selected ? Color.red : Color.black);
           
            return this;
        }
    }
Segue anexo tbm o projeto feito no netbeans e o scrip do banco mysql que está dentro da pasta do projeto.
L

Josimarsis, este problema é classico e eu já tive tbm. :lol: E acho que vc pode resolver colcando setDefaultRenderer para Integer e Double.Onde vc seta o seu renderer?Deve ter algo assim, né:

jTabela.setDefaultRenderer(Object.class, new MyCellRenderer());

Coloque mais duas linhas:

jTabela.setDefaultRenderer(Integer.class, new MyCellRenderer());
 jTabela.setDefaultRenderer(Double.class, new MyCellRenderer());

E veja se funfa…se funfar avisa.Senão funfar eu vejo o seu código para vê se consigo te ajudar.

Abraços.

J

Lintz, realmete funcionou mas eu não consegui entender o porque! Eu criei esse meto e chamo ele no construtor
da minha Tela de Consulta simplismente.

public void AlteraCellRenderer() { jtTabela.setDefaultRenderer(Object.class, new MyCellRenderer()); jtTabela.setDefaultRenderer(Integer.class, new MyCellRenderer()); jtTabela.setDefaultRenderer(Double.class, new MyCellRenderer()); jtTabela.setDefaultRenderer(Float.class, new MyCellRenderer()); }
Teria como vc explicar?
O unico problema que esta ocrrendo é esse Exception quando clico em uma celula que possui os tipos Double e Float

Exception occurred during event dispatching:
java.lang.NumberFormatException: For input string: “10.0”

Mas uma vez eu agradeço a atenção. Realmete estou aprendendo muito com esse topico. Gostaria de saber tbm se vc conheçe algum livro que fale sobre os Models e Renderes tanto do JTable quanto do JComboBox e outros componentes que usam modelo, Estou fascinado com o que eles podem proporcionar, encontrei muito material legal na net mas são meio vagos. Quero realmente entender essas classes alguma dica?

L

Então, pega todos os topicos que eu te passei neste post que foi onde eu aprendi…quando eu nao sei sobre alguma coisa eu procuro tudo na net ou procuro no javadoc.Não precisa de livro…outra forma de vc aprender é ler bastante aqui no guj, principalmente mensagens e dicas que o ViniGodoy sempre posta aqui no guj.Realmente o cara conhece muito sobre Swing…

Abraços.

J

Outro problema que encontrei é o seguinte: Não consigo pegar o getValueAt correto de uma celula quando eu utilizo o RowSorter ou o RowFilter o problema esta aqui, mas não consegui resolver.

// lista (List<?> de beans) public Object getValueAt(int rowIndex, int columnIndex) { try { Object objeto = lista.get(rowIndex); for (Method m : classe.getDeclaredMethods()) { Coluna c = m.getAnnotation(Coluna.class); if (c != null && c.posicao() == columnIndex) { return m.invoke(objeto); } } } catch (Exception ex) { ex.printStackTrace(); } return ""; }
Neste codigo eu pego o valor da celula pelo index da minha lista de beans, sendo assim quando eu aplico o RowSorter ou o RowFilter o meu getValueAt não funciona como esperado.

L

Josimarsis, vc não está usando os códigos que te passei, né?.Faz um teste usando os códigos que eu te passei… acredito que um dos problemas que vc tem vai resolver.

public Object getValueAt(int rowIndex, int columnIndex) {       
          try{       
              Object objeto = lista.get(rowIndex);       
              for(Method m : classe.getDeclaredMethods()){       
                  Coluna c = m.getAnnotation(Coluna.class);       
                  if(c != null && c.posicao() == columnIndex){       
                      if(c.type == String.class){  
                         return String.format(c.formato(), m.invoke(objeto));    
                     }else{  
                        return m.invoke(objeto);    
                    }  
             }       
         }catch(Exception ex){       
             ex.printStackTrace();       
         }       
         return "";       
    }   


//----------------------------------


 public Class getColumnClass(int c) {       
       return getValueAt(0, c).getClass();       
 } 



//----------------------------------


 package comum;     
     
 import java.lang.annotation.ElementType;     
 import java.lang.annotation.Retention;     
 import java.lang.annotation.RetentionPolicy;     
 import java.lang.annotation.Target;     
     
     
 @Target(ElementType.METHOD)     
 @Retention(RetentionPolicy.RUNTIME)     
 public @interface Coluna {     
     
     String nome();     
     int posicao();     
     String formato();     
     Class type();  
 }

Abraços

M

Só uma coisa. A cada getValueAt a sua classe vai rodar a classe inteira procurando o método para pegar o valor.

Imagina uma tabela de 15 linhas apenas e 4 colunas. Isso já vai chamar o método getValueAt 60 vezes.
Seria bom voce pensar em algo melhor nessa parte.

Alguém viu o artigo que postei?

Nesse artigo tem o código e exemplos. Tudo que estão fazendo já esta pronto.

L

Bom, eu já usei desda maneira em alguns códigos e nunca tive problema. Posso afirmar que está muito bem testado…

Mas fica a dica ai para o josimarsis…

Abraços.

J
Olá galera estou com o seguinte problema: Não consigo pegar o getValueAt correto da minha JTable quando utilizo o RowSorter ou o RowFilter. Segue abaixo a classe que estou utilizando como modelo:
package comum;

import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class TableModelPadraoParaBean extends AbstractTableModel {

    private Class<?> classe;
    private List<?> lista;

    public TableModelPadraoParaBean(List<?> linhas) {
        this.setLinhas(linhas);
        if (linhas != null) {
            this.classe = linhas.get(0).getClass();
        }
    }

    public int getRowCount() {
        if (lista != null) {
            return lista.size();
        } else {
            return 0;
        }
    }

    public int getColumnCount() {
        int colunas = 0;
        for (Method m : classe.getDeclaredMethods()) {
            if (m.isAnnotationPresent(Coluna.class)) {
                colunas++;
            }
        }
        return colunas;
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return false;
    }

    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    public void setLinhas(List<?> linhas) {
        this.lista = linhas;
        fireTableDataChanged();
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            Object objeto = lista.get(rowIndex);
            for (Method m : classe.getDeclaredMethods()) {
                Coluna c = m.getAnnotation(Coluna.class);
                if (c != null && c.posicao() == columnIndex) {
                    if(c.formato() == Date.class){
                        return ConverteDataParaString(ConverteDataParaBanco(m.invoke(objeto).toString()));
                    }
                        return m.invoke(objeto);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }

    @Override
    public String getColumnName(int coluna) {
        for (Method m : classe.getDeclaredMethods()) {
            Coluna c = m.getAnnotation(Coluna.class);
            if (c != null && c.posicao() == coluna) {
                return c.nome();
            }
        }
        return "";
    }

     public String ConverteDataParaString(Date date) throws ParseException{
           DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
           String data = formatter.format(date);
           return data;
    }
    public Date ConverteDataParaBanco(String data) throws ParseException{
           DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
           java.sql.Date date = new java.sql.Date(formatter.parse(data).getTime());
           return date;
    }
}
Metodo action onde eu crio o RowSorter e o RowFilter
private void jtfFiltroKeyReleased(java.awt.event.KeyEvent evt) {                                      
        // cria um TableRowSorter a partir do TableModelPadraoParaBean
        final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(new TableModelPadraoParaBean(getLista()));
        // Adiciona o objeto TableRowSorter à Tabela
        jtTabela.setRowSorter(sorter);
        String text = jtfFiltro.getText();
        if (text.length() == 0) {
            sorter.setRowFilter(null);
        } else {
            try {
                // Cria um Filtro de pesquisa com base na coluna selecionada
                sorter.setRowFilter(RowFilter.regexFilter('^' + text, getColuna()));
                setStatusParaAtualizacao(false);

            } catch (PatternSyntaxException pse) {
                System.err.println("Erro");
            }
        }
    }
Metodo action responsavel por setar a coluna de filtragem e setar o codigo que esta na primeira coluna que sera utilizado para efetuar as consultas necessarias para realizar as operações de Alteração e Deleção.
private void jtTabelaMouseClicked(java.awt.event.MouseEvent evt) {                                      
        if (evt.getClickCount() == 1 && jtTabela.getSelectedRow() >= 0) {
            // Seta o indice da coluna selecionada para o RowSorter e RowFilter
            setColuna(jtTabela.getSelectedColumn());
            /* Seta o Codigo da primeira coluna
            para realizar as consultas necessarias à alteração e exclusão de dados*/
            setCodigoPesquisado(Integer.valueOf(((TableModelPadraoParaBean) jtTabela.getModel()).getValueAt(jtTabela.getSelectedRow(), 0).toString()));
            setStatusParaAtualizacao(true);
        }
    }
Funciona perfeitamente desde que eu não utilize o RowSorter ou o RowFilter. Alguem tem uma dica? Grato!
L

Josimarsis, eu não tinha usado este RowSorter até então.
Não sabia como funcionava, então achei melhor ler sobre ele e acabei descobrindo o seu problema:

http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

Quando um jtable usa um sorter, os dados que são vistos na view do jtable podem estar em uma ordem diferente do que o especificado pelo modelo(TableModelPadraoParaBean ) de dados, e pode não incluir todos os registros especificados pelo modelo de dados. Os dados que o usuário vê na verdade é conhecido como wiew, e tem seu próprio conjunto. JTable fornece métodos que converte de modelo para view:

  • convertColumnIndexToView
  • convertRowIndexToView
  • convertColumnIndexToMode
  • convertRowIndexToModel

Coloque este código e faça um teste…

int viewRow = table.getSelectedRow();
              if (viewRow < 0) {
                  //Selection got filtered away.
                   System.out.println("");
               } else {
                     int modelRow = table.convertRowIndexToModel(viewRow);
                      System.out.println( String.format("Selected Row in view: %d. " + "Selected Row in model: %d.",viewRow, modelRow));
                }

Abraços.

J

Olá comunidade GUJ, Gostaria primeiramente de agradecer todos que me ajudaram neste tópico em especial ao Lintz. E afim de explicar a solução proposta e compartilhar o conhecimento adquirido estou disponibilizando o código fonte comentado bem como uma explicação da idéia envolta no desenvolvimento desta JTable Dinâmica. Obs: o script do banco de dados se encontra dentro da pasta do projeto

[b] JTable Dinâmica[/b]

O intuito era desenvolver uma JTable de consulta única que proporcionasse mecanismos de filtragem e ordenação e funcionasse para o sistema todo, e desta forma diminuir consideravelmente o tempo de desenvolvimento pois se levarmos em consideração que um sistema tem N telas e para cada tela temos uma consulta então teríamos N telas de consulta.
A idéia da JTable desenvolvida é definir consultas prontas em Views no banco de dados e criar Dao?s persistentes a partir destas Views, sendo assim a consulta seria realizada em cada view especifica. Você deve estar se perguntando o porquê da view ao invés da própria entidade persistente mapeada no banco de dados? A resposta é: quando criamos uma veiw ?Temos uma tabela virtual no banco de dados definida por comandos SQL? desta forma podemos recuperar campos com chave estrangeira de outra tabela e assim mapear estes campos no Dao criado a partir da view por intermédio de uma Annotation e assim lê-la dinamicamente utilizando Reflection.

[b]Tecnologias Utilizadas[/b]
JPA ? Java Persistence API;

Hibernate;

Banco de Dados ? Mysql 5;

Netbeans 6.5;
[b]Dicas para Entendimento[/b]

Para ser possível realizar a construção deste projeto foi necessário estudar:
Reflection ? Necessário para ler as Annotations ;
AbstractTableModel ? Pois Foi criado um modelo TableModel capaz de atender as necessidades exigidas.
Annotations ? Necessárias para mapear o Dao.
DefaultTableCellRenderer ? Para possibilitar os efeitos de seleção e o efeito zebrado da Tabela.

M

Muito legal.

Uma coisa que reparei olhando o código da sua tabela. Não é possivel ver apenas algumas colunas da tabela apenas todas que estiverem marcadas. Também não é possivel ver as variaveis das variaveis da classe.
Também não é possivel ver classes que voce nao tem acesso ao código fonte. Por exemplo a classe Calendar.
Aquilo de Date foi uma gambiarra por que a pessoa pode querer mudar o formato.

Eu já tinha resolvido essas questões e tinha colocado o link da que postei.

J

Mark_Ameba, eu sinceramente ja tinha baixado seu codigo e vi seu artigo e infelizmente não consegui entende-lo, por isso continuei com a construção da Tabela mesmo apos vc ter disponibilizado o codigo da que vc fez. Sou iniciante em java e gosto de programar mais como vc viu ainda não sou um profissional e meu ingles é muito basico tanto que ja estou procurando um meio de me matricular em um curso de ingles. Vou começar a desenvolver uma pequena aplicação e tive a ideia de tentar fazer algum mecanismo onde eu pudesse ter uma tabela dinamica ou seja uma JTable pra o sistema todo. Tive dificuldades em pegar campos que são chave estrangeira por isso utilizei a veiw. Utilizando seu modelo eu consigo recuperar dados de uma chave estrangeira?

Não sei se é pedir d+ mas acho que seria de enorme valia tanto pra mim quanto pra varias pessoas que enfrentam esse problema principamente os novatos. Seria possivel vc explicar as principais funcionalidades da sua tabela bem como os principais parametros para que ela funcione ou documenta - la escrito em Portugues?

Obrigado.

M

Ok. Vou traduzir o artigo que fiz. Eu só tinha feito em ingles pra ver se a ideia era aceita pela comunidade.

J

Ok! Creio que o entendimento da sua ideia e do seu codigo fonte sera de grande valia para a comuindade.

M

Sei que demorei um tempo. Mas finalmente. Ta ai.

Desculpe a formatação. Mas ainda não sei como deixo o código identado.

J

Valeu Mark! vou conferir, com certeza será de grande valia à comunidade. Obrigado!

T

Tenho esse codigo do rowsorter queria que filtrasse por inteiros, tem como finalidade pesquisar os alunos cadastrados queria que pesquisar usando o codigo dos alunos!!
Que mudanças tenho que fazer no codigo Alguem poderia me ajudar??

codigo:

public class rowSorter extends Converter {

private JTable table;

public JTable getTable() {

return table;

}
public void setTable(JTable table) {

this.table = table;

}
public Object convertForward(Object value) {

return value.toString();

}

public Object convertReverse(Object mask) {
TableRowSorter sorter = new TableRowSorter(table.getModel());

sorter.setRowFilter(RowFilter.regexFilter("." + mask + "."));

return sorter;

}

}
Criado 27 de abril de 2009
Ultima resposta 20 de nov. de 2012
Respostas 55
Participantes 6