2

I am trying to learn more about java. This program is an attempt to understand events as well as serialization. What i am attempting to do is flatten an object when the user closes the JFrame and re-inflate it when the program is started. I know i can create the serialized file but having it take effect again isn't working. Any help in the right direction would be wonderful. Thank you in advance.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.Timer;
import java.io.*;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class tempusFugit extends JFrame implements ActionListener, Serializable, WindowListener
{
String fileN = "tf.txt"; 
public int ToL = 0;
String outT = Integer.toString(ToL);
    JLabel jl = new JLabel(outT);

FileOutputStream fos = null;
ObjectOutputStream out = null;

public tempusFugit()

{
    Timer timer = new Timer(1000, this);

    setBounds(250, 250, 250, 190);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new FlowLayout(FlowLayout.LEFT) );
    setVisible(true);
    add(jl);
    timer.start();
}

public void actionPerformed(ActionEvent e)
{
    ++ToL;
    outT = Integer.toString(ToL);
    jl.setText(outT);
    validate();
    repaint();
}
public static void main(String[] args)
{
    tempusFugit tf = new tempusFugit();
    tf.addWindowListener( tf );

}
public void windowDeactivated(WindowEvent e)
{
}
public void windowActivated(WindowEvent e)
{   
}
public void windowDeiconified(WindowEvent e)
{
}
public void windowIconified(WindowEvent e)
{
}
public void windowClosed(WindowEvent e)
{
}
public void windowClosing(WindowEvent e)
{
    try
    {
        fos = new FileOutputStream(fileN);
        out = new ObjectOutputStream(fos);
        out.writeObject(this);
        out.close();

    }
    catch(IOException ex)
    {
}
}
public void windowOpened(WindowEvent e)
{
try
    {
        tempusFugit tf = new tempusFugit();
        FileInputStream fis = new FileInputStream(fileN);
        ObjectInputStream in = new ObjectInputStream(fis);
        tf = (tempusFugit)in.readObject();
        this.ToL = tf.ToL;
    }
    catch(IOException ex)
    {
    }
    catch(ClassNotFoundException ce)
    {
    }

}

}

I assume i'm trying to recreate the object at the wrong time. Even though the object is serialized correctly i can not access it again with the windowOpened function. Do i need to try to use

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

somehow?

What i end up with is an error saying i am trying to access a Final object (i assume my this). I find that very odd that i cant repopulate my current 'this' with another similar object.

Am i way off base?

Again thank you for your time.

Powe8525
  • 121
  • 6
  • 2
    When I fill in `Exception.printStackTrace()` for each of those catch statements, I see `java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.io.FileOutputStream` Don't swallow exceptions. BTW 1) Did your dog format that code? Please Choose one of the common systems of indenting code blocks and stick to it. 2) What is the purpose of creating 2 frames every run? Is that intentional? – Andrew Thompson Dec 04 '11 at 06:31
  • I can not make heads or tails of your response. 1) i don't have a dog, the code block here reformatted my cut and past and 2) i honestly don't see how i am creating two JFrames and 3) nothing here answers how i can re-inflate my serialization. I am not concurrence with exceptions atm i am just trying to get a working copy of this code so i can better understand the process. I will make it pretty later. The serialization does out put to a file however i am stuck on how to event drive a reversal. (Those are the responses i am looking for) Thank you. – Powe8525 Dec 04 '11 at 06:57
  • *"Those are the responses i am looking for"* Perhaps you'd better seek a help desk. They'll give you answer in any form you want. *"i don't have a dog,"* My bad. That was sarcasm to indicate that your code read like "a dog's breakfast". Google should have many hits on the phrase. – Andrew Thompson Dec 04 '11 at 07:05
  • please learn java naming conventions and stick to them – kleopatra Dec 04 '11 at 10:59

1 Answers1

3

Note that there are much simpler ways to do this than serializing the frame, and much better things to serialize than the frame itself.

See What is the best practice for setting JFrame locations in Java? for an example of storing the location and size of a frame. It would be trivial to adapt that to store the count.


But here is an attempt based on your code.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.Timer;
import java.io.*;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class tempusFugit extends JFrame implements ActionListener, Serializable, WindowListener
{
    String fileN = "tf.txt";
    public int ToL = 0;
    JLabel jl = new JLabel("" + ToL);

    public tempusFugit()
    {
        Timer timer = new Timer(1000, this);

        setBounds(250, 250, 250, 190);
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setLayout(new FlowLayout(FlowLayout.LEFT) );
        setVisible(true);
        add(jl);
        timer.start();
    }

    public void actionPerformed(ActionEvent e)
    {
        ++ToL;
        jl.setText("" + ToL);
        validate();
        repaint();
    }

    public static void main(String[] args)
    {
        tempusFugit tf = new tempusFugit();
        tf.addWindowListener( tf );
    }

    public void windowDeactivated(WindowEvent e){}
    public void windowActivated(WindowEvent e){}
    public void windowDeiconified(WindowEvent e){}
    public void windowIconified(WindowEvent e){}
    public void windowClosed(WindowEvent e){}

    public void windowClosing(WindowEvent e)
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(fileN);
            ObjectOutputStream out = new ObjectOutputStream(fos);
            out.writeObject(this);
            out.flush();
            out.close();
            setVisible(false);
            System.exit(0);
        }
        catch(IOException ex)
        {
            JOptionPane.showMessageDialog(null, ex);
            System.exit(1);
        }
    }

    public void windowOpened(WindowEvent e)
    {
        try
        {
            tempusFugit tf;// = new tempusFugit();
            FileInputStream fis = new FileInputStream(fileN);
            ObjectInputStream in = new ObjectInputStream(fis);
            tf = (tempusFugit)in.readObject();
            this.ToL = tf.ToL;
            //tf.setVisible(false);
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        catch(ClassNotFoundException ce)
        {
            ce.printStackTrace();
        }
    }
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • This solution doesn't re-serialize the object. It does cause a lot of exceptions though. – Powe8525 Dec 04 '11 at 07:13
  • What DYM by 're'-serialize the object? It should only be serialized once per run. – Andrew Thompson Dec 04 '11 at 07:17
  • What i am attempting to do is create a class that when closed will serialize to a flat file, then when opened will DE-searilize into an object in the exact same state as when the close button was pushed. (if ToL was at 110 when it closed, it would be de-serilized as 110 into the new object and continue to mark time from the Timer). – Powe8525 Dec 04 '11 at 07:24
  • 1
    That's what I see give-or-take a little I/O latency; I guess you could stop the `Timer` in `windowClosing()`. – trashgod Dec 04 '11 at 07:32
  • 1
    @trashgod It was the OP's pun. ;) – Andrew Thompson Dec 04 '11 at 07:33
  • *"if ToL was at 110 when it closed, it would be de-serilized as 110 into the new object and continue to mark time from the Timer"* Having 2 frames visible on screen at the same time (on top of each other no less) is confusing things. So I ensured that de-serialized value was applied to the existing frame, and the `tf` instance was never seen. In other words, if you close the visible frame at 110, it will re-appear as 0, then jump straight to 110. BTW - there are much simpler ways to do this than serializing the frame, and much better things **to** serialize than the frame itself. – Andrew Thompson Dec 04 '11 at 07:37
  • Sir, i am all ears. "if there is a better way, ill be the first in line" If there is a faster way to save a program's state then restart that state once the program is, well restarted please point in the right direction. That is the only real point of this exercise. – Powe8525 Dec 04 '11 at 07:40
  • @trashgod *"you could stop the Timer in windowClosing()."* I should have, though I was only playing with the code to the extent that the weirdest aspects of it were removed. ..Caveat emptor. ;) – Andrew Thompson Dec 04 '11 at 07:42
  • *"i am all ears."* See the edit to my answer (I put it at the top). – Andrew Thompson Dec 04 '11 at 07:45
  • 1
    @Powe8525: _a faster way to save a program's state_ brings to mind [`java.util.prefs.Preferences`](http://docs.oracle.com/javase/7/docs/api/java/util/prefs/Preferences.html). – trashgod Dec 04 '11 at 07:47
  • @trashgod Oddly, I've never been able to get the values to 'stick' using `Preferences`. I developed a theory the other night that it was because my code was in the default package and preferences did not like it, though I've yet to run tests to confirm it. – Andrew Thompson Dec 04 '11 at 07:53
  • Your code did just what i wanted it to do. Now i have to dissect it to find where i was off. Thanks for your time. I really want to get to know this aspect of Java coding (all ugly code work aside). BTW why HIDE_ON_CLOSE and not EXIT_ON_CLOSE? – Powe8525 Dec 04 '11 at 07:56
  • *"BTW why HIDE_ON_CLOSE and not EXIT_ON_CLOSE?"* Once you add a `WindowListener`, the listener generally takes care of the frame disappearing. As part of my first changes to the code, I changed that in case they were interfering with one another. To be honest, I don't know if it was actually necessary. – Andrew Thompson Dec 04 '11 at 07:59
  • I have so much to learn. Thank you again for your time and effort. – Powe8525 Dec 04 '11 at 08:01
  • No worries. Glad you got it sorted. BTW +1 for posting an [SSCCE](http://sscce.org/) (very easy to work with & debug). – Andrew Thompson Dec 04 '11 at 08:03
  • 1
    @AndrewThompson: Good theory; I've not tried it. You might try `flush()`; [`RobotChase`](http://robotchase.sourceforge.net/) is an example. – trashgod Dec 04 '11 at 19:47