390 likes | 453 Views
Object-Oriented Programming (Java), Unit 23. Kirk Scott. Serializability, File Choosers, and Multiple Frames. 23.1 Serializability 23.2 File Choosers 23.3 Multiple Frames. 23.1 Serializability. ClickSave.
E N D
Object-Oriented Programming (Java), Unit 23 Kirk Scott
Serializability, File Choosers, and Multiple Frames • 23.1 Serializability • 23.2 File Choosers • 23.3 Multiple Frames
ClickSave • This example program adds two menu options to the example, one to save the current state of the cups in the application, and the other to reload them.
The Serializable interface • To be serializable, a class has to implement the Serializable interface. • It is possible to save and load complete objects of a class if it implements this interface. • This interface does not require the implementation of any methods. • Certain other requirements have to be met in order to implement the interface. • If a class is to be serializable, every object that it contains also has to be serializable.
The Cup and Seed classes: • The SeedCup implements the Serializable interface. • The SeedCup class has a Rectangle instance variable. • The Rectangle class implements the Serializable interface. • Note that Rectangle2D.Double does not. • The only change in the SeedCup class from the previous version is in the declaration. • public class SeedCup implements Serializable
The Seed class also implements the Serializable interface. • None of the system supplied ellipse classes implement the Serialiable interface. • Seeds do not have ellipses. • The dots are transient visual representations.
This is a design point worth noting. • The application would not support serializability if the dots were instance variables of the seed class. • The only change in the Seed class from the previous version is in the declaration. • public class Seed implements Serializable
The SaveListener: • The user is prompted for the name of a file. • An ObjectOutputStream is constructed, and the objects of the application are written to it, one after the other. • private class SaveListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • String inputString; • inputString = • JOptionPane.showInputDialog • ("Enter file path name for saving.");
try • { • ObjectOutputStream objOut = • new ObjectOutputStream • (new FileOutputStream(inputString)); • objOut.writeObject(myPanel.getMyCupA()); • objOut.writeObject(myPanel.getMyCupB()); • objOut.writeObject(myPanel.getWhichCupActive()); • } • catch(IOException e) • { • System.out.println("Problem making or • writing to an output stream."); • System.out.println(e); • } • } • }
The LoadListener: • The user is prompted for the name of a file. • The current state of the application is disposed of by removing the current panel. • A new panel is created and added to the content pane.
An ObjectInputStream is constructed. • The file containing the SeedCup objects is read from the beginning. • The objects are retrieved in the order in which they were saved and put into the application panel.
private class LoadListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • String inputString; • inputString = JOptionPane.showInputDialog • ("Enter file path name for loading."); • try • { • Container contentPane = getContentPane(); • contentPane.remove(myPanel); • myPanel = new ClickSavePanel(); • contentPane.add(myPanel, "Center"); • ObjectInputStream objIn = new ObjectInputStream( • new FileInputStream(inputString)); • myPanel.setMyCupA((SeedCup) objIn.readObject()); • myPanel.setMyCupB((SeedCup) objIn.readObject()); • myPanel.setWhichCupActive((SeedCup) objIn.readObject()); • setVisible(true); • } • catch(IOException e) • …
ClickChooser: • This example program makes use of a JFileChooser in the SaveListener and the LoadListener. • The screenshot below shows what appears if the Save option is taken in the menu.
These lines of code appear in the ClickChooserFrame class and its constructor, respectively: • JFileChooser myChooser; • … • myChooser = new JFileChooser();
The SaveListener and the LoadListener: • Inside the listener actionPerformed() method the following will be found: • The call to setCurrentDirectory() will cause the chooser to open the home directory of the running application. • The call to showSaveDialog() causes the chooser to be displayed. • The call to getSelectedFile().getPath() obtains the full path name of the file which the user selects or enters.
Key parts of the SaveListener: • private class SaveListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • … • myChooser.setCurrentDirectory(new File(".")); • myChooser.showSaveDialog(ClickChooserFrame.this); • fileName = myChooser.getSelectedFile().getPath(); • …
Key parts of the LoadListener: • private class LoadListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • … • myChooser.setCurrentDirectory(new File(".")); • myChooser.showOpenDialog(ClickChooserFrame.this); • fileName = myChooser.getSelectedFile().getPath(); • …
Slow construction of instances of JFileChooser • There is an unpleasant interaction between the Windows operating system and instances of JFileChooser in Java. • The construction of a JFileChooser will take a very long time if there are any zipped folders on the desktop of the machine you are running on. • In order to get reasonable performance of the Java code, move any zipped folders into another, unzipped folder. • This is very strange, and it's enough to make you cry, but at least there is an easy solution that doesn't involve elaborate changes to your code.
ClickMany • This program makes it possible to open up more than one frame with cups in it. • The menu for the main frame allows you to open up the new frames or exit the application overall. • The menu for a subframe allows you to restart or close that frame.
There are two UML diagrams for this application. • This first one shows the relationships of the classes associated with the main frame of the program.
The second UML diagram for the application shows relationships of the classes associated with the subframes of the program. • Notice how the application panel, cups, and seeds are unchanged from the previous versions of the application, but they now descend from the subframe rather than the main frame.
The structure of the menu belonging to the subframe is analogous to that of the main frame, but the menu items have different names and their listeners implement the corresponding functionality. • This application still has key handling functionality, but in order to keep the diagrams a little simpler, it is not shown in them.
Portions of the code for the application follow. • Notice first of all the main frame is simplified somewhat by removing the WindowCloser and going back to the default close operation. • When the main frame is closed, the application ends. • class ClickManyFrame extends JFrame • … • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
The main frame class has a listener for the menu option to make a subframe. • This code is shown next. • Notice how each new subframe is located at an offset from the previous one so they don’t completely overlap each other on the screen.
private class MakeSubFrameListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • ClickSubFrame myframe = new ClickSubFrame(); • myframe.setLocation(subFrameLocation, • subFrameLocation); • if(subFrameLocation >= 500) • { • subFrameLocation = 50; • } • else • { • subFrameLocation += 50; • } • myframe.setVisible(true); • } • }
The subframe of this application is similar to the main frames of the previous example applications. • The subframe has menu items for restarting and closing. • The RestartListener implements the restarting of the application by renewing the cups in the panel.
private class RestartListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • myPanel.renewBoard(); • myPanel.renewTextArea(); • myPanel.setMoveCount(1); • } • }
The CloseListener for the subframe does something different from the WindowCloser or Exit menu options for the main frame. • Closing a subframe does not end the application. • It merely disposes of that particular subframe. • private class CloseListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • dispose(); • } • } • }
The renewCups() method in the panel class duplicates all of the logic of the constructor, plus a call to repaint(). • public void renewBoard() • { • myCupA = new SeedCup(4, 200, 200, 40, 40); • myCupB = new SeedCup(0, 250, 200, 40, 40); • whichCupIsActive = myCupA; • repaint(); • }
This is the renewTextArea() method • public void renewTextArea() • { • actionRecordArea.setText(""); • repaint(); • }
This is the setMoveCount() method • public void setMoveCount(int countIn) • { • moveCount = countIn; • }