# Paint und paintComponent



## PowerOfMac (2. Aug 2014)

Hallo Java-Fans,

ich beiße mir seit einer geraumen Weile an paint() und paintComponent() Methoden von JFrames die Zähne aus. Zur Illustration meines Problems habe ich mal ein Beispielprogramm geschrieben:

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class WindowedWindow extends JFrame
	{
	public WindowedWindow (String name, int width, int height)
		{
		super (name);
		setSize (width, height);
		setLocationRelativeTo (null);
		setResizable (false);
		setUndecorated (false);
		setFocusableWindowState (true);
		setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

		setVisible (true);
		}

	public void paintComponent (Graphics g)
		{
		g.setColor (Color.blue);
		g.fillRect (50, 50, 500, 500);
		}

	public static void main (String [] args)
		{
		WindowedWindow window = new WindowedWindow ("Test", 800, 600);
		}
	}

Anhand dessen kann man sehen, dass paintComponent() bei JFrames nicht funktioniert (zumindest bei mir nicht). Nun gut, gelöst habe ich das Problem mit der Verwendung von paint() statt paintComponent() (obwohl man das ja wohl eigentlich nicht machen soll). Nun schmeißt mir das bei meinem neuesten Projekt leider eine seltsame Exception raus:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at MapEdit.DS2Window.paint(DS2Window.java:36)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:822)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
	at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Gerne krieg ich die auch mehrmals hintereinander. Manchmal wird das Bild trotzdem scheinbar ordnungsgemäß gezeichnet, manchmal bleibt der Bildschirm aber auch einfach weiß. Ich hab noch nicht rausgefunden was genau die Exception auslöst, bzw. wie ich sie vermeiden kann. Kann mir da jemand helfen? Was zur Hölle sind DirtyRegions?

Hier noch mal der Code, der die Exception auslöst:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;

public class DS2Window extends FullscreenWindow
	{
	/*Auflösung des GUI*/
	final static int RES_WIDTH = 1280;
	final static int RES_HEIGHT = 800;

	DS2Panel drawarea;
        BackgroundArea background;
	BufferedImage offimg;
	Graphics2D g2d1;
	Graphics2D g2d2;

	DS2Window (String name)
		{
		super (name);
		setLayout (null);

                 setBounds (0, 0, getWidth (), getHeight ());

		background = new BackgroundArea ();
		add (background);

		/*Double-Buffering, um das GUI in der korrekten Auflösung, ohne schwarzen Rand, darzustellen*/
		offimg = GraphicsEnvironment.getLocalGraphicsEnvironment ().getDefaultScreenDevice ().getDefaultConfiguration ().createCompatibleImage (DS2Window.RES_WIDTH, DS2Window.RES_HEIGHT);
		g2d1 = (Graphics2D) (offimg.createGraphics ());
                }

        public void paint (Graphics g)
		{
		background.paintArea (g2d1);

		g2d2 = (Graphics2D) (g);
		g2d2.drawImage (offimg, 0, 0, getWidth (), getHeight (), this);
		}
	}

//background.paintArea ()
public void paintArea (Graphics2D g2d)
		{
		g2d.setColor (BackgroundArea.BACKGROUND);
		g2d.fillRect (0, 0, DS2Window.RES_WIDTH, DS2Window.RES_HEIGHT);

		map.paintArea (g2d);
		info.paintArea (g2d);
		}

Nun habe ich mich ich mich für besonders clever gehalten und habe ein Panel von der Größe des Fensters als Grundfläche benutzt, also nicht mehr die paint() des DS2Window sondern die paintComponent() des neuen Panels verwendet, um die Objekte auf dem Bildschirm zu zeichnen. Diese Lösung hat sich schon bei früheren Projekten bewährt, aber diesmal haut sie nicht hin. Ich krieg damit wieder dasselbe Problem wie mit der paintComponent() von JFrame, also weißer Bildschirm und bei Benutzung von paint() die seltsame Exception.
Weiß jemand, wie mir zu helfen ist? Wie zeichnet ihr eure GUI's, wenn ihr nicht gerade Swing verwendet? Und wo kommt ist die Nullpointer-Exception her?

Danke im Voraus für eure Mühe!

PS: sorry, dass ich keine Codetags verwendet habe, ich kann grad nur vom Handy aus posten, da ist das leider schwierig


----------



## njans (2. Aug 2014)

Code in JAVA-TAGS packen, so, wie es in großen, roten Buchstaben geschrieben steht...


----------



## Network (2. Aug 2014)

Das was mein Vorgänger geschrieben hat ist sehr wichtig. Also fetter und roter hätte man es nicht machen können. Versuche bitte mal deinen eigenen Post zu lesen.

Und selbstverständlich wäre ein KSKB sehr hilfreich.


----------



## PowerOfMac (3. Aug 2014)

Hallo Java-Fans,

ich beiße mir seit einer geraumen Weile an paint() und paintComponent() Methoden von JFrames die Zähne aus.
Zur Illustration meines Problems habe ich mal ein Beispielprogramm geschrieben:



```
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class WindowedWindow extends JFrame
{
public WindowedWindow (String name, int width, int height)
{
super (name);
setSize (width, height);
setLocationRelativeTo (null);
setResizable (false);
setUndecorated (false);
setFocusableWindowState (true);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

setVisible (true);
}

public void paintComponent (Graphics g)
{
g.setColor (Color.blue);
g.fillRect (50, 50, 500, 500);
}

public static void main (String [] args)
{
WindowedWindow window = new WindowedWindow ("Test", 800, 600);
}
}
```

Anhand dessen kann man sehen, dass paintComponent() bei JFrames nicht funktioniert (zumindest bei mir nicht). Nun gut, gelöst habe ich das Problem mit der Verwendung von paint() statt paintComponent() (obwohl man das ja wohl eigentlich nicht machen soll). Nun schmeißt mir das bei meinem neuesten Projekt leider eine seltsame Exception raus:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at MapEdit.DS2Window.paint(DS2Window.java:36)
at javax.swing.RepaintManager$3.run(RepaintManager.java:822)
at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
at java.awt.EventQueue.access$400(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.awt.EventQueue$3.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Gerne krieg ich die auch mehrmals hintereinander. Manchmal wird das Bild trotzdem scheinbar ordnungsgemäß gezeichnet, manchmal bleibt der Bildschirm aber auch einfach weiß. Ich hab noch nicht rausgefunden was genau die Exception auslöst, bzw. wie ich sie vermeiden kann. Kann mir da jemand helfen? Was zur Hölle sind DirtyRegions?

Hier noch mal der Code, der die Exception auslöst:


```
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;

public class DS2Window extends FullscreenWindow
{
/*Auflösung des GUI*/
final static int RES_WIDTH = 1280;
final static int RES_HEIGHT = 800;

DS2Panel drawarea;
BackgroundArea background;
BufferedImage offimg;
Graphics2D g2d1;
Graphics2D g2d2;

DS2Window (String name)
{
super (name);
setLayout (null);

setBounds (0, 0, getWidth (), getHeight ());

background = new BackgroundArea ();
add (background);

/*Double-Buffering, um das GUI in der korrekten Auflösung, ohne schwarzen Rand, darzustellen*/
offimg = GraphicsEnvironment.getLocalGraphicsEnvironment ().getDefaultScreenDevice ().getDefaultConfiguration ().createCompatibleImage (DS2Window.RES_WIDTH, DS2Window.RES_HEIGHT);
g2d1 = (Graphics2D) (offimg.createGraphics ());
}

public void paint (Graphics g)
{
background.paintArea (g2d1);

g2d2 = (Graphics2D) (g);
g2d2.drawImage (offimg, 0, 0, getWidth (), getHeight (), this);
}
}

//background.paintArea ()
public void paintArea (Graphics2D g2d)
{
g2d.setColor (BackgroundArea.BACKGROUND);
g2d.fillRect (0, 0, DS2Window.RES_WIDTH, DS2Window.RES_HEIGHT);

map.paintArea (g2d);
info.paintArea (g2d);
}
```

Nun habe ich mich ich mich für besonders clever gehalten und habe ein Panel von der Größe des Fensters als Grundfläche benutzt, also nicht mehr die paint() des DS2Window sondern die paintComponent() des neuen Panels verwendet, um die Objekte auf dem Bildschirm zu zeichnen. Diese Lösung hat sich schon bei früheren Projekten bewährt, aber diesmal haut sie nicht hin. Ich krieg damit wieder dasselbe Problem wie mit der paintComponent() von JFrame, also weißer Bildschirm und bei Benutzung von paint() die seltsame Exception.
Weiß jemand, wie mir zu helfen ist? Wie zeichnet ihr eure GUI's, wenn ihr nicht gerade Swing verwendet? Und wo kommt ist die Nullpointer-Exception her?

Danke im Voraus für eure Mühe!


----------



## PowerOfMac (3. Aug 2014)

So, dass hat vom Handy aus ne halbe Stunde gedauert. Vermutlich sagt ihr mir als nächstes, dass die Exception unleserlich ist aber Tooltips gehen am iPhone nu mal nicht auf, also hab ich null Plan welches der 150 Symbole da oben für Exceptiontags ist.


----------



## knilch (3. Aug 2014)

Hi,


> Anhand dessen kann man sehen, dass paintComponent() bei JFrames nicht funktioniert (zumindest bei mir nicht).


Wenn du override von paintComponent() machst, dann musst du das so machen:

```
public void paintComponent (Graphics g) {
   super.paintComponent(g); 
   g.setColor (Color.blue);
   g.fillRect (50, 50, 500, 500);
}
```


----------



## PowerOfMac (3. Aug 2014)

Danke für die konstruktive Antwort. Ich probier dann gleich mal den super-Aufruf einzubinden. Kannst du mir auch was zu der Exception erklären?


----------



## kaoZ (3. Aug 2014)

Ich vermute stark das zu dem Zeitpunkt an welchem du Zeichen möchtest dein Graphics Object noch nicht vollständig initialisiert ist und deshalb die NPE fliegt, und außerdem , warum greifst du in die paint/paintComponent methode deines JFrames ein ? und nicht die eines Panels den du als content in das JFrame setzen möchtest, so wie es für gewöhnlich gemacht wird, der JFrame ist eben im normalfall nur dein "Rahmen" für das was du in deiner GUI darstellen möchtest.


----------



## Harry Kane (4. Aug 2014)

knilch hat gesagt.:


> Hi,
> 
> Wenn du override von paintComponent() machst, dann musst du das so machen:
> 
> ...


Die Klasse JFrame hat keine paintComponent(Graphics g) Methode!
Bitte wie Kaoz gesagt hat, von JPanel oder JComponent ableiten!


----------



## PowerOfMac (4. Aug 2014)

Harry Kane hat gesagt.:


> Die Klasse JFrame hat keine paintComponent(Graphics g) Methode!



Warum nicht?!  wird die nicht von JComponent geerbt? Oder ist ein JFrame kein Component?


----------



## Harry Kane (4. Aug 2014)

Ein JFrame ist zwar eine java.awt.Component, aber keine javax.swing.JComponent.
Dir ist aber schon klar, daß solche basics nur eine google-Suche entfernt sind?


----------



## VfL_Freak (4. Aug 2014)

oder hier :
Java Platform SE 7

gruß
Klaus


----------



## PowerOfMac (6. Aug 2014)

Ok. Hab jetzt von einem JPanel abgeleitet und super.paintComponent() eingebaut. Hat nicht geholfen. Habe dann den Fehler gefunden: ein anderes JPanel, welches ich noch nicht einmal benutzt habe hat das erste Panel verdeckt.


----------

