No método getColumnClass, o correto é Boolean.class (com b maiúsculo):
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == COL_SELECIONADO)
return Boolean.class;
return String.class;
}
O seu método isCellEditable também pode ser simplificado para:
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == COL_SELECIONADO;
}
Bem, vou abrir um projeto separado e testar essa implementação… Se der certo, menos mal, e posto aqui o resultado…
Agora, se não conseguir, realmente devo estar fazendo algo de errado em algum detalhe do código…
Mas vou fazer isso ainda agora.
Ok, depois de colocar a classe produto como indiquei, com “throw new IllegalArgumentException” e tudo mais, o erro continuou sendo NullPointerException? Ou mudou para IllegalArgumentException?
Continuou
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.JTable.prepareRenderer(JTable.java:5729)
at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2075)
at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1977)
at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1773)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
at javax.swing.JComponent.paintComponent(JComponent.java:763)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintChildren(JComponent.java:864)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JViewport.paint(JViewport.java:747)
at javax.swing.JComponent.paintChildren(JComponent.java:864)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5124)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
at javax.swing.RepaintManager.paint(RepaintManager.java:1220)
at javax.swing.JComponent._paintImmediately(JComponent.java:5072)
at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:803)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Outra coisa, ainda no seu getColumnClass(). Um dos campos do seu produto é do tipo integer, então, vc deveria retornar Integer.class para essa coluna. E outro é double, então, vc também deveria retornar Double.class.
Tela:
[code]package Visao;
import Controle.acaoPesquisa;
import Controle.utilitario;
import Modelo.pesquisaTableModel;
public class formPrecos extends javax.swing.JPanel {
public formPrecos() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
btnPesquisa = new javax.swing.JButton();
editPesquisa = new javax.swing.JTextField();
jScrollPane1 = new javax.swing.JScrollPane();
listaPalavras = new javax.swing.JList();
jPanel2 = new javax.swing.JPanel();
btnProximo = new javax.swing.JButton();
painelRolagemTabela = new javax.swing.JScrollPane();
tabelaResultado = new javax.swing.JTable();
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Pesquisa"));
btnPesquisa.setText("Pesquisar");
btnPesquisa.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnPesquisaActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(editPesquisa, javax.swing.GroupLayout.DEFAULT_SIZE, 623, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnPesquisa)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnPesquisa)
.addComponent(editPesquisa, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jScrollPane1.setViewportView(listaPalavras);
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Opções"));
btnProximo.setText("Mais Resultados");
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
.addContainerGap(446, Short.MAX_VALUE)
.addComponent(btnProximo)
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(btnProximo)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
tabelaResultado.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createTitledBorder("Resultado"), "Resultado"));
//tabelaResultado.setModel(new produtosTableModel(new ArrayList<Produto>()));
painelRolagemTabela.setViewportView(tabelaResultado);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(painelRolagemTabela, javax.swing.GroupLayout.DEFAULT_SIZE, 579, Short.MAX_VALUE)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(painelRolagemTabela, javax.swing.GroupLayout.PREFERRED_SIZE, 327, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane1))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>
private void btnPesquisaActionPerformed(java.awt.event.ActionEvent evt) {
if (editPesquisa.getText().trim().length() == 0){
utilitario.mensagemTela("Entre com o texto para pesquisar...",0);
} else {
btnPesquisa.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Visao/img/carregando.gif")));
editPesquisa.setText(editPesquisa.getText().trim().toUpperCase());
acaoPesquisa acao = new acaoPesquisa(editPesquisa.getText());
acao.start();
painelRolagemTabela.getVerticalScrollBar().setValue(tabelaResultado.getHeight());
painelRolagemTabela.getHorizontalScrollBar().setValue(tabelaResultado.getWidth());
}
}
public static void setPesquisa(pesquisaTableModel modelo){
tabelaResultado.setModel(modelo);
}
public static void setListaPalavras(String[] modelo){
listaPalavras.setListData(modelo);
}
public static void setBotaoPesquisar(String texto){
btnPesquisa.setText(texto);
btnPesquisa.setIcon(null);
}
// Variables declaration - do not modify
private static javax.swing.JButton btnPesquisa;
private javax.swing.JButton btnProximo;
private javax.swing.JTextField editPesquisa;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private static javax.swing.JList listaPalavras;
private javax.swing.JScrollPane painelRolagemTabela;
private static javax.swing.JTable tabelaResultado;
// End of variables declaration
}[/code]
Ação:
[code]public class acaoPesquisa extends java.lang.Thread {
private String sql = "";
private String texto = "";
public acaoPesquisa(String texto){
this.texto = texto;
}
@Override
public void run() {
String[] palavras = texto.split(Pattern.quote(" "));
for (int i = 0; i < palavras.length; i++){
sql += formataWhereSQL(palavras[i]);
if (i < (palavras.length - 1))
sql += " and ";
}
sql = "SELECT P.id_produtos, P.descricao, P.valor, P.loja, P.link, P.data_cad FROM produtos P WHERE ativo = 'SIM' AND ("+sql+");";
Conexao conexao = new Conexao();
conexao.Select(sql);
List<Produto> produtos = new ArrayList<Produto>();
while(conexao.lerSelect()){
Produto produto = new Produto(
conexao.lerColuna("id_produtos"),
conexao.lerColuna("descricao"),
conexao.lerColuna("valor"),
conexao.lerColuna("loja"),
conexao.lerColuna("link"),
conexao.lerColunaData("data_cad")
);
produtos.add(produto);
produto = null;
}
if(produtos != null){
pesquisaTableModel modelo = new pesquisaTableModel(produtos);
formPrecos.setPesquisa(modelo);
formPrecos.setListaPalavras(utilitario.identificaPalavras(modelo));
} else {
utilitario.mensagemTela("Nenhum produto foi encontrado!", 1);
}
conexao.fechaConn();
conexao = null;
formPrecos.setBotaoPesquisar("Pesquisar");
}
private String formataWhereSQL(String texto){
texto = "(upper(P.descricao) LIKE '%"+texto+"%') ";
return texto;
}
}
[/code]
Modelo:
public class pesquisaTableModel extends AbstractTableModel {
private static final int COL_SELECIONADO = 0;
private static final int COL_CODIGO = 1;
private static final int COL_PRODUTO = 2;
private static final int COL_VALOR = 3;
private static final int COL_LOJA = 4;
private static final int COL_CADASTRO = 5;
private List<Produto> produtos = new ArrayList<Produto>();
public pesquisaTableModel(List<Produto> produtos) {
this.produtos = produtos;
}
@Override
public int getRowCount() {
return produtos.size();
}
@Override
public int getColumnCount() {
return 6;
}
@Override
public String getColumnName(int columnIndex) {
if (columnIndex == COL_SELECIONADO) return "X";
if (columnIndex == COL_CADASTRO) return "Cadastro";
if (columnIndex == COL_CODIGO) return "Código";
if (columnIndex == COL_LOJA) return "Loja";
if (columnIndex == COL_PRODUTO) return "Produto";
if (columnIndex == COL_VALOR) return "Valor";
return "";
}
@Override
public Object getValueAt(int row, int column) {
Produto produto = produtos.get(row);
if (column == COL_SELECIONADO) return produto.estaSelecionado();
else
if (column == COL_CADASTRO) return produto.getCadastro();
else
if (column == COL_CODIGO) return produto.getCodigo();
else
if (column == COL_LOJA) return produto.getLink();
else
if (column == COL_PRODUTO) return produto.getProduto();
else
if (column == COL_VALOR) return produto.getValor();
return "";
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Produto valor = produtos.get(rowIndex);
if (columnIndex == COL_SELECIONADO) valor.setSelecionado(Boolean.valueOf(aValue.toString()));
}
@Override
public Class getColumnClass(int columnIndex) {
if (columnIndex == COL_SELECIONADO)
return boolean.class;
else
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == COL_SELECIONADO)
return true;
else
return false;
}
public Produto get(int row) {
return produtos.get(row);
}
}
Bean Produto:
[code]public class Produto implements Serializable {
private int codigo = 0;
private String produto = "";
private double valor = 0.0;
private String link = "";
private String loja = "";
private Date cadastro = new Date();
private boolean selecionado = false;
public Produto(String codigo, String produto, String valor, String link, String loja, Date cadastro){
this.codigo = Integer.valueOf(codigo);
if (produto == null)
throw new IllegalArgumentException("O produto não pode ser nulo!");
this.produto = produto;
this.valor = Double.valueOf(valor);
if (link == null)
throw new IllegalArgumentException("O link não pode ser nulo!");
this.link = link;
if (loja == null)
throw new IllegalArgumentException("A loja não pode ser nula!");
this.loja = loja;
if (cadastro == null)
throw new IllegalArgumentException("A data de cadastro não pode ser nula!");
this.cadastro = cadastro;
}
public Produto(){
}
public boolean estaSelecionado() {
return selecionado;
}
public void setSelecionado(boolean selecionado) {
this.selecionado = selecionado;
}
public String getLoja() {
return loja;
}
public void setLoja(String loja) {
if (loja == null)
throw new IllegalArgumentException("A loja não pode ser nula!");
this.loja = loja;
}
public Date getCadastro() {
return cadastro;
}
public void setCadastro(Date cadastro) {
if (cadastro == null)
throw new IllegalArgumentException("A data de cadastro não pode ser nula!");
this.cadastro = cadastro;
}
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getLink() {
return link;
}
public void setLink(String link) {
if (link == null)
throw new IllegalArgumentException("O link não pode ser nulo!");
this.link = link;
}
public String getProduto() {
return produto;
}
public void setProduto(String produto) {
if (produto == null)
throw new IllegalArgumentException("O produto não pode ser nulo!");
this.produto = produto;
}
public double getValor() {
return valor;
}
public void setValor(double valor) {
this.valor = valor;
}
}[/code]
[quote=ViniGodoy]Outra coisa, ainda no seu getColumnClass(). Um dos campos do seu produto é do tipo integer, então, vc deveria retornar Integer.class para essa coluna. E outro é double, então, vc também deveria retornar Double.class.
[/quote]
Ok, ficou:
public Class getColumnClass(int columnIndex) {
if (columnIndex == COL_SELECIONADO)
return boolean.class;
if (columnIndex == COL_CODIGO)
return int.class;
if (columnIndex == COL_VALOR)
return double.class;
if (columnIndex == COL_CADASTRO)
return Date.class;
else
return String.class;
}
E continuou o bendito do erro! :shock:
- Você não precisa definir variáveis que saem de escopo como null diretamente;
- Você não deve concatenar Strings em código SQL, pois isso insere uma falha grave de segurança, use o preparedStatement;
- Você não deve concatenar Strings em for. Use para isso um StringBuilder, monte a string, e só então chame o toString();
- Você deve fechar a conexão e os statements dentro de um finally.
- Sua lista de produtos nunca será nula. Nenhum produto será encontrado quando produtos.size() == 0
Claro que nada disso pode causar o erro que você está tendo. O mais provável é que seja o problema do getColumnClass().
Aproveitando, corrija o construtor do seu modelo. Você estragou ele quando adotou a sugestão do outro colega:
O correto é mesmo:
this.produtos = new ArrayList<Produto>(produtos);
Godoy, cara, nem sei o que falar, obrigado por dispor do seu tempo, vc está me ajudando muito, fico te devendo uma cerveja! 
Vou incrementar as suas dicas nesse projeto, e testar este processo de se não trabalhar com o DefaultTM em um outro código para me facilitar a encontrar o erro…
Mas desde já, estou super agradecido pela ajuda até o momento.
Depois posto aqui os meus novos códigos para ajudar o pessoal que também possui o mesmo problema.
Vou simplificar a coisa, como no exemplo do livro para fazer tudo funcionar primeiro, e então, eu passo o código dentro das minhas necessidade, ok.
Como eu falei, o correto não é:
int.class
E sim:
Integer.class
Não é:
boolean.class
E sim:
Boolean.class
E não é:
double.class
E sim:
Double.class
YES! Blz Godoy! Deu certo agora! Nada de erros, e a tabela veio à vida!
(Já estava implementado o meu outro projeto para campo de testes, e não vou mais…)
Agora é só arrumar a tabela visualmente (alinhar texto, definir tamanho de colunas e etc), mas isso eu vou deixar para um outro post, pois vou arrumar as coisas que faltam (e que orientou durante este problema), mas já me dou como satisfeito…
Por mim, o tópico está resolvido… (vou postar a nova implementação assim que terminar, com efeito de consulta para as pessoas que estão acompanhando este tópico, e encontraram o mesmo problema)
Novamente, um grande obrigado Godoy pela sua ajuda neste domingão!
(Obs: Alterei o nome do tópico para ficar mais específico conforme o problema encontrado - facilitando assim a busca.)
Como eu costumo a brincar, se o assunto é se livrar do DefaultTableModel, minha paciência virtualmente não tem limites. 8)
1 curtida