# swing fenster neu zeichnen, wenn überdeckt



## I-Doetzken (4. Mrz 2012)

salut,

ich habe eine kleine java/swing applikation geschrieben.
ein großteil des programmfensters wird von einer JComponent belegt, in der etwas gezeichnet wird.

wenn dass programmfenster von einem anderen fenster überseckt war, bleibt es grau und wird nicht neu gezeichnet.

auch wenn das menu des programms ausgeklappt war und die JComponent überdeckt, bleibt der überdeckte bereich grau und wird nicht neu gezeichnet.

was habe ich übersehen/ falsch gemacht?

vielen dank für alle tipps


----------



## GUI-Programmer (4. Mrz 2012)

Poste doch mal deinen Code, ohne Code kann man dazu nicht viel sagen!!!

Pauschal fällt mir dazu nur folgendes ein:
1. Du gehst mit den Zeichenmethoden (paint(), paintComponent(), paintBorder(), paintChildren()) falsch um
2. Du verwendest ein Layout, versuchts aber trozdem mit setSize() oder setBounds() die Komponent zu resizen
3. Du rufst irgendow getGraphics auf eine von Window oder Component erbende Instanz auf
oder 4. Mit deiner Grafikkarte oder dein Java stimmt was nicht.

Aber wie bereits gesagt, du musst schon ein wenig Code liefern!!!


----------



## I-Doetzken (4. Mrz 2012)

ok, hier ist der code: 

vielen dank schon mal für alle tipps!

beste gruesse


```
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;

import javax.swing.JComponent;
import javax.swing.JOptionPane;

public class CubeDisplay extends JComponent implements MouseListener{
	public static final long serialVersionUID = 54L;
	private int n; //n by n by n cube
	private int width, height;
	
	private LinkedList<GridShape> ll_GridShapes = new LinkedList<GridShape>();
	private PointDouble[][][] points;
	private LED_Shapes[] ar_leds;
	private boolean showLEDs = true;
	private boolean showGrid = true;
	private boolean ledChanged = true;
	protected boolean imageChanged = false;
	private boolean gridChanged = true;
	protected int duration = 1000;
	private Color backgroundColor = Color.white;
	
	public CubeDisplay(){
		super();
		this.n = LedCubeSimulator.n;
		enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
		addMouseListener(this);
	}
	
	private void calculatePoints(){
		//rechne rechne
		//berechne punkt-koordinaten
	}
	
	/**
	 * erzeugt die linien des gitters und speichert sie in der linkedlist
	 */
	private void createGrid(){
		Color cfront = Color.black;

		ll_GridShapes.clear();
		for (int i = 0; i<n;i++){
			for (int j = 0;j<n;j++){
				//linien hinzufuegen
				ll_GridShapes.add(foo)
			}
		}
		gridChanged = true;
	}
	
	private void createLEDs(){
		//kreisformen hinzufuegen
		ar_leds = new LED_Shapes[(n*n*n)];
		ledChanged = true;
	}
	
	public void setLEDBits(String in){
			//farben von bestehenden formen aus dem array ar_led veraendern
			//und neu zeichnen
			ledChanged = true;
			repaint();
		}else{
			System.out.println("setLEDBits ist nicht ok");
		}
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (gridChanged || ledChanged){
			Graphics2D g2d = (Graphics2D)g;
			g2d.setColor(backgroundColor);
			g2d.fill(new Rectangle2D.Float(0,0,getWidth(),getHeight()));
			if(showGrid && ll_GridShapes.size() >0){
				for(int i = 0; i<ll_GridShapes.size(); i++){
					g2d.setColor(ll_GridShapes.get(i).getColor());
					g2d.setStroke(ll_GridShapes.get(i).getBs());
					g2d.draw(ll_GridShapes.get(i).getShape());
				}
				gridChanged = false;
			}
			if(showLEDs && ar_leds.length>0){
				for (int i = 0; i<(n*n*n);i++){
					g2d.setColor(ar_leds[i].getColor());
					g2d.setStroke(ar_leds[i].getBs());
					g2d.fill(ar_leds[i].getShape());
				}
				ledChanged = false;
			}
		}
	}
	
	private void updateShapes(){
		calculatePoints();
		createGrid();
		createLEDs();
	}
	
	/**reagiert auf veraenderung der groesse*/
	public void processComponentEvent(ComponentEvent e){
		super.processComponentEvent(e);
		if((e.getID() & ComponentEvent.COMPONENT_RESIZED) != 0){
			this.width = getWidth();
			this.height = getHeight();
			updateShapes();
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		int dist = 10;
		for(int i = 0; i < (n*n*n); i++){
			if(
				e.getX() > ar_leds[i].getX()-dist && e.getX() < ar_leds[i].getX()+dist
				&&
				e.getY() > ar_leds[i].getY()-dist && e.getY() < ar_leds[i].getY()+dist
			){
				System.out.println("led nr "+i);
				toggleLED(ar_leds[i]);
			}
		}
		repaint();
	}
	@Override
	public void mousePressed(MouseEvent e) {}
	@Override
	public void mouseReleased(MouseEvent e) {}
	@Override
	public void mouseEntered(MouseEvent e) {}
	@Override
	public void mouseExited(MouseEvent e) {}
}
```


----------



## KrokoDiehl (5. Mrz 2012)

Hm, spontan nichts auffälliges... wie wird dein CubeDisplay denn in die übrige Anwendung eingebunden? Und schonmal probiert von JPanel anstelle von JComponent zu erben?


----------



## bERt0r (5. Mrz 2012)

Generell gehört in eine paintComponent keine Abfrage ob sich irgendwas geändert hat. Die paintComponent Methode ist es, die aufgerufen wird, wenn sich etwas geändert hat, das heisst in der paintComponent musst du alles so zeichnen wie deine Daten gerade sind. Wenn sich etwas ändert, änderst du die jeweiligen Daten und rufst repaint auf.


----------



## I-Doetzken (5. Mrz 2012)

bERt0r hat gesagt.:


> Generell gehört in eine paintComponent keine Abfrage ob sich irgendwas geändert hat. Die paintComponent Methode ist es, die aufgerufen wird, wenn sich etwas geändert hat, das heisst in der paintComponent musst du alles so zeichnen wie deine Daten gerade sind. Wenn sich etwas ändert, änderst du die jeweiligen Daten und rufst repaint auf.



Das klingt in meinen Ohren irgendwie verschwenderisch.
Muss alles neu gezeichnet werden, wenn sich nur ein kleiner Teil verändert?

Vielen Dank für weitere Tipps.


----------



## I-Doetzken (5. Mrz 2012)

KrokoDiehl hat gesagt.:


> wie wird dein CubeDisplay denn in die übrige Anwendung eingebunden?



http://www.gnugeo.de/LedCubeSimulator-src.zip





KrokoDiehl hat gesagt.:


> Und schonmal probiert von JPanel anstelle von JComponent zu erben?



Ja, habe ich eben ausprobiert. auf den ersten Blick sehe ich keinen Unterschied.

Das Verhalten tritt nicht 100%-reproduzierbar auf, mal reagiert das Programm korrekt, mal nicht.
Unter Windows7 ist es viel schlimmer, als unter Linux.
Java 1.7 scheint besser, als Java 1.6 ... aber das ist "aus dem Bauch heraus" und geschätzt.

Vielen Dank für weitere Tipps.

Beste Grüße


----------



## Michael... (5. Mrz 2012)

Wie bERt0r bereits geschrieben hat: In der paintComponent wird nur etwas gezeichnet wenn die Bedingung zu trifft: 
	
	
	
	





```
if (gridChanged || ledChanged){
```
Allerdings hat man es als Programmierer nicht in der Hand wann die paintComponent aufgerufen und somit die Komponente neu gezeichnet wird.
Wenn Deine Komponente zunächst durch ein anderes Fenster verdeckt und dann wieder sichtbar wird, löst der RepaintManager i.d.R. ein Neuzeichnen aus. Wenn nun aber sowohl 
	
	
	
	





```
gridChanged
```
 als auch 
	
	
	
	





```
ledChanged
```
 false sind, wird in Deinem Fall eben nur der Hintergrund gemalt und die Komponente bleibt "leer".


----------



## I-Doetzken (5. Mrz 2012)

Michael... hat gesagt.:


> Wenn nun aber sowohl
> 
> 
> 
> ...



Jetzt habe ich verstanden, was bERtOr mir sagen wollte!

Oh Mann - klar - das ist logisch.
Wie blind kann man sein?

Ich habe es geändert und der Fehler ist bisher nicht aufgetreten.

Vielen Dank!!!


Beste Grüße


----------

