Bild im ImagePanel (AWT) wird nur machmal neu gezeichnet

Status
Nicht offen für weitere Antworten.
W

wimpf

Gast
Hallo

ich zeichne in Java 1.3 unter AWT mit folgendem überschriebenen Panel Grafiken:
Code:
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
 
W

wimpf

Gast
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:

Code:
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

Code:
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

Top Contributor
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.
 
W

wimpf

Gast
Hallo

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

Code:
	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.

Code:
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.

Code:
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

Top Contributor
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.
 
W

wimpf

Gast
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
 
W

wimpf

Gast
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:

Code:
	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:
Code:
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

Top Contributor
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.
 
G

Gast2

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

wimpf

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

Die Klasse BackGroundTest:

Code:
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:

Code:
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.
 
W

wimpf

Gast
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
 
G

Gast2

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

wimpf

Gast
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
 
G

Gast2

Gast
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 ...
 
W

wimpf

Gast
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
 
G

Gast2

Gast
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

Top Contributor
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?

Code:
// 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);
   }
}
 
W

wimpf

Gast
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

Code:
		//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
 
G

Gast2

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

Code:
      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?
 
W

wimpf

Gast
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
 
G

Gast2

Gast
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
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M JavaFX Mandelbrot-bild noch nicht optimiert AWT, Swing, JavaFX & SWT 7
berserkerdq2 Wie füge ich ein Bild in javafx mit dem Scenebuilder ein, das automatisch mitgezogen wird, wenn das Fenster vergrößert wird oder Vollbildmodus AWT, Swing, JavaFX & SWT 6
frager2345 Bild aus Dateien lesen und als Hintergrund verwenden AWT, Swing, JavaFX & SWT 2
T Bild in ein graphics füllen AWT, Swing, JavaFX & SWT 2
N imageIcon zeigt kein Bild an AWT, Swing, JavaFX & SWT 5
B Bild lädt nicht AWT, Swing, JavaFX & SWT 2
izoards Bild ausdrucken - PageFormat setzen geht nicht AWT, Swing, JavaFX & SWT 5
M Bild wird nicht geladen obwohl sie gefunden wird AWT, Swing, JavaFX & SWT 0
V JavaFX Bild leer und keine Fehlermeldung AWT, Swing, JavaFX & SWT 21
D JavaFX Bearbeitetes Bild wird nicht gespeichert AWT, Swing, JavaFX & SWT 9
D JavaFX Größe des Bild an ImageView anpassen AWT, Swing, JavaFX & SWT 3
M Bewegtes Bild im BorderLayout.CENTER AWT, Swing, JavaFX & SWT 6
C Falschfarbenbild (lineare Grauwertspreizung)aus Grauwert-Bild erstellen AWT, Swing, JavaFX & SWT 15
C Kleineres Bild an bestimmte Koordinaten setzen AWT, Swing, JavaFX & SWT 6
S Bild neu skalieren - Bild in Bild speichern? AWT, Swing, JavaFX & SWT 6
N Bild Drehen AWT, Swing, JavaFX & SWT 1
Hatsi09 Swing JPanel Bild einfügen AWT, Swing, JavaFX & SWT 14
J Bild von anderer Klasse will nicht laden AWT, Swing, JavaFX & SWT 1
M JavaFX Bild zur ImageView in einem Kreis anzeigen. AWT, Swing, JavaFX & SWT 4
T JFrame Bild einfügen AWT, Swing, JavaFX & SWT 9
M Combobox bild anklicken AWT, Swing, JavaFX & SWT 2
cool_brivk24 Swing ImageIcon lädt kein Bild AWT, Swing, JavaFX & SWT 12
L Bild nicht in der Mitte AWT, Swing, JavaFX & SWT 16
B JavaFX Bild um die eigene Achse drehen lassen AWT, Swing, JavaFX & SWT 0
J Swing Bild in Button AWT, Swing, JavaFX & SWT 11
I Bild über FXML (ImageView, Image) anzeigen AWT, Swing, JavaFX & SWT 1
T Image Loader lädt Bild nicht AWT, Swing, JavaFX & SWT 10
stroggi Swing Mehrere transparentes Objekte (Grafiken) über einem Bild (JLabel) darstellen AWT, Swing, JavaFX & SWT 4
P Kein Bild wird angezeigt bei ImageIcon AWT, Swing, JavaFX & SWT 16
T JavaFX Bild in Tabellenzelle AWT, Swing, JavaFX & SWT 2
Ksanatos Swing Bild (.jpg) einlesen und per Button wechseln AWT, Swing, JavaFX & SWT 9
S JPanel rotieren, Bild ist abgeschnitten, Clipping? AWT, Swing, JavaFX & SWT 0
MaxG. Swing Bild Button AWT, Swing, JavaFX & SWT 7
P Swing Bild Skallieren AWT, Swing, JavaFX & SWT 1
P Jframe Bild einfügen, Hintergrund Farbe ändern, und Button schrift Größe ändern AWT, Swing, JavaFX & SWT 2
A Swing Bild wird nicht mehr geladen AWT, Swing, JavaFX & SWT 4
A Swing Gemaltes Bild über saveDialog speichern unter AWT, Swing, JavaFX & SWT 15
R 2D-Grafik PNG Bild per Graphics auf JPanel AWT, Swing, JavaFX & SWT 9
S Bild mit ImageIcon auf GUI verkleinern AWT, Swing, JavaFX & SWT 3
T AWT Farben in einem Bild ändern AWT, Swing, JavaFX & SWT 8
I JFrame Bild strecken und auf Bildschirmgröße anpassen AWT, Swing, JavaFX & SWT 2
F Gezeichnetes als bild speichern AWT, Swing, JavaFX & SWT 4
B 2D-Grafik Bild farblich filtern AWT, Swing, JavaFX & SWT 2
B JavaFX ImageView neues Bild zuweisen AWT, Swing, JavaFX & SWT 19
A 2D-Grafik Bild wird nicht neu gezeichnet AWT, Swing, JavaFX & SWT 24
K Bild in JFrame AWT, Swing, JavaFX & SWT 2
S JavaFX Teil eines Bildes ausschneiden / als neues Bild nutzen AWT, Swing, JavaFX & SWT 8
B Swing Unterteiltes JFrame mit Bild in der Mitte AWT, Swing, JavaFX & SWT 4
I Applet BlueJ Applet - Bild mit if-Schleife zeichnen lassen AWT, Swing, JavaFX & SWT 16
Z Bildervorschau, MouseDragged das Bild verschieben AWT, Swing, JavaFX & SWT 1
M JavaFX Ein Bild ohne Rahmen fällt runter? AWT, Swing, JavaFX & SWT 2
G Anonyme Instanz von JXImageView erstellen und mit Bild initialisieren AWT, Swing, JavaFX & SWT 7
A JPanel Bild laden (Porblem mit Dateipfad) AWT, Swing, JavaFX & SWT 2
M JavaFX - Bild in Jar einbinden, sodass es auch außerhalb der IDE geladen wird. AWT, Swing, JavaFX & SWT 2
M Bild Beschreibung mit ImageIO speichern AWT, Swing, JavaFX & SWT 1
M "ImageIO.read()" liest Bild nicht richtig ein AWT, Swing, JavaFX & SWT 3
I Swing JLabel Bild für 1sec anzeigen lassen AWT, Swing, JavaFX & SWT 13
K Bild in Label wird nicht angezeigt AWT, Swing, JavaFX & SWT 5
C GUI öfters durchlaufen und hinterher Bild speichern AWT, Swing, JavaFX & SWT 1
M AWT Farben in Bild ersetzen AWT, Swing, JavaFX & SWT 11
E JavaFX Bild einfügen AWT, Swing, JavaFX & SWT 6
G paintComponents zerstückelt Bild AWT, Swing, JavaFX & SWT 0
C 2D Grafik ein Bild soll permanent durchlaufen AWT, Swing, JavaFX & SWT 2
1 Textfield: jede Buchstabe ein Bild AWT, Swing, JavaFX & SWT 2
C Bild Koordinaten AWT, Swing, JavaFX & SWT 6
M Bild aus JLabel resizen und speichern AWT, Swing, JavaFX & SWT 0
M Bild in JPanel mit Maus einfügen AWT, Swing, JavaFX & SWT 0
B JPanel und png-Bild AWT, Swing, JavaFX & SWT 2
B Swing Bild von Webseite herunterladen, diese dann in JList anzeigen. AWT, Swing, JavaFX & SWT 1
O 2D-Grafik Bild abgeschnitten nach Rotation mit Affine Transform und Hintergrund Schwarz AWT, Swing, JavaFX & SWT 8
A Swing Malprogramm Bild speichern? AWT, Swing, JavaFX & SWT 9
U Bild innerhalb hatml code anzeigen AWT, Swing, JavaFX & SWT 5
Y JavaFX Bild speichern und Pfad dazu abspeichern AWT, Swing, JavaFX & SWT 2
S Geladenes Bild wird nicht in JPanel angezeigt AWT, Swing, JavaFX & SWT 7
L 2D-Grafik Bild in Richtung Maus drehen AWT, Swing, JavaFX & SWT 18
C Bild in JFrame AWT, Swing, JavaFX & SWT 8
T AWT Bild laden und transparent zeichnen AWT, Swing, JavaFX & SWT 2
I SWT Bilder, bzw. ein einzelnes Bild AWT, Swing, JavaFX & SWT 6
L JavaFX: Bild in Image einlesen AWT, Swing, JavaFX & SWT 11
T Mit getSubimage ruckelt das Bild AWT, Swing, JavaFX & SWT 7
T Bild drehen ohne Resize AWT, Swing, JavaFX & SWT 3
A Bild in JLabel skalieren AWT, Swing, JavaFX & SWT 4
A Bild über Imageviewer auf GUI anzeigen AWT, Swing, JavaFX & SWT 3
D 3D-Grafik [JOGL] streifen im bild AWT, Swing, JavaFX & SWT 2
D Bild bewegen mit Tastendruck AWT, Swing, JavaFX & SWT 7
H Bild wird nicht angezeigt, Fehlercode unverständlich AWT, Swing, JavaFX & SWT 5
J 2D-Grafik Bildteile in ein anderes Bild speichern AWT, Swing, JavaFX & SWT 12
C Swing ImageIcon mit Bild aus Temp-Verzeichniss füllen AWT, Swing, JavaFX & SWT 15
J Swing Bild laden, Kreise drin malen, Schreiben AWT, Swing, JavaFX & SWT 2
S Bild skalieren AWT, Swing, JavaFX & SWT 3
D Bild in JFrame nur kurz da AWT, Swing, JavaFX & SWT 9
H Bild mit KeyListener verschieben AWT, Swing, JavaFX & SWT 2
GianaSisters Bild wird S/W gespeichert. AWT, Swing, JavaFX & SWT 4
O Bild auf das JLabel AWT, Swing, JavaFX & SWT 10
D Swing Text auf Bild legen AWT, Swing, JavaFX & SWT 7
S Ein externes Bild in ein JFrame einfügen AWT, Swing, JavaFX & SWT 8
J Swing Bild wird nicht auf JLabel angezeigt AWT, Swing, JavaFX & SWT 12
S Swing Bild auf jPanel nach Änderung von JComboBox zeichnen AWT, Swing, JavaFX & SWT 4
R Bild in Bild finden AWT, Swing, JavaFX & SWT 4
B Bild bearbeiten mit Transparenz (spiegeln, Farben austauschen) AWT, Swing, JavaFX & SWT 8

Ähnliche Java Themen

Neue Themen


Oben