Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Object-Oriented Programming (Java), Unit 23 Kirk Scott.

Similar presentations


Presentation on theme: "1 Object-Oriented Programming (Java), Unit 23 Kirk Scott."— Presentation transcript:

1 1 Object-Oriented Programming (Java), Unit 23 Kirk Scott

2 2 Serializability, File Choosers, and Multiple Frames 23.1 Serializability 23.2 File Choosers 23.3 Multiple Frames

3 3 23.1 Serializability

4 4 ClickSave This example program adds two more menu options to the example One triggers a listener to save the current state of the cups in the application The other triggers a listener to reload them. Saving and loading will involve the concept of serializability. A screenshot of the application, showing the menu, is given on the next overhead.

5 5

6 6 The Serializable interface Serializability is the term used to describe tools in the Java API that make it possible to save objects in files. To be serializable, a class has to implement the Serializable interface. If a class implements the interface, it is possible to save and load complete objects of a class. It is not necessary to take them apart and save their instance variable values one at a time, for example.

7 This interface does not require the implementation of any methods. In other words, it is a marker interface, kind of like Cloneable was a marker interface. Certain requirements have to be met in order for a class to successfully implement the interface. In particular, if a class is to be serializable, every object that it contains also has to be serializable. 7

8 8 The Cup and Seed classes: The SeedCup class implements the Serializable interface. The SeedCup class has a Rectangle instance variable. The Rectangle class in the Java API implements the Serializable interface.

9 It is worth noting that the Rectangle2D.Double class in the Java API does not implement the interface. This provides a concrete example of something that you could not include in a serializable class of your own. The SeedCup class would not be serializable if it were based on Rectangle2D.Double instead of Rectangle. 9

10 The SeedCup class contains an ArrayList that will hold instances of the Seed class. In order for the SeedCup class to be serializable, it will also be necessary for the Seed class to be serializable. It is, and that will be discussed next. 10

11 Because every object that an instance of a SeedCup class could contain is serializable, the SeedCup class is serializable. All that has to be done, and the only change from the previous version of the SeedCup class, is to declare it serializable. public class SeedCup implements Serializable 11

12 The Seed class also implements the Serializable interface. Unlike with the rectangle classes, none of the system supplied ellipse classes implement the Serializable interface. This accounts for one of the important design characteristics of the Seed class which was already built in earlier, without giving a full explanation of why. 12

13 Seeds do not have instances of ellipses as instance variables. The application code uses elliptical dots to represent seeds, but they are generated and displayed as part of the code of the drawSeed() method. The dots are not persistent. They are only transient visual representations of seeds. 13

14 This is a design point worth noting. The application would not support serializability if the dots (ellipses) were instance variables of the Seed class. All that has to be done, and the only change from the previous version of the Seed class, is to declare it serializable. public class Seed implements Serializable 14

15 The SaveListener: The SaveListener is built around the concept of serializability. It is possible to open an output stream to a file which is designed to handle the saving of serializable objects. The user is prompted for the name of a file. 15

16 An ObjectOutputStream is constructed. Then, one after the other, references to the objects comprising the state of the application are acquired by calling get methods. As they are acquired, they are saved by calling the write() method on the output stream. 16

17 The SaveListener has to deal both with the cups and the text area. The getText() method returns a String, which is also an object. This method contains the logic for acquiring the text for the action record area. 17

18 You may or may not be familiar with file I/O in Java. Notice that I/O operations have to occur in a try/catch block. File I/O operations are a classic example of exception handling in Java. 18

19 An I/O error might occur that is not the program’s fault The exception handling mechanism makes it possible for the program to handle the error gracefully, assuming the programmer wants to go to the trouble of writing the code to do so. The code for the SaveListener is given on the following overheads. 19

20 20 private class SaveListener implements ActionListener { public void actionPerformed(ActionEvent event) { String inputString; inputString = JOptionPane.showInputDialog("Enter file path name for saving.");

21 21 try { ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(inputString)); objOut.writeObject(myPanel.getMyCupA()); objOut.writeObject(myPanel.getMyCupB()); objOut.writeObject(myPanel.getWhichCupIsActive()); objOut.writeObject(myPanel.getText()); objOut.writeObject(myPanel.getMoveCount()); } catch(IOException e) { System.out.println("Problem making or writing to an output stream."); System.out.println(e); }

22 Notice that a type of “auto-boxing” occurs on the moveCount value. The system automatically wraps the integer value in an instance of the Integer class. It’s automatic when saving. It turns out that it will have to be dealt with directly when loading. 22

23 23 The LoadListener: The LoadListener is analogous to the SaveListener. It is also built around the concept of serializability. It is possible to open an input stream to a file which is designed to handle the reading of serializable objects which were previously saved in the file.

24 In 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. 24

25 The 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. This is done using the readObject() method. Notice that an Object reference is returned, and this has to be cast to the class expected. 25

26 The retrieved objects are put into the application panel. This is done using set methods in the application. The application deals with cups and text. To set the text area with text retrieved with the load operation, call setText() with the String that is returned from the file. 26

27 Reading is also a file I/O operation, so it also has to occur in a try/catch block. It is worth repeating that the order of the logic for retrieving objects is the same as for saving them. Do not get the mistaken idea that something odd happens, like the order is reversed, for example. 27

28 private class LoadListener implements ActionListener { public void actionPerformed(ActionEvent event) { String inputString; inputString = JOptionPane.showInputDialog("Enter file path name for loading."); 28

29 29 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.setWhichCupIsActive((SeedCup) objIn.readObject()); myPanel.setText((String) objIn.readObject()); Integer localMoveCountObject = (Integer) objIn.readObject(); int localMoveCount = localMoveCountObject.intValue(); myPanel.setMoveCount(localMoveCount); setVisible(true); } catch(IOException e)…

30 30 23.2 File Choosers

31 ClickChooser This example program makes use of a JFileChooser in the SaveListener and the LoadListener. The screenshot on the next overhead shows what appears if the Save option is taken in the menu. It should be apparent that the Java API makes available useful tools for creating a graphical file I/O interface. 31

32 32

33 33 The lines of code given below appear in the ClickChooserFrame class and its constructor, respectively. This is where the chooser is created that the menu item listeners make use of. JFileChooser myChooser; … myChooser = new JFileChooser();

34 34 The SaveListener and the LoadListener: Inside the actionPerformed() method of the save and load listeners 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.

35 Only key parts of the code are shown for this new version of the application. Most of the code remains the same as in the previous version. Parts of the save listener and the load listener are given on the following overheads. 35

36 36 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(); …

37 37 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(); …

38 38 Slow construction of instances of JFileChooser There is an unpleasant potential interaction between at least some versions of the Windows operating system and instances of JFileChooser in Java. The construction of a JFileChooser may take a very long time if there are any zipped folders on the desktop of the machine you are running on.

39 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. 39

40 40 23.3 Multiple Frames

41 41 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—without exiting the application. Screenshots of the main frame and a subframe, and their menu options, are given on the following overheads.

42 42

43 43

44 44 The application is getting large enough that it’s hard to fit everything into a single static structure diagram that would fit on a single overhead. Therefore, there are two UML diagrams for this application. The diagram on the following overhead shows the relationships of the classes associated with the main frame of the program.

45 45

46 46 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.

47 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. The second UML diagram is given on the following overhead. 47

48 48

49 49 Portions of the code for the application follow. Notice first of all that 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);

50 50 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.

51 51 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); }

52 52 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. Code for this is given on the following overhead.

53 53 private class RestartListener implements ActionListener { public void actionPerformed(ActionEvent event) { myPanel.renewBoard(); myPanel.renewTextArea(); myPanel.setMoveCount(1); }

54 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. Code for this is given on the following overhead. 54

55 55 private class CloseListener implements ActionListener { public void actionPerformed(ActionEvent event) { dispose(); }

56 The renewBoard() method in the panel class duplicates all of the logic of the constructor, plus a call to repaint(). Code for this is given on the next overhead. 56

57 57 public void renewBoard() { myCupA = new SeedCup(4, 200, 200, 40, 40); myCupB = new SeedCup(0, 250, 200, 40, 40); whichCupIsActive = myCupA; repaint(); }

58 Code for the renewTextArea() method is given on the next overhead. 58

59 public void renewTextArea() { actionRecordArea.setText(""); repaint(); } 59

60 Code for the setMoveCount() method is given on the next overhead. 60

61 public void setMoveCount(int countIn) { moveCount = countIn; } 61

62 Managing Increasing Complexity As applications grow in complexity it can become difficult to manage all of the pieces and keep them all working. In the last unit keystroke functionality was introduced. You may notice that in later versions of the application that is removed. Making keystrokes work when other functionality is added can be difficult. In the assignments, keystroke functionality can be dropped after unit 22 until it’s raised again in a future unit. 62

63 63 The End


Download ppt "1 Object-Oriented Programming (Java), Unit 23 Kirk Scott."

Similar presentations


Ads by Google