Pessoal,
Alguém tem um exemplo de uma classe que extenda de SwingWorker, onde ela alimente uma JTable adicionando linhas ou alterando algumas ?
Exemplo:
[code]…
this.rotina = new String[]{"Clientes", "Processando", String.valueOf(qtdRegistros), "0"};
this.modelo.addRow(this.rotina);
int linhas = this.modelo.getRowCount();
for (int i = 0; i < qtdRegistros; i++) {
this.rotina = new String[]{String.valueOf(i)};
this.modelo.setValueAt(this.rotina, linhas, 4); //desta forma não gera erro, mas pára aqui e não continua no restante do código.
…
}
…
[/code]
O exemplo abaixo funciona bem. Só que adiciona linhas para cada registro trabalhado (fato que não quero). Apenas citei para deixar claro que a rotina não está com problema no for{}
[code]…
this.rotina = new String[]{"Clientes", "Processando", String.valueOf(qtdRegistros), "0"};
this.modelo.addRow(this.rotina);
for (int i = 0; i < qtdRegistros; i++) {
this.rotina = new String[]{"Clientes", "Processando", String.valueOf(qtdRegistros), String.valueOf(i)};
this.modelo.addRow(this.rotina);
…
}
…
[/code]
Amigo,
Não seria interessante (e mais rápido) vc usar um AbstractTableModel , popular uma List com valores e adicioná-la ao model?
Olá luiz_renato,
Pois bem, estou utilizando o DefaultTableModel pelo seguinte:
esta JTable servirá apenas para posicionar o usuário de como está andamento de uma fila de processos. Trata-se de uma rotina de importação para diversos cadastros, onde aparecerá nesta tabela aquilo que está sendo processando ou que já finalizou. Algo semelhante ao que temos na rotina de exportação de dados de tabelas do MS Sql Server. Ao todo não passará de 20 importações.
Ex.:
Cadastro | Status | Total de Registros | Registro atual
Produtos | Finalizado | 89 | 89
Clientes | Processando | 1000 | 27 (este 27 é que vai sendo modificado dentro do for{} )
…
Sugestões ?
Deixa eu entender:
Cadastro | Status | Total de Registros | Registro atual
Produtos | Finalizado | 89 | 89
Clientes | Processando | 1000 | 27
são array´s de valores que vao preencher as jTable´s ?
É apenas uma jtable, preenchida com um array de string, ver this.rotina.
Aconselho usar TableModel mas vai uma dica (nao testei tente adaptar):
public class TableSwingWorker extends SwingWorker<Void, Void> {
private JTable table;
private int qtdRegistros;
private DefaultTableModel modelo;
private TableSwingWorker(int quant, JTable table) {
this.qtdRegistros = quant;
this.table = table;
}
@Override
protected Void doInBackground() throws Exception {
String [] rotina = new String[]{"Clientes", "Processando", String.valueOf(qtdRegistros),
"0"};
modelo = (DefaultTableModel) table.getModel();
modelo.addRow(rotina);
for (int i = 0; i < qtdRegistros; i++) {
rotina = new String[]{"Clientes", "Processando", String.valueOf(qtdRegistros),
String.valueOf(i)};
modelo.addRow(rotina);
}
return null;
}
}
luiz_renato,
Seu exemplo se assemelha com aquele que funciona, que mostrei no início. Ou seja, tem apenas adições de linhas. O que desejo é adicionar linhas e alterar o valor da coluna que mostra o número do registro atual.
Ex.:
Cadastro | Status | Total de Registros | Registro atual
Produtos | Finalizado | 89 | 89 // aqui já finalizou o processo de Produtos. Daí, é adiciona nova linha para Clientes, como segue abaixo:
Clientes | Processando | 1000 | 27 (este 27 é que vai sendo modificado dentro do for{} )
…
Simples,
Adapta a lógica dentroi do loop pra ao inves de adicionar , executar o setValue .
Eu compartilho da opinião do luiz_renato.
Use um TableModel particular onde você vai trabalhar com o objeto em questão, e não com células. Ao invés de “alterar o valor da coluna”, você muda o valor do seu objeto. É OO e mais prático, não? Me baseei no exemplo do luiz_renato:
[code]public class TableSwingWorker extends SwingWorker<void, void> {
private JTable table;
private SeuTableModel modelo;
private TableSwingWorker(JTable table, SeuTableModel modelo) {
setTable(table);
setModelo(modelo);
}
@Override protected void doInBackground() throws Exception {
// Supondo que você transformou aquele array de string em uma classe POJO.
Rotina rotina = new Rotina("Clientes", "Processando", modelo.getQuantidadeRegistros(), 0);
modelo.adicionarRegistro(rotina);
for (int I = 0; I < modelo.getQuantidadeRegistros(); ++I) {
Rotina rotina = new Rotina("Clientes", "Processando", modelo.getQuantidadeRegistros(), I);
modelo.adicionarRegistro(rotina);
}
}
}
[/code]
Assim, você não fica preocupado com cast, com buscar células na tabela nem nada do tipo.
luiz_renato,
mas é isto que está emperrando! Veja lá no início quando coloquei o :
esta linha acima não funciona! A aplicação pára e não surge erro algum no console, tampouco há alteração no JTable.
Nicolas Fernandes,
Agradeço sua participação, mas reforço a idéia de que não preciso adicionar linhas na JTable para cada passagem loop do for{}. Se eu fizer do jeito que ambos sugeriram, no JTable ocorrerá isto:
Cadastro | Status | Total de Registros | Registro atual
Produtos | Processando | 89 | 0
Produtos | Processando | 89 | 1
Produtos | Processando | 89 | 2
Produtos | Processando | 89 | 3
Produtos | Processando | 89 | 4
Produtos | Processando | 89 | 5
Produtos | Processando | 89 | 6
Produtos | Processando | 89 | 7
Produtos | Processando | 89 | 8
…
Produtos | Processando | 89 | 89
Clientes | Processando | 1000 | 0
Clientes | Processando | 1000 | 1
Clientes | Processando | 1000 | 2
Clientes | Processando | 1000 | 3
Clientes | Processando | 1000 | 4
Clientes | Processando | 1000 | 5
Clientes | Processando | 1000 | 6
…
Clientes | Processando | 1000 | 1000
Quando na realidade eu quero apenas:
Cadastro | Status | Total de Registros | Registro atual
Produtos | Finalizado | 89 | 89 // aqui já passou pelo processo
Clientes | Processando | 1000 | 27 // este 27 é o 27ª passagem loop do for. Ele é resultado do this.modelo.setValueAt(this.rotina, linhas, 4)
Entendi o que você precisa, vicentedepaula. Mas ainda continuo com a ideia do TableModel específico. Porquê? Porque você cria um evento onde você altera um objeto específico e avisa sua tabela que aquela linha foi alterada.
Vamos pensar…
Você pode ver se aquele objeto tem o status processando. Se ele estiver totalmente processado, você seta o status como Finalizado. Que tal?
Algo como:
// onde linha é o procedimento atual.
Rotina rotina = modelo.getItemAt(linha);
if (rotina.getLinhaProcessada() == rotina.getTotalRegistros()) {
rotina.setStatus(Status.PROCESSADO);
modelo.updateItemAt(rotina, linha); // dentro do update, você chama o fireTableRowsUpdated(row, row), para avisar que mudou o registro na tabela.
}
Entendi o que você precisa ou ainda estou voando longe? rs
Resolvido!
Como era um caso simples, mantive o uso de DefaultTableModel ao invés do AbstractTableModel.
O erro foi bobo!!! Vejamos:
Se na JTable desejo alterar o valor da 4ª coluna, o parâmetro de número da coluna deve ser 3 no .setValueAt. Havia colocado erroneamente 4.
O mesmo ocorreu para a linha.
Portanto, dentro do for{} coloquei:
Portanto, se congelou sem erro (era ao menos para surgir um array Index out of Bounds mas nem surgiu no console), dê uma olhada nas referências de linha e coluna passadas no setValuAt do modelo usado.
De qualquer forma, obrigado Nicolas Fernandes e luiz_renato pela atenção !!! 
Que bom que deu certo. 
Mas amigão, é o seguinte: eu penso que não existe caso simples e caso complexo para usar um modelo correto e bacana, sabe? Eu ainda acho que você deveria tentar adaptar o seu código para um AbstractTableModel, porque assim você faria o uso de objetos ao invés de linha/coluna. Fica mais “orientado”, saca?
Mas que bom que resolveu, era bobo mesmo. Às vezes a gente procura o complexo e acaba não percebendo o simples rs.
Nicolas,
O setValueAt do DefaultTableModel tem a mesma parametrização do setValueAt do AbstractTableModel. Ambos no primeiro parâmetro tratam de um objeto a ser enviado para a linha e coluna passados nos parâmetros seguintes.
Uso o AbstractTableModel em outras situações mais complexas. Mas nesta, onde a tabela não possui nenhuma coluna editável, apenas com caráter informativo, não vejo probs
