New to Java

New to Java Programming Center

New to Java

Programming Center

Java Platform Overview | Getting Started | Learning Paths
References & Resources | Certification | Supplements




 

More on MVC and Serialization

Model/View/Controller Architecture

A Swing Architecture Overview

Object Serialization

FAQ about Serialization

 

In Part 4, you learned to handle conditions and problems so you can read from and write to files. You also learned the Box layout, how to create pop-up windows for warning messages, and how to use the JFileChooser class for naming new files.

Part 5 reinforces these concepts and introduces the second part of the Log Dives pane, showing you how to:

 

  • Separate interface from implementation.
  • Create a DiveRecord object.
  • Serialize objects and write them to files, then read them back into the GUI.
  • Use Vector objects to store input.
  • Create pull-down menus and radio buttons.


 

Getting Started



For this part of the tutorial, you will change two classes you previously created: Dives.java and CenterPanel.java . In addition, you'll define new classes, renaming the WestPanel.java placeholder class to DiveHandler, and create two other classes called UIWestPanel.java and DiveRecord.java.

 

  • Dives.java: Initializes the two classes ( UIWestPanel and DiveHandler) that make up the Log Dives pane.
  • UIWestPanel.java: Initializes the GUI features, such as text fields, radio buttons, a drop-down menu, and buttons for entering and viewing dives.
  • CenterPanel.java: Is no longer needed. The JTextArea and the shark image are moved into the UIWestPanel class.
  • DiveRecord.java: Models what a DiveRecord object is.
  • DiveHandler.java: Provides functionality, such as collecting the data from the UIWestPanel object, and saving the DiveRecord object to a file.


This lesson shows you how to build a user interface that allows a user to enter information that is saved for each dive, and a separate class that collects data from the user interface into a DiveRecord object through public get methods. Lastly, you create code that writes the object to a file, which can later be read back into the GUI.

The Log Dives pane is built in four basic steps:

 

  1. Change two classes you created earlier.
  2. Create a DiveRecord class for the DiveRecord object.
  3. Build the GUI components for user input.
  4. Create a class that provides functionality for the buttons, gathers the data, saves the collection of data as an object, and writes the object to a file. Later the object is passed back to the GUI.


 


Note: It's assumed you installed the Java 2 Platform, Standard Edition (J2SE) on your system, and that you have completed Part 1, Part 2, Part 3, and Part 4 of the Building an Application tutorial.


 

Making Changes

In Part 4 of the Building an Application series, you learned about JFileChooser, and how to text to a file. The CenterPanel creates the text area for the user to enter text. You keep the code that creates the text area and shark image, but you no longer need the rest of the code. Because the text area is a GUI feature, the code for it needs to be included with the other GUI features of this pane.

 




  1. Open the CenterPanel.java class you created in Part 4.
  2. Remove the code for the text area and shark image, and save the code to a separate file for now.
  3. Open the Dives.java class you created in Part 4.
  4. Either comment out or remove the line that initializes the CenterPanel class, and the line that adds the CenterPanel object to the panel, as shown in bold.
  5. Change NorthPanel to DiveHandler, as shown in bold:
    public class Dives extends JPanel
    { // Opens class
        public Dives()
       {// Opens constructor
        // Sets the layout for the page and the
        // background to white.
        setLayout(new BorderLayout());
        setBackground(Color.white);
    
         // Initializes the placeholder classes.
         NorthPanel northPanel = new NorthPanel();
          
                           //CenterPanel centerPanel = new CenterPanel();
          
                           //NorthPanel northPanel = new NorthPanel();
         DiveHandler ui = new DiveHandler();
    
         // Adds class objects to panel regions.
         add("North", northPanel);
         add("West", ui);
          
                           //add("Center", centerPanel);
       } // Closes constructor
    </li>
                        
  6. Save the file.


Note: You cannot compile this class until you create the DiveHandler class, which you'll do later in this tutorial.

The CenterPanel class is no longer needed.


 


Completed Log Dives pane


Separating Interface from Implementation

Until now you've built each pane from a single user-defined class. These classes included code for both GUI components, the data, and the functionality of the pane. A better way of designing software involes the Model, View, Controller (MVC) architecture.

The idea behind MVC is to separate the graphical (or view) components from the data (or model), and use a controller to deal with user interaction and modifying the model or view as appropriate:

 

  • Model: Stores the data that defines the component.
  • View: Creates the visual representation of the component.
  • Controller: Deals with user interaction with the component and then updates the model and/or the view as needed, depending on user input.


Of course, some applications are small or have little functionality, so the MVC architecture is overkill. But for this pane, MVC works well.

The classes of the Log Dives pane serve as an example:

 

  • UIWestPanel.java: Creates the GUI components for the user to enter information. This class acts as the view.
  • DiveRecord.java: Contains a contructor to build a DiveRecord object that eventually holds all the user input, and has the public get and set methods necessary to access indiviual data. This class defines a model for a DiveRecord object.
  • DiveHandler.java is the controller. This class instantiates the UIWestPanel and DiveRecord classes. In addition, it provides the functionality of the buttons for the UIWestPanel class by calling the public set and get methods of the other classes.


 



 

Designing the Object



Now that you've made necessary changes to the two classes you created previously, you're ready to design a dive object class. This is the plan for what each dive consists of. It also tells you what type of GUI features you'll need to collect information from the diver, because each dive object consists of dive data only.

To decide what the DiveRecord class constructor needs passed into it, determine the most common information divers provide for each dive, and note what type of data it is, such as:

 

  • Type of dive, such as shore or boat ( String t)
  • Date the dive took place ( String d)
  • The depth the diver reached on that dive ( int dth)
  • The starting pressure of the tank at the beginning of the dive ( int s)
  • The ending pressure of the tank at the end of the dive ( int e)
  • Total air consumed on the dive ( int u)
  • The length of bottom time for the dive ( int b)
  • Dive count number, such as the 30th dive for that diver ( int c)
  • Water visibility ( int v)
  • Comments about the dive ( String cts)


Each piece of information above is assigned to a type such as a String or an int, and assigned an identifier. The dive object is constructed at the time when the diver enters all of the information.

This class then needs to include the following:

 

  • A constructor
  • get methods for each information item


That's all. The instructions for what should be done with that information go into the controller class that you'll construct last.

This DiveRecord class provides a constructor for the data that is collected, and methods to work with that data. Because you're going to write this object to a file using serialization, this class implements Serializable.

Object Serialization

Usually objects last only as long as the program that creates them is up and running. The ability of an object to save, or record, its state so it can be reproduced in the same application or a different one is persistence. Objects persist by being recorded through writing their values that describe their state in a file. For instance, let's say you've created a Car class so users can create their own Car objects according to their needs. Persistence would allow each Car instance to save its make, model, color, and so forth for each individual Car object and record the state of each car to be brought up at a later time.

You save an object's state through object serialization, which is represented by an ordered series of bytes. If that state information is another object, the current settings for that object are also saved, and so on until everything is a primitive data type. Methods and static variable state are not saved. Methods consist of behavior and not state, so they are not saved. Static variable state is information about the class, not the instance, so it isn't saved either.

Serialization is ideal for saving the dive data because you only need the data saved. A DiveRecord is simply an object with that data.

If a class implements the java.io.Serializable interface, it is serializable. There are no methods to the interface, so it just serves as a marker interface. However, simply implementing the interface isn't sufficient. The instance variables of that class must also be serializable; otherwise, when you try to serialize the state, an exception will be thrown.

Later you'll learn about the methods that write and read the object to and from a file. For now, just make sure that your DiveRecord class implements the Serializable interface.

 




  1. Open your text editor, and create a DiveRecord class by importing the following packages, and implementing Serializable:
    //Represents a record of a dive
    package divelog;
    import java.io.*;
    import java.io.Serializable;
    
    public class DiveRecord implements Serializable
      {
      
    
  2. Add the following instance variables:
        //Instance variables
        private String date, type, cts;
        private int depth, start, end, used, 
                             time, count, vis;
    
  3. Create a default constructor that calls a setDive method:
        public DiveRecord ()
         {
           setDive();
         }
    
  4. Implement a setDive method that doesn't take any arguments, but contains the variables listed above:
        public void setDive()
         {
           type = "";
           date = "00/00/00";
           depth = 00;
           start = 0000;
           end = 0000;
           used = 0000;
           time = 00;
           count = 000;
           vis = 00;
           cts = "";
         }
    
  5. Now create a setDive method that takes all those variables as arguments:
        public void setDive ( 
                    String t,String d, int dth, 
                    int s, int e, int u, int bt, 
                       int c, int v, String cts)
            {
              
              this.type = t;
              this.date = d;
              this.depth = dth;
              this.start = s;
              this.end = e;
              this.used = u;
              this.time = bt;
              this.count = c;
              this.vis = v;
              this.cts = cts;
              
             }
    
  6. Override the toString method of the String class so that toString returns the data associated with the instance variables:
        public String toString()
         {
           return type + date + depth + start + 
              end + used + time + count + vis + cts;
         }
    
  7. Now provide a get method for each instance variable:
        public String getDte()
          {
            return date;
          }     
        public int getDepth ()
          {
            return depth;
          }
         public String getType ()
         {
           return type;
          }
         public int getStart ()
          {
            return start;
           }
        public int getEnd ()
          {
            return end;
           }
           
         public int getUsed ()
           {
             return used;
            }
         public int getTime()
           {
             return time;
           }
         public int getCount ()
           {
             return count;
            }
         public int getVis()
           {
              return vis;
            }
        public String getComments()
          {
             return cts;
           }
       }//closes class     
    
  8. Save the file.
  9. Compile the file DiveRecord.java.


Your new class should look like this DiveRecord.java example.



Note: The keyword this used in the constructor above. Argument names hide the member variables. So identifers within the body of the constructor refer to the argument, not to the member variable. To access the member variable, you must reference it through this, the current object. Typically, within an object's method body, you can refer directly to the object's member variables. However, sometimes you need to distinguish the member identifier if one of the arguments to the method has the same name. This is done simply with the keyword this.

That completes the model for the dive log object. Now that you have the model object class completed, you need to create the GUI components the user needs to enter data.

 

Building the GUI Components

The Logs Dives pane contains a text area for comments about dives and other useful graphical input components, such as a drop-down menu to choose a dive depth, two radio buttons to toggle between shore or boat dives, and the familiar text fields to record date, bottom time, visibility, and a label that gets filled in by a method you create that automatically records the dive number. If you're building, for example, an exercise log instead, you can change these features to record calories burned, aeorbic and non-aerobic exercise, and so forth. Change these features as you see fit for your application.

Next, you'll create a UIWestPanel class to define the GUI components for a diver to enter dive data.

 

Read the API for class JComboBox. Which line of code is correct to make the combo box editable?
   A.  JComboBox week = new JComboBox(SetEditable);
   B.  JComboBox week = new JComboBox(week.setEditable);
   C.  week.setEditable(true);
   D.  week.setEditable == true;

 

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.