Serialisierung vom JPanel mit paintComponent()

maltor

Mitglied
Hi,


Ich habe ein JPanel geschrieben das mit der mehtode paintComponent(Graphics g)
ein Bild als Hintergrund darstellt. Auf das Panel werden Bilder per Drag and Drop gezogen.


Diese Klasse möchte ich nun serialisieren(in einer Datei schreiben), wenn ich das nun speichertn will bekomme ich eine java.io.NotSerializableException: sun.awt.image.ToolkitImage Exception.


Nun ich meine Frage wie kann ich das Problem lösen.


Dieses ist nur ein Ausschnitt des Codes.


Code:
public class SinkPanel extends JPanel implements DropTargetListener,Serializable {
  
private Image img;
 
public SinkPanel(....) {
    
     loadImage(this.img_path,this.screen_size);
 }
 

 public void loadImage(String img_path, Dimension screen_size) {
 
this.img = getToolkit().getImage(img_path);      
            MediaTracker mt = new MediaTracker(this);
            mt.addImage(this.img, 0);

try {
              mt.waitForAll();


            } catch (InterruptedException e) {
//nothing
            }
   }
 

public void paintComponent(Graphics g) {
  
      g.drawImage(this.img, 0, 0, this.new_img_width,this.new_img_height, null);
}

}
mfg malte
 
Moin!
Kurze Frage.. wieso willst du denn einen Teil der GUI serialsieren? Das macht doch überhaupt keinen Sinn. Was bezweckst du denn damit?

*grüssle*
MeinerEiner
 
Für mein Programm das ich programmiere macht das Sinn.


Ich bin dabei ein Visualisierungs-Programm zu schreiben. Über eine seriellen Schnittstelle bekomme ich Dateien von einer Anlage, z.B ein bestimmt Kontakt wurde geschlossen.


Mit dem Programm kann der Benutzer sich ein Visualisierung erstellen (Grafische anzeige der Kontakte). Der Benutzer kann in einen JTree Knoten anlegen und jeder Knoten verweist dann auf so einen SinkPanel (Quelltext steht oben) , diesen SinkPanel kann der User dann ein Hintergrundbild geben ( paintComponent(Graphics g) ). Auf dieses SinkPanel können die im Programm erstellte Labels mit einem Bild auf das SinkPanel gezogen werden. Wenn nun ein Kontake auslöst (serielle Schnittstelle z.B Kontakt 1 ein),
bekommt das Label einen vorher zugeordnete Border Farbe.


Nun will der User seine erstellte Visualisierung speichern, also müssen die einzelnen SinkPanel gespeichert werden. Diese in zur Laufzeit in einen Baum gespeichert.
 
Moin!
Dennoch, ich finde man sollte nicht die SinkPanels abspeichern, sondern Das, was die einzelnen Panels unterscheidet. In deinem Fall wären dies wohl das Hintergrund Bild(bzw. dessen Pfad) und die einzelnen JLabels, bzw. deren Texte. All diese Informationen einfach in eine geeignete Datenstruktur ablegen und dieses dann abspeichern. Und natürlich dann eine Methode erstellen, mit der man ein SinkPanel durch eine geladene Datenstruktur wieder initialisieren kann.
So würde ich es halt machen...

Aber wenn du dennoch drauf bestehst, kannst du natürlich auch das SinkPanel abspeichern. Allerdings nicht serialisiert. Stattdessen, wie auch von Sun empfohlen (http://java.sun.com/developer/JDCTechTips/2003/tt0805.html#2)um Swing Objekte abzuspeichern, würde ich den XMLEncoder nutzen.
Beispiel:
Code:
SinkPanel p = new SinkPanel(path,dimension);
            XMLEncoder e = new XMLEncoder(
                     new BufferedOutputStream(
                         new FileOutputStream("E:/Test.xml")));
                             e.writeObject(p);
                             e.flush();        
                             e.close();

Bilder kannst du auf diese Weise allerdings auch nicht abspeichern. Der Pfad muss dir also reichen.
Und es gilt noch weiteres zu beachten.. Für den XMLEncoder muss die zu speichernde Klasse den Java Bean Anforderungen genügen.. also Leerer Konstruktor muss (zusätzlich) vorhanden sein, getter und setter Methoden für die Attribute (ausser für das Image, das wollen wir ja net)...
Hab das mal mit deinem geposteten Quellcode ausprobiert gehabt und klappt tadellos.

Code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class SinkPanel extends JPanel implements DropTargetListener{
  
private BufferedImage img= null;
private String img_path = "";
private Dimension screen_size = null;
 
public SinkPanel(){
	
}
public SinkPanel(String path, Dimension dim) {
    	this.img_path = path;
this screen_size = dim;
     loadImage(path,dim);
 }
 

 public void loadImage(String img_path, Dimension screen_size) {
 
	 try {
		this.img = ImageIO.read(new File(img_path));
	} catch (IOException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
            MediaTracker mt = new MediaTracker(this);
            mt.addImage(img, 0);

try {
              mt.waitForAll();


            } catch (InterruptedException e) {
//nothing
            }
   }
 

public void paintComponent(Graphics g) {
		if(this.img == null)
			this.loadImage(this.img_path, this.screen_size);
      g.drawImage(this.img, 0, 0, 50,50, null);
}


public void dragEnter(DropTargetDragEvent arg0) {
	// TODO Auto-generated method stub
	
}


public void dragExit(DropTargetEvent arg0) {
	// TODO Auto-generated method stub
	
}


public void dragOver(DropTargetDragEvent arg0) {
	// TODO Auto-generated method stub
	
}


public void drop(DropTargetDropEvent arg0) {
	// TODO Auto-generated method stub
	
}


public void dropActionChanged(DropTargetDragEvent arg0) {
	// TODO Auto-generated method stub
	
}
public String getImg_path() {
	return img_path;
}
public void setImg_path(String img_path) {
	this.img_path = img_path;
}
public Dimension getScreen_size() {
	return screen_size;
}
public void setScreen_size(Dimension screen_size) {
	this.screen_size = screen_size;
}


}
Aufruf
Code:
try
	     {
			 JFrame j = new JFrame();
			 SinkPanel p = new SinkPanel("E:/01.jpg", new Dimension(20,20
));
			 j.getContentPane().add(p);
			 j.setSize(300,300);
			 j.setVisible(true);
			 
			 XMLEncoder e = new XMLEncoder(
                     new BufferedOutputStream(
                         new FileOutputStream("E:/Test.xml")));
			 				e.writeObject(p);
			 				e.flush();		
			 				e.close();
			 XMLDecoder d = new XMLDecoder(
			 		                          new BufferedInputStream(
			 		                              new FileInputStream("E:/Test.xml")));
			 		       SinkPanel result = (SinkPanel) d.readObject();
			 		      
			 		       d.close();
			 		       System.out.println(result.getImg_path());
			 		      JFrame j1 = new JFrame();
			 			
			 			 j1.getContentPane().add(result);
			 			 j1.setSize(300,300);
			 			 j1.setVisible(true);

So, ich hoffe mal das hilft weiter...
(Sorry für die Formatierung.. aber da hatt ich jetzt keine Lust mehr drauf ;))

*grüssle*
MeinerEiner
 
Zuletzt bearbeitet von einem Moderator:
Danke,
habe das gerade in meinen Code eingesetzt, es funktioniert.



Nun muss ich mal sehen wie ich das
umsetze. Auf dem SinkPanel werden ja noch die label add(Jlabel label) eingefügt. Und die SinkPanel's sind dann ja noch in einem Baum. Da muss ich mir nun mal was überlegen, das sieht nach viel Arbeit aus.
 

Neue Beiträge

Zurück