Java - Ayuda con carrera de tortugas. Thread y BufferedImage

   
Vista:
Imágen de perfil de Kabuto

Ayuda con carrera de tortugas. Thread y BufferedImage

Publicado por Kabuto (150 intervenciones) el 07/12/2018 01:32:17
Hola.
Estoy jugueteando con Threads y se me había ocurrido crear una especie de animación donde unas tortugas se desplazan de derecha a izquierda, cada una a distinto ritmo, como si fuera una carrera.
Es todo muy simplón, básicamente quería practicar y experimentar con hilos y dibujar imagenes.

Bien, uso básicamente dos clases.
Una de ellas es un JPanel donde creo un BufferedImage a partir de un archivo .png con un dibujo de una tortuga y con un bucle voy "repintando" la tortuga una y otra vez, con un desplazamiento de 10 pixeles en cada iteracion.
Por el constructor le paso el tiempo que quiero que transcurra entre cada desplazamiento.

Esta es la clase, llamada Circuito, la cual implementa la interfaz Runnable para luego poder crear un Thread a partir de ella.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package carreras;
 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
 
import javax.imageio.ImageIO;
import javax.swing.JPanel;
 
public final class Circuito extends JPanel implements Runnable{
 
	private BufferedImage tortuga;
	private int x;
	private Color colorFondo;
	private int tiempo;
 
	public Circuito(int tiempo) {
		this.tiempo = tiempo;
		x = 680; //Posicion inicial de la tortuga
		colorFondo = this.getBackground();
		setPreferredSize(new Dimension(800, 140));
		try {
			tortuga = ImageIO.read(new File("imagenes/tortuga.png"));
		} catch (Exception e) {
			e.printStackTrace();
		}
 
	}
 
	@Override
    public void paint(Graphics g) {
		g.setColor(colorFondo); //Nos aseguramos de "pintar" con el color actual del fondo del panel
		g.fillRect(x+10, 0, 120, 120); //Borra la tortuga en la posicion anterior antes de repintar en la nueva posicion
        g.drawImage(tortuga, x, 0, 120, 120, null);
    }
 
	@Override
	public void run() {
		while (x > 0)
		{
			x-=10;
			repaint();
			try {
				Thread.sleep(tiempo);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
 
	}
 
}


Vale, luego, en otra clase. creo un JFrame, donde añado mi clase Circuito que hereda de JPanel donde repinto la tortuga.
Luego, en un metodo a parte, creo un Thread a partir de mi clase y lo ejecuto.

Y esto funciona perfectamente. La tortuga se va desplazando 10 pixeles, deteniendose el tiempo que yo le indique.

EL problema ha venido al agregar un segundo objeto de mi clase Circuito.
Mi intención era poner dos tortugas, una que se desplaze cada segundo, y la otra cada dos segundos
Así tendría dos Jpanels, cada uno con su tortuga, una más lenta que la otra.

Pero ocurre algo extraño, parece que las tortugas se dibujan por duplicado. Es decir, en ambos paneles se están dibujando la tortuga "rápida" y la "lenta"... con lo que se están mostrando 4 tortugas....

Y no acierto a entender a que se debe. Es la primera vez que hago algo "interesante" con Threads y repintando BufferedImage.... así que quizás este metiendo la pata en algo o hay algo que desconozco y no estoy teniendo en cuenta.

Esta es mi clase JFrame donde arranco todo el proceso.

Adjunto también la imagen de la tortuga que estoy usando, pero vamos, podeis usar cualquier imagen de 120x120 px

Un saludo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package carreras;
 
import java.awt.Container;
 
import javax.swing.BoxLayout;
import javax.swing.JFrame;
 
public final class Carrera extends JFrame{
 
	Circuito circuito1;
	Circuito circuito2;
 
	public Carrera() {
		super("Carrera Tortugas 0.1");
		Container contenedor = getContentPane();
		circuito1 = new Circuito(1000); //Tiempo 1 segundo
		circuito2 = new Circuito(2000); //Tiempo 2 segundos
		contenedor.setLayout(new BoxLayout(contenedor, BoxLayout.Y_AXIS));
		contenedor.add(circuito1);
		contenedor.add(circuito2);
		setContentPane(contenedor);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
	}
 
	void comenzar() {
		Thread carrera1 = new Thread(circuito1);
		Thread carrera2 = new Thread(circuito2);
		carrera1.start();
		carrera2.start();
	}
 
	public static void main(String[] args) {
		Carrera carrera = new Carrera();
		carrera.comenzar();
 
	}
 
}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Ayuda con carrera de tortugas. Thread y BufferedImage

Publicado por kingk (105 intervenciones) el 07/12/2018 06:55:27
Hola, puedes repintar y cubrir todo el panel, seria asi:

1
2
3
4
5
6
@Override
public void paint(Graphics g) {
    g.setColor(colorFondo); //Nos aseguramos de "pintar" con el color actual del fondo del panel
    g.fillRect(0, 0, g.getClip().getBounds().width, g.getClip().getBounds().height); //Cubre toda la superficie del panel
    g.drawImage(tortuga, x, 0, 120, 120, null);
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Ayuda con carrera de tortugas. Thread y BufferedImage

Publicado por Tom (1299 intervenciones) el 07/12/2018 18:00:22
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Kabuto

Ayuda con carrera de tortugas. Thread y BufferedImage

Publicado por Kabuto (150 intervenciones) el 08/12/2018 00:37:51
Gracias a ambos por las respuestas.

1
no_ debes "pintar" con swing desde hilos distintos.

Algo de esto me olía que iba a ser el problema.

Así que de momento he cambiado el enfoque. Un solo hilo que pintará varias tortugas.

Mi idea inicial era que cada hilo hiciera un .sleep() con un valor random y asi las tortugas iban variando su velocidad.
En vista de que esto no parece viable, de momento va todo en un solo hilo, con un sleep() de 1 segundo y lo que hago randomo es la cantidad de pixeles que se desplazan en cada iteración del bucle.

Gracias de nuevo, voy a seguir jugueteando con las tortugas añadiendo más cosas.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con carrera de tortugas. Thread y BufferedImage

Publicado por Tom (1299 intervenciones) el 08/12/2018 09:10:46
No hagas sleep() en el hilo de swing.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Revisar política de publicidad