Graphics objekt sauber in Variable kopieren

Schnubbel

Mitglied
Tach,
folgende Problematik:

Ich habe ein kleines Java Projekt. Grafische ausgabe erfolgt über die AWT, ich benutze ein kleines Eigenbau-DoubleBuffering, folgedessen male ich in meinen Funktionen auf ein Bild, und zeichne das Bild in der paint() auf das Applet.

Was ich vorhabe ist, das Gezeichnete zu einem bestimmten Moment zu speichern, dann weiterzeichnen zu können und das gespeicherte wieder laden zu können, dass die seit der Speicherung vollzogenen änderungen wieder gelöscht werden. DIe Speicherung soll nicht übers Dateisystem geschehen, sondern nur in eine Variable - trotzdem bekomme ich es nicht hin.
Hier ein paar Code-Fetzen zu dem Thema:
Code:
//Deklarationen in der Klasse
private Graphics gc, gc_copy;
private Image img;

public void init() {
	img = createImage(breite, hoehe);
	gc = img.getGraphics();
}

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

public void speichern() {
	gc_copy = gc.create();
	//im manual stand, gc.create() würde einen Klon des objektes ausgeben...gc_copy = gc hilft genau so wenig
	repaint();
}

public void laden() {
	gc = gc_copy;
	//der Kommentar von oben (create()) gilt auch für hier
	repaint();
}
Man kann bei diesem Code laden und speichern wie man lustig ist, es wird immer das alte Bild angezeigt und auch darauf weitergezeichnet.
Wahrscheinlich ist der Fehler ziemlich dämlich, und ich sitze nur schon zu lange davor, um ihn selbst zu finden, wäre nett wenn mir jemand weiterhelfen würde!

Danke
TiM
 
Moin,
wenn Graphics.create() nicht funktioniert, probier doch mal clone(), vielleicht klappt das ja.
Im übrigen ist es wenig glücklich, eine Instanzvariable so zu nennen wie einen Übergabeparameter, s.u. Bedenke, dass die paint()-Methode automatisch vom System aufgerufen wird, wenn die entsprechende Komponente angezeigt werden soll, somit nicht in Deiner Kontrolle liegt.

Code:
//Deklarationen in der Klasse
private Graphics gc, gc_copy;
private Image img;

public void init() {
img = createImage(breite, hoehe);
gc = img.getGraphics();
}

public void paint(Graphics gc) {
if ( img != null )
 gc.drawImage( img, 0, 0, this );
}
 
Hallo!

Kann es sein, dass du vielleicht Tripple Bufferung machen willst?
Andernfalls nimm doch einfach noch ein Image in das du deine Grafikausgabe zeichnest. Zeichne dann dieses Image auf das Off-screen Image und zeichne danach dieses auf den Screen. Ein graphics.create(int x,
int y,
int width,
int height)
bringt dir hier nicht viel, da die Graphicsreferenz du du nach dem Aufruf erhälst immernoch auf das Graphicsobjekt referenziert auf dem es erstellt wurde. Es zeigt dann den Ausschnitt aus dem "alten" Graphicsobjekt der mit x,y,width,heigth
spezifiziert ist. Anlog dazu graphics.create(); ...

(steht so in API Doc unter Graphics)

Wie schon gesagt versuchs einfach mal mit 2 Images ...
kannst ja das folgende Fragment als Ausgangspunkt nehmen...

Code:
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

/**
 * @author      Darimont<br>
 * @version     1.0<br>
 * Date of creation:  07.06.2004<br>
 * File:         AWTDblBuffer.java<br>
 * Modifier:     Darimont<br>
 * Revision:     Revision<br>
 * State:        Germany<br>
 */

public class AWTDblBuffer extends Frame {
	
	//Unser Off-Screen Image in das wir zeichnen wollen...	
	private BufferedImage offScreen;
	//Der Grafikkontext des OffScreen Images mit dem wir Zeichenoperationen auf das
	//Off-Screen Image ausführen können. 
	private Graphics gOffScreen;

	public AWTDblBuffer() {
		super("AWT Double Buffer");
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				dispose();
				System.exit(0);
			}
		});
		
		//Off-Screen Image erstellen.
		offScreen = new BufferedImage(320, 240, BufferedImage.TYPE_INT_RGB);
		//Graphics Kontext besorgen
		gOffScreen = offScreen.getGraphics();

		drawSomething();

		setSize(320, 240);
		setVisible(true);
	}

	/**
	 * Irgendwas auf das BufferedImage zeichnen
	 */
	private void drawSomething() {
		gOffScreen.setColor(Color.WHITE);
		//Ins Off-Screen Image Zeichnen
		gOffScreen.fillRect(40, 40, 80, 80);
	}

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

	public void paint(Graphics g) {
		//Das Off-ScreenImage auf den Bildschirm bringen
		g.drawImage(offScreen, 0, 0, this);
	}
}

Gruß Tom
 
Original geschrieben von Thomas Darimont Kann es sein, dass du vielleicht Tripple Bufferung machen willst?
Wenn das, was in deinem Beispiel beschrieben ist Double Buffering ist, dann schon brauche ich scheinbar TrippleBuffering ;)

Danke für den Code, auch an Snape, aber das eigentliche Problem liegt darin, das Image "offScreen" in deinem Beispiel, Tom, nochmals zwischenzuspeichern.
Nehmen wir als Beispiel eine primitive Applikation à la Paint. Will ich ein Rechteck bei gedrückter Maustaste temporär zeichnen, und beim Loslassen fest auf der Canvas verankern brauche ich einen Snapshot, der beim drücken der Maustaste erstellt wird, und auf dem immer wieder temporäre Viereckt gezeichnet werden...sonst hätte ich ja bei jedem aufruf der mouseDragged ein neues statisches Rechteck, dass die Canvas vollkrickelt.
Das Problem ist also, die Objektvariable zu kopieren, momentan scheint bei mir eine Art Zeiger zu entstehen.
Außerdem noch die Frage, wo genau der Vorteil der Verwendung eines "BufferedImage" gegenüber eines "Image" liegt...der EInfachkeit halber habe ich bis jetzt immer auf die Canvas-BufferStrategy zurückgegriffen, die allerdings meine Idee nicht zu mögen schien und mich zu einer eigenen (mißlungenen) Lösung zwang.

Dank & Gruß
TiM
 
Zurück