# paintComponent malt bei repaint() Rahmen um Panel



## Rakasch (6. Feb 2012)

Auf einem JPanel hab ich die paintComponent-Methode überschrieben.
MouseListener+MouseMotionListener rufen repaint() auf.
Nun bekomme ich jedoch immer bei den MouseEvents so einen "zusätzlichen" Rahmen um das JPanels und die JLabels.

Hier erstmal zwei Bilder von meinem Problem.
Die Hintergrundbilder hab ich rausgenommen, damit man es besser sieht.
(anklicken zum vergrößern, sonst sieht mans nicht^^)

normal:




mit repaint():




(der grüne strich soll da sein, da ich mit der paintComponent drauf male)

Das große JPanel ist jenes mit der paintComponent() Methode, das kleine was man da noch drauf sieht ist ein JLabel, auf welchem der MouseListener liegt.

paintComponent-Methode des JPanels
[Java]	@Override 
	public void paintComponent(Graphics g){	
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		// draw background
//		g2d.drawImage(backgroundImg, 0, 0, null);
		// draw Solution
		for(int i=0;i<9;i++){
			g2d.drawImage(currentSolution_,i%3*kartenSize+kartenSize, i/3*kartenSize+kartenSize,null);
		}
		// draw line		
		if(dragSource!=null && dragTarget!=null) {
			g2d.setStroke(new BasicStroke(4.0f));
			g2d.setColor(actualColor);
			g2d.drawLine(dragSource.x, dragSource.y, dragTarget.x, dragTarget.y);
		}
	}[/Java]

Und der MouseListener ruft dann halt auf dem JPanel repaint() auf, wenn ich mit der Mouse zB über das kleine JLabel komme, und dann taucht dieser "Zusatz-Rahmen" auf. Sowohl am Rand des JPanels, als auch auf den JLabels.

Es muß was mit dem Zeichnen der Linie zu tun haben, wenn ich das auskommentiere, ist der Fehler weg._


----------



## SlaterB (6. Feb 2012)

aus deinem vorherigen Thema weiter zusammenkopiert bereinigt um das unbekannte Image ist der Code nicht schuld, 
warum sollte das Zeichnen einer Linie auch was zum Rahmen veranlassen,

oder ist bei dir das untenstehende Programm auch ok, deins aber weiter mit Rahmen?
teste auch weitere beliebige Programme aus dem Internet, etwa von
2D Graphics GUIJava

-----

ich vermute eher irgendwas mit deiner Umgebung, die Screenshots sind bisschen knapp,
der bunte Balken oben auffällig, ist das nur allgemeines Desktop-Design?

bzw. dass überhaupt so ein kleines Fenster mit Rahmen zu sehen ist, also dein 1. Bild, ist ja bereits nicht normal,
woher kommt das? welchen Code verwendest du komplett, welche IDE?



```
public class Test
{
    public static void main(String[] args)
        throws Exception
    {
        new MainWindow().setVisible(true);
    }
}


class MainWindow
    extends JFrame
{
    DrawImgPanel myPanel;

    public MainWindow()
    {
        setSize(400, 300);
        myPanel = new DrawImgPanel();
        JPanel left = new JPanel();
        left.setPreferredSize(new Dimension(100, 100));
        this.add(left, BorderLayout.WEST);
        this.add(myPanel, BorderLayout.CENTER); // panel mit der verschobenen grafik
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args)
    {
        new MainWindow().setVisible(true);
    }
}


class DrawImgPanel
    extends JPanel
    implements MouseMotionListener
{

    public DrawImgPanel()
    {
        this.addMouseMotionListener(this);
    }

    public void paintComponent(final Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        // draw line

        g2d.setStroke(new BasicStroke(4.0f));
        g2d.drawLine(20, 20, 120, 120);
    }

    public void mouseDragged(MouseEvent arg0)
    {
        this.repaint();
    }

    public void mouseMoved(MouseEvent arg0)
    {
    }
}
```


----------



## xehpuk (6. Feb 2012)

Du änderst den Zustand der Graphics und setzt ihn nicht mehr zurück. 
Der Rahmen wurde schon vorher gezeichnet, nur durch deinen 
	
	
	
	





```
setStroke()
```
-Aufruf wird dieser nun dicker.

Probier es mal so:

```
@Override 
    public void paintComponent(Graphics g){ 
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create(); // neue Graphics
        // draw background
//      g2d.drawImage(backgroundImg, 0, 0, null);
        // draw Solution
        for(int i=0;i<9;i++){
            g2d.drawImage(currentSolution[i],i%3*kartenSize+kartenSize, i/3*kartenSize+kartenSize,null);
        }
        // draw line        
        if(dragSource!=null && dragTarget!=null) {
            g2d.setStroke(new BasicStroke(4.0f));
            g2d.setColor(actualColor);
            g2d.drawLine(dragSource.x, dragSource.y, dragTarget.x, dragTarget.y);
        }
        g2d.dispose(); // Speicher freigeben
    }
```


----------



## Rakasch (6. Feb 2012)

Bei dem Beispiel funktioniert es normal, da hab ich den Fehler nicht.

Die bunte Leiste oben ist normal, Windows Vista-Design...
Als IDE verwende ich Eclipse.

Was die Rahmen betrifft. Das ist schon richtig, dass da welche sind. Auf dem JPanel liegen mehrere JLabels, die sind im Grunde leer und haben nur eine Größe, eine BevelBorder und einen Listener. Damit hab ich mir so ne Art Roll-Over Effekt gebaut. Das funktioniert wie gesagt auch.
Nur sobald ich den Teil mit dem Linien zeichnen in den Code einfüge, malt er immer beim mouseDragged, also beim repaint() diese komischen dicken Rahmen... 

Auf deinen Wunsch hin nochmal ganze Bilder:

normal:




nicht normal:


----------



## SlaterB (6. Feb 2012)

xehpuk hat gesagt.:


> Du änderst den Zustand der Graphics und setzt ihn nicht mehr zurück.
> Der Rahmen wurde schon vorher gezeichnet, nur durch deinen
> 
> 
> ...


pff, also das glaube ich weniger,
mag sein dass das setStroke() für SPÄTERES Zeichnen eine Auswirkung hat, das wäre dann gut gefunden (ob dann aber [c]g2d.dispose();[/c] günstig ist?)
aber doch nicht auf VORHERIGES Zeichnen, wozu würde man sonst ständig setColor() & Co. aufrufen


----------



## Rakasch (6. Feb 2012)

xehpuk hat gesagt.:


> Du änderst den Zustand der Graphics und setzt ihn nicht mehr zurück.
> Der Rahmen wurde schon vorher gezeichnet, nur durch deinen
> 
> 
> ...


Das mit dem setStroke war der richtige Gedanke!
Wenn ich dispose verwende, ist der Fehler zwar weg, aber er zeichnet mir die Labels nicht mehr.
Wenn ich den stroke wieder auf 1 zurücksetzte, funktioniert´s.

```
g2d.setStroke(new BasicStroke(1.0f));
```

Speicher freigeben klingt aber nach etwas, das man besser tun sollte, oder? ^^
Ich muß nochmal nachlesen, was dispose eigentlich macht...


----------



## xehpuk (6. Feb 2012)

SlaterB hat gesagt.:


> mag sein dass das setStroke() für SPÄTERES Zeichnen eine Auswirkung hat


Der Rahmen wird ja auch erst danach gezeichnet. 


```
paint()
```
 wird ja so gegliedert:



```
paintComponent()
```



```
paintBorder()
```



```
paintChildren()
```


Das "vorher" in meinem Satz hinterließ wohl eine Zweideutigkeit. Damit war gemeint, dass der Rahmen allgemein schon vorhanden war, also noch vor der Existenz der grünen Linie (aber falls existent: danach) gezeichnet wurde. Nur war er einfach nicht so dick.

@Rakasch:
Du hast bei meinem Code die Veränderung in Zeile 4 übersehen. Dort wird eine Kopie der aus dem Parameter stammenden Graphics über 
	
	
	
	





```
Graphics.create()
```
 erstellt. Änderungen an dieser _neuen_ Graphics haben keinen Einfluss auf die ursprüngliche.
Da hier also manuell eine neue Graphics erstellt wurde, muss diese auch wieder von Hand "zerstört" werden. Siehe dazu dann auch die Doku zu 
	
	
	
	





```
Graphics.dispose()
```
.

Es gibt beim Zeichnen grundsätzlich zwei Strategien:

Neue Graphics erstellen. Änderungen daran wirken sich nicht auf spätere Zeichenvorgänge aus. Vorteil ist die leichte Handhabung. Nachteil ist ein höherer Ressourcenverbrauch.
Alten Zustand der Graphics vor jeder Änderung merken und am Ende der Zeichenroutine wieder zurücksetzen. Vorteil ist der geringere Ressourcenverbrauch. Nachteil ist, dass es umständlicher ist.


----------



## Rakasch (6. Feb 2012)

xehpuk hat gesagt.:


> Du hast bei meinem Code die Veränderung in Zeile 4 übersehen.


Wo du Recht hast, hast du Recht.
So geht´s! Vielen Dank! :toll:


----------

