Java - Que pasa en este programa?

 
Vista:

Que pasa en este programa?

Publicado por Jordi (135 intervenciones) el 07/01/2018 15:26:26
Tengo dos clases, una que extiende de JPanel (Fons significa Fondo):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.awt.Graphics;
 
import javax.swing.JPanel;
 
public class Fons extends JPanel{
 
	@Override
	public void paintComponent(Graphics g) {
 
		g.drawLine((int)(Math.random() * 400),
				(int)(Math.random() * 400),
				(int)(Math.random() * 400),
				(int)(Math.random() * 400));
 
	}
 
}
Y la clase del Main:
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
import javax.swing.JFrame;
 
public class Main {
 
	public static void main(String[] args) {
 
		Fons fons = new Fons();
 
		JFrame finestra = new JFrame();
		finestra.setSize(400, 400);
		finestra.setLocationRelativeTo(null);
		finestra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
		finestra.add(fons);
 
		finestra.setVisible(true);
 
		for(int i = 0; i < 10; i++) {
			fons.repaint();
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
 
	}
 
}
Nada del otro mundo, pero la cosa se da dentro del Thread.sleep(); si por cada iteracion del bucle hago que espere un poco aparecen varias lineas en el JPanel mientras que si no pongo espera solo aparece una linea.
Alguien tiene una explicación para esto?
Gracias.
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

Que pasa en este programa?

Publicado por Tom (1831 intervenciones) el 07/01/2018 17:47:10
Pues es porque no usas la propiedad Opaque de JPanel, ni limpias el contenido antes de redibujar.
Así que swing limpia si le parece (generalmente no) antes de llamar a paintComponent.
Tal y como dice la documentación, funcionaría mejor tu ejemplo así:

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
public class Main {
	public static void main(String[] args) {
		DrawA panel = new DrawA();
		JFrame mainWin = new JFrame();
 
		mainWin.setSize(400, 400);
		mainWin.setLocationRelativeTo(null);
		mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainWin.add(panel);
 
		mainWin.setVisible(true);
 
		for(int i = 0; i < 10; i++) {
			panel.repaint();
			try {
				Thread.sleep(1);
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
 
	/* */
	static class DrawA extends JPanel {
		DrawA() {
			setOpaque(false);
		}
		@Override
		public void paintComponent(Graphics g) {
			g.drawLine((int)(Math.random() * 400),
					   (int)(Math.random() * 400),
					   (int)(Math.random() * 400),
					   (int)(Math.random() * 400));
		}
	}
}
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

Que pasa en este programa?

Publicado por Jordi (135 intervenciones) el 08/01/2018 00:25:56
Osea, que entonces el repintado de swing se da un poco cuando le da la gana a la librería y no sigue unas reglas claras?
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

Que pasa en este programa?

Publicado por Tom (1831 intervenciones) el 08/01/2018 09:07:16
No.
En teoría swing no limpiará antes de llamar a paintComponent() si supone que el propio componente lo hará (opaque == true). Lo que sí podría ocurrir es que incluso con opaque == false podría ser necesario limpiar previamente (la optimización del pintado en pantalla no es tan sencilla como puede parecer cuando se pueden solapar controles de tu aplic y ventanas de distintas aplicaciones).
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