Thread, Painel, Atualização

Olá a todos. Anteriormente vim pedir ajuda de um colega aqui de fórum para fazar um autoScroll, funcionou até, quando utilizei em um painel simples sem background e muitas coisas desenhadas.
Então o problema é o seguinte, estou fazendo uma thread.sleep(10) e nesse intervalo de tempo a JScrollPane recebe na posição horizontal +1 pixel o que faz ela ir se movendo para a direita. Mas, econtrei um problema: quando executo ele até vai indo pra direita, mas, ele cria duas linhas “como se fossem um delay” do lado direito do painel, sendo que estas duas linhas não existem, se vc usar o scroll manualmente verá que isto não existe, então pessoal, segue o código da forma que estou fazendo a JScrollPane “caminhar”:


public class AutoScroll implements Runnable {

	private JScrollPane pane;
	private Thread thread;
	private int valor = 10;
	public AutoScroll(JScrollPane pane) {
		this.pane = pane;
	}
	public void start(){
		thread = new Thread(this);
		thread.start();
	}
	public void interrupt(){
		thread = null;
	}
	public void setValue(int valor){
		this.valor = valor;
	}
	public void run() {
		while(thread != null){
		try {
			thread.sleep(10);
			scrollPane.getHorizontalScrollBar().setValue(scrollPane.getHorizontalScrollBar().getValue() + valor);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		}
		
	}

}

(...) AutoScroll scroll = new AutoScroll(meuJScrollPane);
scroll.start();

daí acontece o delay (em anexo):


Tente trocar isso:

scrollPane.getHorizontalScrollBar().setValue(scrollPane.getHorizontalScrollBar().getValue() + valor);

Por isso:

EventQueue.invokeLater(new Runnable() { public void run() { scrollPane.getHorizontalScrollBar().setValue(scrollPane.getHorizontalScrollBar().getValue() + valor); } });

[quote=ViniGodoy]Tente trocar isso:

scrollPane.getHorizontalScrollBar().setValue(scrollPane.getHorizontalScrollBar().getValue() + valor);

Por isso:

EventQueue.invokeLater(new Runnable() { public void run() { scrollPane.getHorizontalScrollBar().setValue(scrollPane.getHorizontalScrollBar().getValue() + valor); } });[/quote]

Hmm, deu certinho aqui Vini. Mas, então o motivo para se criar outra runnable seria para evitar esse problema de renderização do Swing?

Obrigado, ajudou e muito!

Eu já falei isso em outros tópicos, vou repetir aqui.

O Swing não é thread safe. Quando dizemos que ele não é thread-safe significa exatamente que você não pode usar 2 threads para atualizar o mesmo componente swing ao mesmo tempo, o que era exatamente o que você estava fazendo quando criou sua thread que movimenta o scrollbar.

Isso é errado, e, como você viu com seus próprio olhos, pode dar problemas na pintura.

O que você faz com esse EventQueue é enfileirar um pedido para a thread do Swing, para que ela faça a atualização do seu scrollbar quando ela julgar conveniente. O runnable, neste caso, apenas serve para dizer que pedido é esse. Ele não dispara nenhuma outra thread nesse momento.

A classe EventQueue nada mais é do que essa fila, com o os métodos de enfileirar (invokeLater) e o método de desenfileirar sincronizados. Sua thread então coloca um Runnable lá, e a thread do Swing é quem retira ele de lá e processa. Filas de mensagens são formas simples de garantir paralelismo entre threads, sem recorrer a sincronização.