Um Grafik in eine Component (also auch z.B. einen Frame) zu zeichnen, muss grundsätzlich die Methode
ü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.
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:
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.
Code:
public void paint (Graphics g)
Code:
super.paint(g);
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.