JTable x SwingWorker

3 respostas
alex

Pessoal,
estou lidando com um problema que me parece ser algo que estou usando de forma errada. O programa carrega os dados de uma tabela a partir de um banco de dados. Como o processo não é muito rápido, inseri um pequeno JFrame sem decoração com a mensagem "Aguarde". Como a Thread principal bloqueia essa que descrevi, usei o SwingWorker para derivar para uma Thread secundária. Porém, se chamo o processo que insere os dados do banco na JTable dentro do "doInBackground()" é gerada uma exceção associada com o CellRenderer da JTable. Se coloco fora, o JFrame ("aguarde") não é exibido.

** A chamada para a carga de dados é : refreshItemSelection(item);

final String item  = String.valueOf(e.getItem());
						SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
							private WaitFrame waitFrame;
							protected java.lang.Boolean doInBackground() throws Exception {
								waitFrame  = new WaitFrame();
								waitFrame.start();
								//refreshItemSelection(item);
								return true;
							}
							protected void done() {
								System.out.println("done");
								waitFrame.stop();
							}
						};	
						worker.execute();
						refreshItemSelection(item);

Para ajudar a exceção não ocorre sempre. O detalhe é que o número "14" do exemplo coincide em muitas vezes com a quantidade de linhas da tabela. Acredito que por alguma razão o CellRenderer tenta renderizar uma linha que não existe ! (a 14º começando da linha 0).

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 14
	at javax.swing.DefaultRowSorter.convertRowIndexToModel(Unknown Source)
	at javax.swing.JTable.convertRowIndexToModel(Unknown Source)
	at javax.swing.JTable.getValueAt(Unknown Source)
	at javax.swing.JTable.prepareRenderer(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
	at javax.swing.plaf.ComponentUI.update(Unknown Source)done

	at javax.swing.JComponent.paintComponent(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.BufferStrategyPaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(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)

Já tentei uma porção de soluções mas sem sucesso. Alguém já deu de cara com um problema parecido ?

3 Respostas

L

Alex@nder, não sei se alguém vai conseguir te ajudar só olhando este pedaço de código.Particulamente eu não consigo(rsrs).Tem como vc disponibilizar o seu TableModel e o seu CellRenderer de tiver?.Bom, manda o que estiver envolvido com este codigo do SwingWorker.

Abraços.

R

O método doInBackground() NÃO deve atualizar diretamente a interface gráfica, o que certamente ocorre quando você tenta instanciar e exibir um formulário a partir dele. A documentação do método get() exemplifica como usar uma caixa de diálogo para aguardar a execução do SwingWorker:

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#get()

Se você quiser atualizar a interface gráfica dentro de doInBackground(), deve usar o método publish(). Os dados enviados via publish() serão “canalizados” para o método process(), que você terá de redefinir conforme o exemplo abaixo:

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#publish(V...)

alex

Senhores, muito obrigado pela ajuda !
Testei e pesquisei sobretudo a solução com publish(). Porém, quando tento chamar a parte gráfica por ele, por alguma razão a janela com a mensagem não é exibida. Com JDialog, apenas a decoração da janela aparece. De qualquer forma o meu código ficou dessa forma e as exceções deixaram de ocorrer.

if(productCombo.getSelectedItem() == e.getItem()) { 
						final String item  = String.valueOf(e.getItem());
						SwingWorker<Boolean, Object> worker = new SwingWorker<Boolean, Object>() {
							private WaitFrame waitFrame =  new WaitFrame();
							protected Boolean doInBackground() throws Exception {
								publish();
								return true;
							}							
							protected void process(List<Object> info) {
								refreshItemSelection(item);
							}		
							protected void done() {
								waitFrame.stop();
							}
						};	
						worker.execute();
					}
Criado 7 de maio de 2009
Ultima resposta 11 de mai. de 2009
Respostas 3
Participantes 3