Page 1 of 2 12 LastLast
Results 1 to 20 of 21
  1. #1
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Question Drawing Serializable, how to save/load?

    Hello all!

    I've made a program where you could click points, and a line will appear between them. In this way you could make drawings (using ArrayList of Points). Now I want to save the drawing, and load the drawing. I made the class 'Tekening' Serializable. I'll post part of the Panel class here, just to make sure you understand the names.

    I think I tried the wrong ting to save/load. I already tried to save the Points, but didn't work... Here is part of the code as I have it now.

    Java Code:
    public class TekenPaneel extends JPanel implements ActionListener, MouseListener, KeyListener, MouseMotionListener
    {
      private ArrayList<Tekening> tekeningen = new ArrayList();
      private Tekening huidigeTekening, tekeningtest;
      private boolean links = false, rechts = false, omhoog = false, beneden = false;
      private Random random = new Random();
      private Timer timer = new Timer(10, this);
      private JFrame venster;
      private FileDialog dialoogvenster;
      private JButton openKnop, saveKnop;
    
      public void nieuweTekening()
      {
        int red = this.random.nextInt(256);
        int green = this.random.nextInt(256);
        int blue = this.random.nextInt(256);
        Color kleur = new Color(red, green, blue);
    
        huidigeTekening = new Tekening(kleur);
        tekeningen.add(huidigeTekening);
      }
    
    	public void bestandschrijven()
    	{
    		dialoogvenster =
    			new FileDialog( venster, "Bewaar een bestand", FileDialog.SAVE);
    		dialoogvenster.setVisible( true );
    		String bestandsnaam = dialoogvenster.getFile();
    		if (bestandsnaam != null)
    		{
    			String padEnBestand = dialoogvenster.getDirectory() + bestandsnaam;
    			try
    			{
    			ObjectOutputStream uit = new ObjectOutputStream( new FileOutputStream( padEnBestand ));
    
    			uit.writeObject( huidigeTekening );
    			System.out.println(tekeningen + "HuidigeTekeningenOpslaan:");
    			tekeningen.clear();
    			repaint();
    		    uit.close();
    		    }
    			catch (IOException ex)
    			{
    				JOptionPane.showMessageDialog(
    				null, 
    				"Er is een fout opgetreden bij het schrijven.", 
    				"Bewaren van bestand is mislukt", 
    				JOptionPane.WARNING_MESSAGE);
    			}
    		}
    	}
    	
    	public void bestandlezen()
    	{
    		dialoogvenster =
    			new FileDialog( venster, "Open een bestand", FileDialog.LOAD );
    		dialoogvenster.setVisible( true );
    		String bestandsnaam = dialoogvenster.getFile();
    		if (bestandsnaam != null)
    		{
    			String padEnBestand = dialoogvenster.getDirectory() + bestandsnaam;
    			try
    			{
    				System.out.println( "EERSTE TEST:" + tekeningtest );
    		        ObjectInputStream in = new ObjectInputStream( new FileInputStream( padEnBestand ) );
    		        tekeningtest = (Tekening) in.readObject();
    		        repaint();
    				System.out.println( "TWEEDE TEST:" + tekeningtest );
    				in.close();
    		    }
    			catch (IOException ex)
    			{
    				JOptionPane.showMessageDialog(
    				null, 
    				"Er is een fout opgetreden bij het lezen.", 
    				"Inlezen van het bestand is mislukt", 
    				JOptionPane.WARNING_MESSAGE);
    			}
    			catch ( ClassNotFoundException ex )
    			{
    				JOptionPane.showMessageDialog(
    				null, 
    				"Er is een fout opgetreden bij het lezen.", 
    				"Inlezen van het bestand is mislukt", 
    				JOptionPane.WARNING_MESSAGE);
    			}
    		}
    	}
      
      public void paintComponent(Graphics g)
      {
        super.paintComponent(g);
    
        for (Tekening tekening : this.tekeningen)
        {
          tekening.teken(g);
        }
      }
    }
    Thanks already!
    Last edited by warchieflll; 01-03-2011 at 05:56 PM. Reason: Deleting some more code, too much to read :)

  2. #2
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Does the Tekening class implement Serializable? If not, that's the problem.

  3. #3
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    yup:

    Java Code:
    public class Tekening extends JPanel implements Serializable

  4. #4
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Ok, so next you need to make sure that every class contained in Tekening that you are expecting to be serialized also implements Serializable. For example, Point2D does not implement Serializable, so if you are using those to store the points, they will not serialize.

  5. #5
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Eehm... I do not really understand where to put more 'implements Serializable'... I set it in the constructor of Tekening. But I coudn't set 'implements Serializable' after, for example, 'public void teken(Graphics g)'... Also, I haven't a Point2D anywhere in my class Tekening. But I do make Points indeed...

    A little more question: I try to save drawings. Now, do I need to save the arraylist of Points, so the drawing could rebuild, or do I need to save a whole drawing somehow?

  6. #6
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    I've put 'transient' in the Tekening class.. you mean this?

    Java Code:
    	transient public ArrayList<Point> punten = new ArrayList();
    	transient private Color kleur;

  7. #7
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,783
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by warchieflll View Post
    I've put 'transient' in the Tekening class.. you mean this?

    Java Code:
    	transient public ArrayList<Point> punten = new ArrayList();
    	transient private Color kleur;
    No, the contrary: if you mark a member as transient it won't be serialized at all. For an object of class C, the class C needs to implement the Serializable interface and all the members of that class C also need to implement the Serializable interface (unless you mark them as transient).

    Note that the Point2D class doesn't implement the Serializable interface but the two nested classed Point2D.Double and Point2D.Float do so.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  8. #8
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Eehm... I don't really get it. You mean with the 'class C' my class Tekening I guess? (dataclass)?

    So... what do I actually need to add to the code now? I've the 'implements Serializable' in the 'Tekening' class, and I removed the 'transistent'...

  9. #9
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    It would help if you post the code for the Tekkening class.

  10. #10
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Here is the full code:

    Java Code:
    package tekenApplicatie;
    
    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import java.io.*;
    
    /**
     * @author Bjorn Hoogeveen
     */
    
    public class Tekening extends JPanel implements Serializable
    {
    	public ArrayList<Point> punten = new ArrayList();
    	private Color kleur;
    
      /**
       * Bepaal de kleur van de tekening (gegeven in het TekenPaneel)
       * @param kleur
       */
      
      public Tekening(Color kleur)
      {
        this.kleur = kleur;
      }
    
      /**
       * Voeg een punt toe (bij een klik)
       * @param punt
       */
      
      public void voegPuntToe(Point punt)
      {
        punten.add(punt);
      }
    
      /**
       * Indien de tekening verplaatst moet worden, voer deze methode uit. Voor elke punt wordt de coordinaten opgehaald, en vervolgens waardes aan toegevoegd of hiervanaf gehaald. Hierna worden dus alle punten verplaatst, waardoor de tekening verschuift.
       * @param verplaatsX
       * @param verplaatsY
       */
      
      public void verplaats(int verplaatsX, int verplaatsY)
      {
        for (Point punt : punten)
        {
          double x = punt.getX() + verplaatsX;
          double y = punt.getY() + verplaatsY;
          punt.setLocation(x, y);
        }
      }
    
      /**
       * Teken methode; stel de kleur in. Stel een xOud en yOud in, en vervolgens maak boolean eerste true. Voor elk punt haal de x en y waardes op, en teken een rondje (een punt). Als het eerste punt waar is, teken alleen een punt, en als de eerste niet waar is, dan teken je een punt plus een lijn van x en y, naar xOud en yOud.
       * @param g
       */
      
      public void teken(Graphics g)
      {
        g.setColor(kleur);
    
        int xOud = 0;
        int yOud = 0;
        boolean eerste = true;
    
        for (Point punt : this.punten)
        {
          int x = Math.round((float)punt.getX());
          int y = Math.round((float)punt.getY());
          g.fillRect(x - 5, y - 5, 10, 10); // helft van 10 voor midden van muis
    
          if (!eerste)
          {
            g.drawLine(x, y, xOud, yOud);
          }
          else
          {
            eerste = false;
          }
    
          xOud = x;
          yOud = y;
        }
      }
    }

  11. #11
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    That looks ok. I don't see anything fundamentally wrong. Are you seeing the message associated with "System.out.println(tekeningen + "HuidigeTekeningenOpslaan:");" ? Are you seeing any exceptions? Is huidigeTekening empty at the time it is being written?

  12. #12
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Eeh... I'm seeing this when I run:

    When saving:

    [tekenApplicatie.Tekening[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=]]HuidigeTekeningenOpslaan:

    When opening:

    EERSTE TEST:null
    TWEEDE TEST:tekenApplicatie.Tekening[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=]

  13. #13
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Try adding to the println to see what the size of tekeningen.punten is when you save. I'm guessing it's size is 0.

  14. #14
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    System.out.println(tekeningen.size());

    results in 0 indeed...

    System.out.println(huidigeTekening.punten.size());

    results in a number of points drawing in the last Tekening (a new Tekening starts by pressing right, what makes the color different).

    So... the last command results in a number of points (of the last drawing)
    Last edited by warchieflll; 01-03-2011 at 11:48 PM. Reason: more information :)

  15. #15
    Jodokus's Avatar
    Jodokus is offline Senior Member
    Join Date
    Jan 2011
    Location
    Amsterdam, the Netherlands
    Posts
    230
    Rep Power
    4

    Default

    In my opinon you're doing almost everything OK.
    You save your model, the tekening with all the info needed to restore it later (only that class needs to be marked "Serializable", as remarked by JosAH, and "transient" is only to tell that some fields don't need to be stored). I only don't see you putting the restored "tekeningtest" back in "tekeningen", which is the only thing you draw in paintComponent(). I think you confused it with ''huidigeTekening" which is stored and could be used as a reference to an object in "tekeningen".

  16. #16
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Hmm yea I think that's it. I haven't solved the problem yet, but I see the problem now. I changed it to 'huidigeTekening = (Tekening) in.readObject();'. If I'm correct I now could delete the 'tekeingentest' completely?

    Now the output of System.out.println(huidigeTekeing) is:

    EERSTE TEST:tekenApplicatie.Tekening[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=]
    TWEEDE TEST:tekenApplicatie.Tekening[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=]

    So it is exactly the same still...

  17. #17
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Woowwwh! I did it!!! I had to save the arraylist 'tekeningen', instead of only a object from the class 'Tekening'.

    In 'bestandschrijven()' (save)
    Java Code:
    	uit.writeObject( tekeningen );
    in 'bestandlezen()' (load)
    Java Code:
            tekeningen = (ArrayList) in.readObject();
    Thanks for all the help!!!

  18. #18
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,224
    Rep Power
    20

    Default

    Can I make a suggestion?
    Serialisation can be a bit of a minefield and it's generally best to try and reduce what actually needs to be serialised to a minimum, so you avoid dependencies as much as possible.

    In your case it looks to me like you only actually need to serialise the points, and the color. Now, you could even reduce the Points to your own class if need be (should Point be a problem class). I always twitch when I see people serialising JPanels, which you are doing at the moment.

    So, create a class representing the model for your drawing (that is your Points array, and the color) and serialise that. Have the JPanel hold that model and read from it.

    ETA: Oh, looks like you've done that...:)

  19. #19
    warchieflll is offline Member
    Join Date
    Dec 2010
    Posts
    55
    Rep Power
    0

    Default

    Eerm, at the moment I've the class Tekeningen, which has the 'implements Serializable'. Everything works great now. Ty for all the help!

  20. #20
    Jodokus's Avatar
    Jodokus is offline Senior Member
    Join Date
    Jan 2011
    Location
    Amsterdam, the Netherlands
    Posts
    230
    Rep Power
    4

    Default

    You didn't close the thread, so I feel free to post again :>)
    Tolls warned you, and now I do the same. I'm working on "the same" application (that's why I was interrested in the first place), I serialized too, made some great drawings, changed some code (empty edges were null first and have a getter now), and the saved drawings are unreachable now (I knew the risk, but anyway).
    I'm experimenting now with XmlEncoder/Decoder (see the tips-section on this forum). I didn't finish refactoring, but it seems to work fine. The Xml contains only the fields, is
    viewable/editable and the code is far less sensitive to codechanges.
    I now think standard serialisation is for VERY stable products, datacommunication and/or deepcopies.

Page 1 of 2 12 LastLast

Similar Threads

  1. Save/Load ArrayList
    By chielt in forum New To Java
    Replies: 3
    Last Post: 05-08-2011, 07:12 PM
  2. Drawing Serializable, how to save/load?
    By warchieflll in forum New To Java
    Replies: 1
    Last Post: 01-03-2011, 05:06 PM
  3. Load and Save images
    By shakeel in forum Java 2D
    Replies: 13
    Last Post: 12-29-2010, 07:38 PM
  4. Arraylist Save and Load
    By frankycool in forum Advanced Java
    Replies: 1
    Last Post: 11-14-2009, 11:29 PM
  5. How to Save/Load Vector to/from file
    By Java Tip in forum java.lang
    Replies: 0
    Last Post: 04-14-2008, 09:37 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •