# Bild im ImagePanel (AWT) wird nur machmal neu gezeichnet



## wimpf (22. Mai 2008)

Hallo

ich zeichne in Java 1.3 unter AWT mit folgendem überschriebenen Panel Grafiken:

```
package .....;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.image.ImageObserver;

public class ImagePanel extends Panel implements ImageObserver{
	private static final long serialVersionUID = -6364883255675338017L;
	private Image myImage = null;
	private Color myColor = null;
	private int panelWidth = 0;
	private int panelHeigth = 0;
	
	private Image dbImage;
	private Graphics dbg;
	
	public ImagePanel (String i, int r, int g, int b, boolean opaque) {
		super();
		
		//set background if opaque = true
		if (opaque) {
			myColor = new Color(r, g, b);
			this.setBackground(myColor);
			System.out.println("set color imagepanel");
		}
		
		//read image
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}

	    panelWidth = myImage.getWidth(this);
	    panelHeigth = myImage.getHeight(this);
	    
	    //set 
	    this.setLayout(null);
	    this.setSize(panelWidth, panelHeigth);
	    this.setVisible(true);
	}
	
	public void paint (Graphics g) {
		super.paint(g);
	    //set background image
		g.drawImage(myImage, 0, 0, this);
	}
	
	public void update (Graphics g) {
		//initialize double buffer
		if (dbImage == null) {
			dbImage = createImage (this.getSize().width, this.getSize().height);
			dbg = dbImage.getGraphics ();
		}

		System.out.println("w "+this.getSize().width);
		System.out.println("h "+this.getSize().height);
		System.out.println("b "+getBackground ());

		//clear screen
		dbg.setColor (getBackground ());
		dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);

		//paint foreground
		dbg.setColor (getForeground());
		paint (dbg);

		//draw picture
		g.drawImage (dbImage, 0, 0, this);
	}

	public void setImage (String i) {
		//read image
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}
	}
	
	public Dimension getMinimumSize() {
		Dimension temp = new Dimension(panelWidth, panelHeigth);
		return temp;
	}

	public Dimension getPreferredSize() {
		return getMinimumSize();
	}

}
```

Das funktioniert auch in soweit. Problem ist, dass wenn ich ImagePanels zu anderen ImagePanels hinzufüge, einige nicht immer gezeichnet werden. Das sieht dann bspw. so aus:




Der kleine Papierkorb bei Nr. 5 fehlt einfach in der Darstellung, obwohl er da ist. Wenn ich das Programm dazu zwinge das Fenster neu zu zeichnen (indem ich scrolle oder einfach ein anderes Windows-Fenster wie ein Radiergummi darüber schiebe) erscheint der Papierkorb.

Warum ist das so und warum kann ich das nicht nachvollziehen? Es fehlt mal die eine Grafik und dann die andere. Etliche repaints oder validates haben keine Änderung gebracht.

Habt ihr einen Tipp für mich?

Danke,
wimpf


----------



## L-ectron-X (22. Mai 2008)

Ist das Thema in diesem Thread ein anderes?
http://www.java-forum.org/de/viewtopic.php?t=67545
Warum der zweite Thread?

Ist es immer nur die 5. Grafik?


----------



## wimpf (3. Jul 2008)

Hallo

also das Problem schien mir ein anderes zu sein. Aber es besteht nach wie vor. Ich verstehe nicht, warum es immer Flackert wenn man die Grafik bspw. scrollt. Im Moment habe ich dieses ImagePanel:


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.image.ImageObserver;

public class ImagePanel extends Panel implements ImageObserver{
	private static final long serialVersionUID = -6364883255675338017L;
	private Image myImage = null;
	private Color myColor = null;
	private int panelWidth = 0;
	private int panelHeigth = 0;
	private Image dbImage; 
	private String image;

	public ImagePanel (String i, int r, int g, int b, boolean opaque) {
		super();

		image = i;
		
		//set background if opaque = true
		if (opaque) {
			myColor = new Color(r, g, b);
			this.setBackground(myColor);
			System.out.println("set color imagepanel");
		}

		//read image
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}

		panelWidth = myImage.getWidth(this);
		panelHeigth = myImage.getHeight(this);

		//set 
		this.setLayout(null);
		this.setSize(panelWidth, panelHeigth);
		this.setVisible(true);
	}

	public void paint (Graphics g) {
		if (myImage != null){
			g.drawImage(myImage, 0, 0, this);
		}
	}

	public void update (Graphics g) { 
		//initialize double buffer 
		if (dbImage == null) { 
			dbImage = getToolkit().getImage(image);
			MediaTracker mt = new MediaTracker(this);
			mt.addImage(dbImage, 0);
			try {
				mt.waitForAll();
			} catch (InterruptedException ex) {
			}
		} 

		//draw picture 
		g.drawImage (dbImage, 0, 0, this); 
		paint(g);
	}

	public void setImage (String i) {
		//read image
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}
		this.repaint(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		System.out.println("x" + this.getX() + "y" + this.getY() + "w" + this.getWidth() + "h" + this.getHeight());
	}

}
```

Ich habe versucht die Bufferung im Update einzufügen. Ich habe mir das so gedacht:
- wenn die Grafik neu gezeichnet werden soll, wird ja die Methode update aufgerufen. Daher habe ich diese überschrieben.
- in meinem update lade ich nochmals das Bild (String image) in dbImage. Das gleiche Bild habe ich ja schon in my Image und stelle es aktuell dar.
- Das dbImage lade ich, damit ich kein Flackern habe in der Zeit in welcher das myImage erneut aufgebaut wird.
- Ich lade also das dbImage und stelle es dann dar ("g.drawImage (dbImage, 0, 0, this); ")
- anschliessend rufe ich "paint(g)" auf um dann das ursprüngliche myImage darzustellen.

Das flackern verschwindet trotzdem nicht.  Ich tue mir leider schwer hier ein funktionsfähigs Beispiel anzuhängen, habe aber mal versucht einen sehr abgspeckten TestClient hinzuzufügen. Beim Scrollen flackert bei mir immer die Hintergrundgrafik. Habt Ihr noch Ideen?

Danke,
wimpf


```
import java.awt.Frame;
import java.awt.ScrollPane;
import java.awt.TextArea;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class TestClient2 extends Frame {
	public static TestClient2 TestClient;
	
	Frame mainFrame;
	ScrollPane mainScroller;
	ImagePanel mainPanel;
	TextArea textArea;
	
    public static void main(String[] args) {
    	TestClient = new TestClient2();
    }
    
	public TestClient2() {
		//UI
		mainFrame = new Frame();
		mainScroller = new ScrollPane();
		mainPanel = new ImagePanel("./PICTURE/mainBackground2.gif", 44, 55, 66, false);
		
		textArea = new TextArea(30, 20);
		textArea.setBounds(20, 75, 250, 150);
		mainPanel.add(textArea);
		
		mainScroller.add(mainPanel);
		mainFrame.add(mainScroller);
		mainFrame.setSize(400, 400);
		
		//default mainFrame behavior
	    mainFrame.addWindowListener(new WindowAdapter() {
	    	public void windowClosing(WindowEvent event){
	    		System.exit(0);
	    	};
	    });
	    
	    textArea.append("---START-1--\n");
		mainFrame.setVisible(true);
    	textArea.append("---SERVICE---\n");
		System.out.println("FINISH");
	}
	
	public void addText(String t){
		textArea.append(t);
	}
}
```


----------



## Marco13 (3. Jul 2008)

Das mit dem DoubleBuffering stimmt so wohl nicht. Schau dir nochmal die Codebeispiele zu double buffering in AWT an - oder nimm' gleich Swing (JPanel), da ist DoubleBuffering schon eingebaut.


----------



## wimpf (7. Jul 2008)

Hallo

ich habe jetzt ein Beispiel für das Buffering 1 zu 1 aus dem Handbuch entnommen. Das sieht dann so aus:


```
public void update(Graphics g){
		//initialize double buffer
		if (dbImage == null) {
			dbImage = createImage(this.getSize().width, this.getSize().height);
			dbGraphics = dbImage.getGraphics();
		}
		//delete background
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
		//draw foreground
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		//draw off screen
		g.drawImage(dbImage,0,0,this);
	}
```

Aber es flackert immer noch. Ich versuch nochmals mein Problem zu schildern.

Also ich habe ganz neu ein Panel gemacht auf welchem ich mit Rechtecken einen Hintergrund zeichne Das ist dieses Panel hier.


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.image.ImageObserver;

public class MainPanel extends Panel implements ImageObserver{
	private static final long serialVersionUID = -6364883255675338017L;
	private Image myImage = null;
	private Color myColor = null;
	private int panelHeigth = 0;
	
	private Image dbImage;
	private Graphics dbGraphics;
	
	public MainPanel (String i, int h) {
		super();
		panelHeigth = h;

		//layout
	    setLayout(null);
	}

	public void paint (Graphics g) {
		//background colors
//		|x| | | | |
		g.setColor(new Color(193, 209, 224));
		g.fillRect(0, 0, 157, panelHeigth);

//		| |x| | | |
		g.setColor(new Color(220, 229, 238));
		g.fillRect(157, 0, 1, panelHeigth);
		
//		| | |x| | |
		g.setColor(new Color(162, 184, 209));
		g.fillRect(158, 0, 50, panelHeigth);
		
//		| | | |x| |
		g.setColor(new Color(220, 229, 238));
		g.fillRect(208, 0, 1, panelHeigth);
		
//		| | | | |x|
		g.setColor(new Color(193, 209, 224));
		g.fillRect(209, 0, 17, panelHeigth);
	}

	public void update(Graphics g){
		//initialize double buffer
		if (dbImage == null) {
			dbImage = createImage(this.getSize().width, this.getSize().height);
			dbGraphics = dbImage.getGraphics();
		}
		//delete background
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
		//draw foreground
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		//draw off screen
		g.drawImage(dbImage,0,0,this);
	}

}
```

Dann setze ich darauf ein weiteres Panel mit Content darin. Dieses weitere Panel wird wie folgt erstellt und mit hintergrundPanel.add(contentPanel1) auf das andere Panel gebracht.


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.image.ImageObserver;

public class ImagePanel extends Panel implements ImageObserver{
	private static final long serialVersionUID = -6364883255675338017L;
	private Image myImage = null;
	private Color myColor = null;
	private int panelWidth = 0;
	private int panelHeigth = 0;
	
	private Image dbImage;
	private Graphics dbGraphics;
	
	public ImagePanel (String i, int r, int g, int b, boolean opaque) {
		super();
		//set background if opaque = true
		if (opaque) {
			myColor = new Color(r, g, b);
			this.setBackground(myColor);
			System.out.println("set color imagepanel");
		}
		
		//read image
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}

	    panelWidth = myImage.getWidth(this);
	    panelHeigth = myImage.getHeight(this);
	    
	    //set 
	    setLayout(null);
	    setSize(panelWidth, panelHeigth);
	}

	public void paint (Graphics g) {
		g.drawImage(myImage, 0, 0, this);
	}

	public void update(Graphics g){
		//initialize double buffer
		if (dbImage == null) {
			dbImage = createImage(this.getSize().width, this.getSize().height);
			dbGraphics = dbImage.getGraphics();
		}
		//delete background
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
		//draw foreground
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		//draw off screen
		g.drawImage(dbImage,0,0,this);
	}
    
	public void setImage (String i) {
		myImage = getToolkit().getImage(i);
		MediaTracker mt = new MediaTracker(this);
		mt.addImage(myImage, 0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ex) {
		}
	}
}
```

Jetzt das Problem.

Ich entferne das ContentPanel1 vom HintergrundPanel um gleich anschliessend ein anderes ContentPanel2 darauf anzuzeigen.

hintergrundPanel.remove(contentPanel1)
hintergrundPanel.add(contentPanel1)

Wenn ich das mache sehe ich nach dem removen kurz einen weissen Hintergrund erscheinen. Warum ist das so? Wie kann ich vom Hintergrund ein Panel entfernen ohne dass mir mein durch die Rechtecke gezeichneter Hintergrund verschwindet (weiss wird)?

Ich habe hier immer das gleiche Problem und versuche einfach durch unterschiedliche Wege es zu lösen. Sorry, wenn ich immer wieder einen anderen Ansatz reinbringe, aber es kann doch nicht sein, dass es nicht funktionieren mag. 

Danke,
Wimpf

PS: Ich kann nach wie vor nur AWT verwenden und höchstens Java 1.4


----------



## Quaxli (7. Jul 2008)

Mir fällt auf, daß in Deiner überschriebenen paint-Methode kein super-Aufruf enthalten ist. Den würde ich mal reinpacken.

Zudem würde mich interessieren. Was genau Du realisieren willst, evtl. kann man dann ein paar Tipps zur Umsetzung geben.


----------



## wimpf (7. Jul 2008)

Hallo

Danke für die Antwort. Aber das führt zu keiner Aenderung. Ich baue hier einen Client für ein Handy. Recht speziell mit Hilfe von Ericsson SDS.

Letzendlich habe ich nur Probleme mit der Aktualisierung meiner grafischen Panels. Da ich hier komplett mit positionierten Grafiken arbeiten muss, habe ich einige Panels erweitert und mit Layout null versehen. Zwei davon habe ich ja in meiner letzten Nachricht angehängt. 

Es ist so, dass ich also ein solches grafisches Panel habe (Hintegrund) und darauf je nach Inhalt ein anderes grafisches Panel (Contentpanel1) hinzufüge. Bei meinem Hintergrund Panel habe ich paint überschrieben mit dem Zeichnen von gefüllten Rechtecken. Bei meinem Contentpanel steckt in paint die Darstellung einer png-Grafik.

Wenn sich der Inhalt des Content ändert, will ich das erste Contentpanel entfernen und ein anders Contentpanel auf meinem Hintergrund anzeigen. Beim Entfernen flackert der Hintergrund, bzw. ich kann sehen dass dieser weiss wird, obwohl in der Paint Methode des Hintergrunds lauter Rechtecke zeichne (eben mein Hintergrund) und update überschrieben habe.

Ich will also nur ein Panel (Content) von einem anderen Panel (Hintergrund) entfernen und ein neues Contentpanel auf den Hintergrund bringen ohne dass dieser weiss wird oder sonst wie flackert.

Entweder ist meine Denke falsch oder ich habe ein Problem in mit meinen überschriebenen Panels? Ich weiss es eben nicht besser, leider.

Vielen Dank für eure Mühe,
Wimpf


----------



## wimpf (8. Jul 2008)

Hallo

ich konnte das Problem einschränken und es nun in (hoffentlich) einfachen Worten erklären.

1. Ich habe mir ein Frame erstellt und den Hintergrund davon blau eingefärbt.

2. Darauf ist ein ScrollPane. In diesem Scrollpane überschreibe ich die paint Mehrode und zeichne mir meinen eigenen Hintergrund:


```
public void paint (Graphics g) {
		super.paint(g);
		g.setColor(new Color(193, 209, 224));
		g.fillRect(0, 0, 157, 400);
}
```

3. Ich füge diesem ScrollPane ein anderes Panel hinzu. Dieses wird dann problemlos dargestellt.

4. Nun entferne ich vom ScrollPane dieses Panel wieder:

```
backgroundPanel.remove(mainPanel);
```

5. Beim Debugen ist direkt nach dieser Befehlszeile erkennbar, dass a) das Panel entfernt wurde und b) ich an Stelle des Panels nun den blauen Hintergrund des Frames angezeigt bekomme, was ich bisher als Flackern wahrgenommen hatte.

Mein Problem ist, dass ich diesen blauen Hintergrund oder irgendeinen anderen einfarbigen Hintergrund dort nicht brauchen kann. Ich will die "Oberfläche" des ScrollPane sehen welche ich in paint des ScrollPane erstellt habe. Es hilft leider auch nichts, wenn ich zusätzlich noch die paint Methode des Frames überschreibe und dafür dann Hintergrund nicht blau definiere, dann wird eben weiss anstatt blau gezeigt. 

Wie kann ich es denn schaffen, dass mir nicht die Farbe anzeigt wird die getBackground() wohl zurück liefert sondern mein gezeichneter Background in der paint Methode?

danke,
wimpf


----------



## Marco13 (8. Jul 2008)

Bei dem DoubleBuffering hatte ich wohl was falsch gelesen - das im 1. Post stimmt wohl so. 

Allerdings hast du jetzt schon etliche Klassen gepostet und etliche (verschiedene!) Fehler/Verhaltensweise beschrieben, und verschiedene(!) Prozesse, die zu diesen Fehler führen. 

Wenn du ein minimales, compilierbares Beispiel posten würdest, und klar sagen würdest: "Wenn ich den Button klicke, passiert DIES, es soll aber DAS passieren", wäre das Problem sicher schnell gelöst.


----------



## Gast2 (8. Jul 2008)

Erstelle ein Hintergrundpanel mit deinem Bild adde dieses auf die Scrollpane...
und wenn du neue Panels erstellst immer auf dein Hintergrundpanel adden und removen...


----------



## wimpf (8. Jul 2008)

Danke für die Antworten. Ich habe jetzt wie vorgeschlagen zwei Klassen erstellt die das Problem zeigen.

Die Klasse BackGroundTest:


```
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class BackGroundTest extends Frame {
	public static BackGroundTest BackGroundTest;
	public Frame mainFrame;
	public ScrollPane scrollPane;
	public BackgroundPanel backgroundPanel;
	public Panel buttonPanel;
	public Panel contentPanel1;
	public Panel contentPanel2;

	
    public static void main(String[] args) {
    	BackGroundTest = new BackGroundTest();
    }
    
	public BackGroundTest() {
		super();
		
		//window
		mainFrame = new Frame();
		
		//the scroll pane
		scrollPane = new ScrollPane();
		
		//set background of frame for test
//		mainFrame.setBackground(Color.blue);
		
		//my background with colored lines
		backgroundPanel = new BackgroundPanel();
		
		//panel with buttons
		buttonPanel = new Panel();
		buttonPanel.setBounds(0, 0, 400, 50);
		
		//my panels with different content
		contentPanel1 = new Panel();
		contentPanel1.setBounds(50, 100, 300, 300);
		contentPanel1.setBackground(Color.red);
		
		contentPanel2 = new Panel();
		contentPanel2.setBounds(50, 100, 300, 300);
		contentPanel2.setBackground(Color.green);

		//put all together
		backgroundPanel.add(buttonPanel);
		scrollPane.add(backgroundPanel);
		mainFrame.add(scrollPane);
		
		//default mainFrame behavior
	    mainFrame.addWindowListener(new WindowAdapter() {
	    	public void windowClosing(WindowEvent event){
	    		System.exit(0);
	    	};
	    });
	    
	    //add buttons
		Button button1 = new Button("contentpanel 1");
		button1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				backgroundPanel.remove(contentPanel2);
				backgroundPanel.add(contentPanel1);
				mainFrame.validate();
			}
		});
		button1.setBounds(50, 0, 50, 25);
		buttonPanel.add(button1);
		
		Button button2 = new Button("contentpanel 2");
		button2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				backgroundPanel.remove(contentPanel1);
				backgroundPanel.add(contentPanel2);
				mainFrame.validate();
			}
		});
		button2.setBounds(150, 0, 50, 25);
		buttonPanel.add(button2);

		//show everything
		mainFrame.setSize(400, 250);
		mainFrame.setVisible(true);
	}
}
```

Und die Klasse mit dem gezeichneten Background:


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;

public class BackgroundPanel extends Panel {
	private static final long serialVersionUID = -6364883255675338017L;

	private Image dbImage;
	private Graphics dbGraphics;
	
	public BackgroundPanel () {
		super();
		setLayout(null);
	}

	public void paint (Graphics g) {
		super.paint(g);
		
		//background colors
		g.setColor(new Color(193, 209, 224));
		g.fillRect(0, 0, 400, 400);

	}
	
	public void update(Graphics g){
		System.out.println("update scroller");
		//initialize double buffer
		if (dbImage == null) {
			dbImage = createImage(this.getSize().width, this.getSize().height);
			dbGraphics = dbImage.getGraphics();
		}
		//delete background
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
		//draw foreground
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		//draw off screen
		g.drawImage(dbImage,0,0,this);
	}
}
```

Mein Debuggpunkt ist in der Zeile "backgroundPanel.remove(contentPanel1);".

Was passiert:
Ich starte das Programm und kann über die beiden Buttons ein rotes oder grünes Panel auf mein BackgroundPanel hinzufügen bzw. entfernen. Das sieht recht flüssig aus.

Wenn man nun das ganze debuggt, kann man erkennen, dass die Zeile "backgroundPanel.remove(contentPanel1);" dazu führt, dass das contentPanel verschwindet und die Farbe des Hintergrunds des BackgroundPanels erscheint. Ich würde mir wünschen, dass in diesem Schritt nicht diese Hintergrundfarbe erscheint, sondern sofort das, was ich in der paint Methode der Klasse BackgroundPanel definiert habe.

Ich denke jetzt ist es wirklich klar, oder?

wimpf

PS: Das ganze läuft auf einem wirklich langsamen Endgerät und ich kann dort praktisch zuschauen, wie nach und nach das Panel mit der Hintergrundgrafik wieder aufgebaut wird.


----------



## Gast2 (8. Jul 2008)

bei mir läuft alles wunderbar... kommt rot und grün


----------



## wimpf (8. Jul 2008)

Das glaube ich dir, SirWayne. Bei mir ja auch. 

Aber während des Wechsels der Panels direkt nach "backgroundPanel.remove(contentPanel1);" verschwindet der gezeichnete Hintergrund des BackgroundPanels und es erscheint die Farbe des BackGroundPanels welche bspw. über setForgroundColor gesetzt werden kann.

Ich hätte an dieser Stelle auch gerne meinen gezeichneten Hintergrund dargestellt auf dem BackGroundPanel und nicht eine einfarbige Fläche.

wimppf


----------



## Gast2 (8. Jul 2008)

es flimmert nichts... die 2 farben kommen sofot hintereinander... 
????????


----------



## wimpf (9. Jul 2008)

Hallo

Also wie gesagt, beim Debuggen (und da hält bei mir in Eclipse die Programmausführung an) an der von mir angegebenen Zeile verschwindet das rot (bzw. grün) und es erscheint die Farbe des BackGroundPanels. Vielleicht kann das jemand anderes auch nachvollziehen und hat eine Lösung für dieses von mir nicht gewollte Verhalten?

Wenn man das Programm durchlaufen läst, fällt der Wechsel fast nicht auf. Aber auf meinem Low-Power Endgerät ist es deutlich zu sehen!

Danke,
Wimpf


----------



## Gast2 (9. Jul 2008)

is ja klar wenn du dein panel removst dass dann erstmal wieder das standard main angezeigt wird und dann wieder ein neues addest erst wieder das neue ...


----------



## wimpf (9. Jul 2008)

Ja klar, SirWayne.

Aber warum wird vom "standard main" nicht sofort der Hintergrund gezeigt welchen ich in der paint Methode überschreibe? Es erscheint einfach die Farbe, welche beim "standard main" als Background definiert ist (bzw. definiert werden kann) und erst später das, was in meinem paint steht. 

Und genau das empfinde ich als flackern.

wimpf


----------



## Gast2 (9. Jul 2008)

wie gesagt bei mir kommt der effekt nicht vor, aber wenn du ein breakpoint setzt is klar dass deine anwendung einfriert und du noch deinen container siehst mit der hintergrundfarbe... erst nachdem validate nimmt er die änderung wahr...


----------



## Marco13 (9. Jul 2008)

Ich erinnere mich an die Windows 3.1-Zeiten. Da gab es keine 3D-Beschleuniger-Karten, sondern "Windows-Beschleuniger", die u.A. dafür gesorgt haben, dass gefüllte Rechtecke möglichst schnell auf dem Bildschirm erschienen. 

Wenn sich irgendwas an der Oberfläche ändert, bekommt Swing/AWT den Aufrag, neu zu zeichnen. WANN dieses Neuzeichnen durchgeführt wird, kann man nicht sagen - das erledigt der EDT.

However - wenn ich es richtg verstanden habe (und sorry: Das ist schon verammt schwer........) dann ist das Flackern egal, aber es soll bitteschön in der Hintergrundfarbe flackern. So vielleicht?


```
// Von [url]http://www.java-forum.org/de/viewtopic.php?t=69705&postdays=0&postorder=asc&start=0[/url]
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;


public class BackGroundTest extends Frame {
   public static BackGroundTest BackGroundTest;
   public Frame mainFrame;
   public ScrollPane scrollPane;
   public BackgroundPanel backgroundPanel;
   public Panel buttonPanel;
   public Panel contentPanel1;
   public Panel contentPanel2;


    public static void main(String[] args) {
       BackGroundTest = new BackGroundTest();
    }

   public BackGroundTest() {
      super();

      //window
      mainFrame = new Frame();

      //the scroll pane
      scrollPane = new ScrollPane();

      //set background of frame for test
//      mainFrame.setBackground(Color.blue);

      //my background with colored lines
      backgroundPanel = new BackgroundPanel();

      //panel with buttons
      buttonPanel = new Panel();
      buttonPanel.setBackground(Color.WHITE);
      buttonPanel.setBounds(0, 0, 400, 50);

      backgroundPanel.setBackground(new Color(193, 209, 224));

      //my panels with different content
      contentPanel1 = new Panel();
      contentPanel1.setBounds(50, 100, 300, 300);
      contentPanel1.setBackground(Color.red);

      contentPanel2 = new Panel();
      contentPanel2.setBounds(50, 100, 300, 300);
      contentPanel2.setBackground(Color.green);

      //put all together
      backgroundPanel.add(buttonPanel);
      scrollPane.add(backgroundPanel);
      mainFrame.add(scrollPane);

      //default mainFrame behavior
       mainFrame.addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent event){
             System.exit(0);
          };
       });

       //add buttons
      Button button1 = new Button("contentpanel 1");
      button1.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e) {
            backgroundPanel.remove(contentPanel2);
            backgroundPanel.add(contentPanel1);
            mainFrame.validate();
         }
      });
      button1.setBounds(50, 0, 50, 25);
      buttonPanel.add(button1);

      Button button2 = new Button("contentpanel 2");
      button2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            backgroundPanel.remove(contentPanel1);
            backgroundPanel.add(contentPanel2);
            mainFrame.validate();
         }
      });
      button2.setBounds(150, 0, 50, 25);
      buttonPanel.add(button2);

      //show everything
      mainFrame.setSize(400, 250);
      mainFrame.setVisible(true);
   }
}


class BackgroundPanel extends Panel {
   private static final long serialVersionUID = -6364883255675338017L;

   private Image dbImage;
   private Graphics dbGraphics;

   public BackgroundPanel () {
      super();
      setLayout(null);
   }

   public void paint (Graphics g) {
      super.paint(g);

      //background colors
      g.setColor(new Color(193, 209, 224));

      double d =0;
      //for (int i=0; i<1000000; i++){ d+=Math.log(Math.tan(1)); } // Verzögerung einbauen, zum Testen....
      g.fillRect(0, 0, 400, 400);

   }

   public void update(Graphics g){
      System.out.println("update scroller");
      //initialize double buffer
      if (dbImage == null) {
         dbImage = createImage(this.getSize().width, this.getSize().height);
         dbGraphics = dbImage.getGraphics();
      }
      //delete background
      dbGraphics.setColor(getBackground());
      dbGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
      //draw foreground
      dbGraphics.setColor(getForeground());
      paint(dbGraphics);
      //draw off screen
      g.drawImage(dbImage,0,0,this);
   }
}
```


----------



## wimpf (9. Jul 2008)

Hallo

und Danke für die Mühe das verstehen zu wollen!

Der Ansatz mit dem Flackern in der Hintergrundfarbe ist schon nicht schlecht. Aber natürlich hatte ich das nur vereinfacht dargestellt in der paint Methode die nur eine Farbe zeichnet. In Wirklichkeit ist es ein Muster aus Linien welches dort gezeichnet wird und man sieht dann wieder das Flackern eindeutig


```
//background colors
		g.setColor(new Color(193, 209, 224));
		g.fillRect(0, 0, 157, panelHeigth);

		g.setColor(new Color(220, 229, 238));
		g.fillRect(157, 0, 1, panelHeigth);
		
		g.setColor(new Color(162, 184, 209));
		g.fillRect(158, 0, 50, panelHeigth);
		
		g.setColor(new Color(220, 229, 238));
		g.fillRect(208, 0, 1, panelHeigth);
		
		g.setColor(new Color(193, 209, 224));
		g.fillRect(209, 0, 17, panelHeigth);
```

Wenn sich das Flackern nicht vermeiden läst, dann habe ich ein echtes Problem. Daher nochmals:

Kann ich mit AWT unter Java 1.4 kein HintergrundPanel erzeugen welches mehr als einen einfarbigen Hintergrund hat und auf welches ich AWT Componenten (bspw. Panels) hinzufügen und entfernen kann ohne dass mir dabei dieser gezeichnete Hintergrund des HintergrundPanels in irgendeiner Art flackert?

Danke,
wimpf


----------



## Gast2 (9. Jul 2008)

da du eh keine layoutmanager benutzt...  versuch mal das hier und sagst mit was du dann für einen effekt bekommst


```
backgroundPanel.add(contentPanel1);
      backgroundPanel.add(contentPanel2);
      contentPanel2.setVisible(false);
      contentPanel1.setVisible(false);
      //default mainFrame behavior
       mainFrame.addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent event){
             System.exit(0);
          };
       });

       //add buttons
      Button button1 = new Button("contentpanel 1");
      button1.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e) {

           contentPanel2.setVisible(false);
           contentPanel1.setVisible(true);
           mainFrame.validate();

         }
      });
      button1.setBounds(50, 0, 50, 25);
      buttonPanel.add(button1);

      Button button2 = new Button("contentpanel 2");
      button2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           contentPanel2.setVisible(true);
           contentPanel1.setVisible(false);
           mainFrame.validate();
         }
      });
```

für was ist die updateMethode eigentlich da?


----------



## wimpf (9. Jul 2008)

Danke SirWayne. Die Idee war auch nicht schlecht, allerdings hat das genau den gleichen Effekt.

Die Update Methode hatte ich einbaut für doublebuffering.

Ich denke Marco13 hat es schon recht gut formuliert:



> Wenn sich irgendwas an der Oberfläche ändert, bekommt Swing/AWT den Aufrag, neu zu zeichnen. WANN dieses Neuzeichnen durchgeführt wird, kann man nicht sagen - das erledigt der EDT.



Und meine nun recht einfach formulierte Frage 


> Kann ich mit AWT unter Java 1.4 kein HintergrundPanel erzeugen welches mehr als einen einfarbigen Hintergrund hat und auf welches ich AWT Componenten (bspw. Panels) hinzufügen und entfernen kann ohne dass mir dabei dieser gezeichnete Hintergrund des HintergrundPanels in irgendeiner Art flackert?



wird wohl letzendlich mit einem "ein solches Panel kann nicht erzeugt werden" beantwortet werden müssen.

wimpf


----------



## Gast2 (9. Jul 2008)

naja bei mir klappt es ja also kannst es nicht so pauschal sagen...
Hast es schon mal Swing versucht?
und soviel ich weiß sagst du dem EDT mit validate();  er soll neu zeichnen


----------

