Repaint limpando a tela

5 respostas
K

Olá! Sou novo por aqui e queria saber se alguém pode me ajudar.

Estava querendo desejar um tabuleiro de xadrez em um JPanel, usando paint()
Tenho motivos para usar o paint() mesmo e também para chamar o paint() casa por casa do tabuleiro; mas somente a última casa é pintada.
Inicialmente achei que o repaint() limpava toda a tela, mas li que ele não faz isso. De qualquer forma, para garantir coloquei:

public void update(Graphics g) {
		paint(g);
	}
(aparentemente esse método nem é chamado)

Minha segunda suspeita é que o repaint() estava sendo chamado muito rapidamente e, entrava para a "fila de execução", assim somente o último era executado. Para tentar resolver (ou ao menos debugar) isso, criei a variável esperaRepaint e aparentemente deu deadlock :(

Alguma sugestão?

(estou colando as funções principais)

int atualizarX=-1; int atualizarY=-1;
	int esperaRepaint=0;
	int size=500;

	public void updateSquare(int i, int j) {
		atualizarX=i;
		atualizarY=j;
		while(esperaRepaint == 1) { }
		esperaRepaint = 1;
		repaint(posicao2pixels(atualizarX), posicao2pixels(atualizarY), size/8, size/8);
	}
	
	public Tabuleiro() {
		int i, j;

		// fix size to a multiple of 8 
		size=8*(int)(size/8);

		posicaoInicial();
				
		for(i=0; i<7; i++) {
			for(j=0; j<7; j++) {
				updateSquare(i, j);
			}
		}
		
		add(new JLabel("aaaaaaa"));
		addMouseListener(new Acao());
	}	public void paint(Graphics g) {
		if (atualizarX != -1) {
			if ((atualizarX+atualizarY) % 2 == 0) { g.setColor(Color.WHITE); }
			else { g.setColor(new Color(0, 128+3*(atualizarX+atualizarY), 0)); }
			g.fillRect(posicao2pixels(atualizarX), posicao2pixels(atualizarY), size/8, size/8);
			
			atualizarX = -1;
			
			esperaRepaint = 0;
		}
	}

Obrigado!

5 Respostas

ViniGodoy

Se você está desenhando num componente do Swing, não sobrescreva o método paint() e sim o paintComponent().

O que você percebeu é verdade. Quando existem muitos repaint, o java discarta alguns deles. É um fenômeno chamado “coalescing repaint”. O motivo para isso é simples: Numa aplicação gráfica swing normal, a tela não precisa ser repintada tantas vezes.

Jogos entretanto não são uma aplicação swing normal.

ViniGodoy

Ah sim, veja os tópicos Double Buffering Drawing e Converting to Active Rendering no livro Killer Game Programming in Java. Fica no capítulo 2. O site do livro é esse aqui (tem uma versão em pdf oficial lá):
http://fivedots.coe.psu.ac.th/~ad/jg/

Ele explica como evitar o uso do paint() e repaint() e usar uma técnica mais eficiente para a pintura do tabuleiro.

K

Obrigado, ViniGodoy

Alguns comentários:
Troquei o paint por paintComponent e realmente melhorou (ao menos outros objetos que haviam sido incluídos não sumiram).
Mas somente o último quadrado acaba sendo pintado de qualquer forma.

Os quadrados deveriam ser desenhados pelo for/for que contem updateSquare(i, j);

no updateSquare eu utilizo até repaint(x,y,w,h) para tentar garantir que a tela não seja limpada e também que os repaints não sejam excluídos (por serem regiões diferentes, imagino que não haja remoção deles nesse caso)

Um teste que eu gostaria de fazer era colocar um delay logo após as chamadas ao updateSquare(), para ver se ele realmente está pintando o primeiro quadrado, dai substituindo pelo segundo, depois terceiro. Se não for isso, posso tentar resolver de outra forma. Se for (e tenho quase certeza que é), não tenho mais idéias :frowning:

K

Ah, e quanto ao double buffering, ACHO que não é o caso. Double buffering costuma ser interessante especialmente quando há muito “movimento rápido”. No caso de um jogo de xadrez, só haverá movimento quando uma peça for movida.

Petronio_Braga

kavelot,

acho que o que você está querendo é isso. Dá uma olhada neste link abaixo:

http://mindprod.com/jgloss/validate.html

Criado 20 de janeiro de 2007
Ultima resposta 20 de jan. de 2007
Respostas 5
Participantes 3