Search code examples
javaobject-serialization

How to load line array objects from a file using object serialization java


The program is meant to enable the user draw something with lines and save it to a file which can then be loaded, saving using ObjectOutput writeObject method works fine, but it is loading the file that does not work, if you save the file you can draw an additional line to make the display different from what was saved, but on loading it using ObjectInputStream readObject method, It does not display the saved drawing on the panel.

import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import java.io.*;

public class DrawLine extends JPanel
{
  private LineClass lines[];
  private String fileName;
  private int lineCount;
  private LineClass currentLine;
  public JLabel statusLabel;
  private int currShapeX1,currShapeY1;
  private static JButton saveButton, loadButton;
  private ObjectOutputStream output;
  private ObjectInputStream input;
  private JFileChooser fileChooser;
  public DrawLine()
  {
    statusLabel = new JLabel("(0,0)");
    saveButton = new JButton("Save");
    loadButton = new JButton("Load");
    lines = new LineClass[100];
    lineCount = 0;
    currentLine = null;

    MouseHandler handler = new MouseHandler();
    addMouseListener(handler);
    addMouseMotionListener(handler);
    saveButton.addActionListener(handler);
        loadButton.addActionListener(handler);



      }


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

    for(int count = 0; count < lineCount; ++count)
    {
      lines[count].draw(g);
    } 
    if( currentLine != null ) {
  currentLine.draw(g); 
}
  }

  public static void main(String args[])
  {
JFrame frame = new JFrame();
DrawLine panel = new DrawLine();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(saveButton,BorderLayout.NORTH);
frame.add(loadButton,BorderLayout.SOUTH);
frame.add(panel,BorderLayout.CENTER);
frame.setSize(400,400);
frame.setVisible(true);
  }

  private class MouseHandler extends MouseAdapter implements         MouseMotionListener, ActionListener
  {
    public void actionPerformed(ActionEvent event)
    {
      if (event.getSource() == loadButton)
      {
          fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

        int result = fileChooser.showOpenDialog(DrawLine.this);

    if (result == JFileChooser.CANCEL_OPTION)
      System.err.println("No file selected.");
    else
    {
      File file = fileChooser.getSelectedFile();
      if ((file != null) && !(file.getName().equals("")))
      {
        fileName = file.getName();

try
{
input = new ObjectInputStream(new FileInputStream(fileName));

lines = ((LineClass[])input.readObject());
     lineCount = 0;
    for(int j = 0; j < 100; ++j)
    {
      if (lines[j] == null)
        break;
      else
        lineCount++;
    }
repaint();        
}
catch(EOFException ex)
{
  System.out.println("Finished loading file");
}
catch(IOException ex)
{
  JOptionPane.showMessageDialog(DrawLine.this, "Error loading \""+fileName+"\"", "Error Message", JOptionPane.ERROR_MESSAGE);
}
catch(ClassNotFoundException ex)
{
  JOptionPane.showMessageDialog(DrawLine.this, "Unable to create object", "Error Message", JOptionPane.ERROR_MESSAGE);
}
      }
  }
  }
  if (event.getSource() == saveButton)
  {
    fileChooser = new JFileChooser();
    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

    int result = fileChooser.showSaveDialog(DrawLine.this);

    if (result == JFileChooser.CANCEL_OPTION)
      System.err.println("File was not saved");
    else if (result == JFileChooser.APPROVE_OPTION)
    {
      File file = fileChooser.getSelectedFile();

      if ((file != null)&&!(file.getName().equals("")))
      {
        fileName = file.getName()+".drw";


     try
{
  output = new ObjectOutputStream(new FileOutputStream(fileName));
    output.writeObject(lines);
  output.close();
  System.out.println(fileName+" saved");
}
catch(IOException ex)
{
  JOptionPane.showMessageDialog(DrawLine.this, "Error saving \""+fileName+"\"", "Error Message", JOptionPane.ERROR_MESSAGE);
}
  }
    }
  }
}
public void mousePressed(MouseEvent event)
{
  //it assigns currentShape a new shape and initializes both points to the mouse position.
  currShapeX1 = event.getX();
  currShapeY1 = event.getY();           
}
public void mouseReleased(MouseEvent event)
{
  //finish drawing the current shape and place it in the array
  //Set the second point of currentShape to the current mouse position
    currentLine = new LineClass(currShapeX1,currShapeY1,event.getX(),event.getY());

  // and add currentShape to the array.
  //Instance variable shapeCount determines the insertion index. Set currentShape to null and call method repaint to update the drawing with the new shape.
  lines[lineCount] = currentLine;
  lineCount++;

  currentLine = null;
  repaint();
}
public void mouseDragged(MouseEvent event)
{

  //it sets the second point of the currentShape to the current mouse position and calls method repaint

  //finish drawing the current shape and place it in the array
  //Set the second point of currentShape to the current mouse position
    currentLine = new LineClass(currShapeX1,currShapeY1,event.getX(),event.getY());

  // and add currentShape to the array.
  //Instance variable shapeCount determines the insertion index. Set currentShape to null and call method repaint to update the drawing with the new shape.
  //lines[lineCount] = currentLine;

  //currentLine = null;
  repaint();
  statusLabel.setText(String.format("(%d,%d)",event.getX(),event.getY()));
}

public void mouseMoved(MouseEvent event)
{
  //to set the text of the statusLabel so that it displays the mouse coordinates—this will update the label with the coordinates every time the user moves 
  //(but does not drag) the mouse within the DrawPanel
  statusLabel.setText(String.format("(%d,%d)",event.getX(),event.getY()));
}
}
}

//LineClass
class LineClass implements Serializable
{
private int x1;
private int y1;
private int x2;
private int y2;

public LineClass(int x1, int y1, int x2, int y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}

public void draw(Graphics g)
{
g.drawLine(x1,y1,x2,y2);
}
}

Solution

  • It appears that when you read your file back in lineCount is set to 100 as this is the size of your array that you saved.

    If you only drew 3 lines lineCount is 100 instead of 3.

    This means that when you do a repaint it is trying to draw null objects.

    What you need to do is when you load the file find the first null value in the lines array and set your lineCount according to that, and not the length of the array.

    A simplistic method would be

    for (int loop = 0; loop < lines.length; loop++)
    {
      if (lines[loop] == null)
      {
        lineCount = loop;
        break;
      }
    }
    

    instead of

    lineCount = lines.length;