swing fenster neu zeichnen, wenn überdeckt

I-Doetzken

Mitglied
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
 
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!!!
 
ok, hier ist der code:

vielen dank schon mal für alle tipps!

beste gruesse

Java:
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) {}
}
 
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?
 
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.
 
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.
 
wie wird dein CubeDisplay denn in die übrige Anwendung eingebunden?

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



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
 
Wie bERt0r bereits geschrieben hat: In der paintComponent wird nur etwas gezeichnet wenn die Bedingung zu trifft:
Code:
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
Code:
gridChanged
als auch
Code:
ledChanged
false sind, wird in Deinem Fall eben nur der Hintergrund gemalt und die Komponente bleibt "leer".
 
Wenn nun aber sowohl
Code:
gridChanged
als auch
Code:
ledChanged
false sind, wird in Deinem Fall eben nur der Hintergrund gemalt und die Komponente bleibt "leer".

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
 

Neue Themen


Zurück
Oben