Auf Frames zeichnen

Status
Nicht offen für weitere Antworten.

Illuvatar

Top Contributor
Um Grafik in eine Component (also auch z.B. einen Frame) zu zeichnen, muss grundsätzlich die Methode
Code:
public void paint (Graphics g)
überschrieben werden. Diese Methode wird von dem GUI-Thread in regelmäßigen Abständen aufgerufen. Bei JComponents sollte übrigens die Methode paintComponent überschrieben werden. Vor allem bei JFrames ist es auch wichtig, die paint-Methode der Superklasse aufzurufen.
Code:
super.paint(g);
Bei Swing-Komponenten ist zudem zu beachten, dass Swing nicht threadsicher ist, und diese aus anderen Threads nicht gezeichnet werden können, es sei denn, diese Threads wurden über SwingUtilities.invokeLater (Thread) bzw. SwingUtilities.invokeAndWait (Thread) mit dem Swing-Thread synchronisiert.

Ziemlich nutzlos ist es hingegen, über die Graphics aus Component#getGraphics zu zeichnen. Bei dem nächsten repaint wird das so gezeichnete wieder überzeichnet.
Der einzige Ausweg besteht darin, die Methode update leer zu implementieren, wodurch auf die Komponente aber überhaupt nicht mehr gezeichnet würde, wenn der Frame zum Beispiel minimiert und wieder maximiert worden wäre.

Die einzige Möglichkeit, während des Programmablaufes gezeichnete Dinge permanent auf die Component zu zeichnen, besteht somit darin, alles, was gezeichnet werden soll, in einer Datenstruktur (Array, ArrayList, Vector usw) zu speichern. Dies könnte zum Beispiel so aussehen:
Code:
import javax.swing.*;
import java.util.Vector;
import java.awt.*;

/**
 *Dieses Component muss hinzugefügt werden.
 */
public class JPaintComponent extends JComponent
{
	private Vector<PaintableObject> paints = new Vector<PaintableObject>(); // < 1.5 private Vector paintableObjects = new Vector();
	public void paintObj (PaintableObject po)
	{
		paints.add (po);
	}
	public Vector<PaintableObject> getObjects() // < 1.5 public Vector getObjects()
	{
		return paints;
	}
	public void removeObj (PaintableObject po)
	{
		paints.remove (po);
	}
	public void removeAll()
	{
		paints.removeAllElements();
	}
	public void paintComponent (Graphics g){
		for (PaintableObject po : paints){ // < 1.5 PaintableObject po; for (int i = 0; i < paints.size(); i++){po = ((PaintableObject)paints.elementAt (i));
			po.update (g);
		}
	}
}
/**
 *Nur Klassen, die von dieser Klasse abgeleitet wurden, können gezeichnet werden.
 */
abstract class PaintableObject
{
	private Color actual;
	public PaintableObject (Color actual)
	{
		this.actual = actual;
	}
	public void setColor (Color newColor)
	{
		actual = newColor;
	}
	void update (Graphics g)
	{
		g.setColor(actual);
		paint (g);
	}
	public abstract void paint (Graphics g);
}
/**
 *Beispielimplementation einer Linie.
 */
class PaintableLine extends PaintableObject
{
	int x1, y1, x2, y2;
	public PaintableLine (Color c, int x1, int y1, int x2, int y2)
	{
		super (c);
		this.x1 = x1;
		this.x2 = x2;
		this.y1 = y1;
		this.y2 = y2;
	}
	public void paint (Graphics g)
	{
		g.drawLine (x1, y1, x2, y2);
	}
}

Der Quellcode ist Java 1.5, ich habe den Code für ältere Versionen in Kommentaren reingeschrieben.
Er ist außerdem natürlich noch verbesserungsfähig (preferredSize z.B.) und soll nur als Beispiel dienen.
 
B

Beni

Gast
Um neu zu Zeichnen, muss man die Methode "repaint" aufrufen:

Code:
// eine Component, auf der etwas ist, das neu gezeichnet werden soll. Das kann auch eine Untercomponent sein.
Component component = ... 

// so wird der Component befohlen, neu zu zeichnen. Diese Methode kann von überall her aufgerufen werden, insbesondere auch von verschiedenen Threads.
component.repaint();
 
Status
Nicht offen für weitere Antworten.

Oben