MVC and Java Graphics

Sample Program and MVC

The current directory (~comp212/public_html/01-spring/notes/lecture-16/) contains the Java source code and byte code for a GUI application that (almost) meets the requirements of milestone #2 of project #1. To see how the application behaves, run the command

     java OldBPControl
. You should see a window appear with two main panels: a left (west) panel and a right (east) panel. Each panel has a button at the top (north) and a graphics a panel at the center. If you click on the left button, you should see body parts moving to the right. If you continue to click when there is no more body part, you will see an exception thrown. Click on the right button and you should see the body parts move to the left. Play around with this program and record its behavior. The program is designed according to what is called the Model-View-Controller (MVC) pattern as shown in the UML diagram below.

mvc.png (22290 bytes)

Class BPList is the model. It represents the list of body parts, each of which is a concrete implementation of the Drawable interface.

BodyPartsGUI contains Java GUI (graphical user interface) components to display the model BPList and to allow the user to interact with it by clicking a couple of buttons. When a user clicks a button, the Java virtual machine fires an event, called ActionEvent, and delivers it to this button.` In order to be able to sense this event and do something useful, the button must have an ActionListener object attached to it. You attach an ActionListener to a GUI component by calling addActionListener(...) on the GUI component (see code sample in the next section). An ActionListener responds to the ActionEvent object it receives by executing its

     public void actionPerformed(ActionEvent e)
method. The programmer writes the code for this method to carry out the desired task.

The wiring between a GUI component and the model is called a control. In the above example, the main control, BPControl, references two BPList objects, one for each panel of the BodyPartsGUI object. It is in this control that we install all the event listeners for each of the GUI components in the view (BodyPartsGUI). The action listener for the left button handles the click button event by asking the left BPList to remove one body part from the front of the list and then asking the right to insert it at the end. The listener for right button does the reverse. The provided source code for BPControl is incomplete.

Basic Java Graphics

The simplest to draw graphics in Java is to extend JPanel, a Swing component, and override its

     paintComponent(Graphics g)
method in order to draw on the graphics object g. Whenever Java tries to render a Swing GUI component, it calls the component's paintComponent(Graphics g) method with the current graphics context as the parameter. In the code for this method, you almost always call super.paintComponent(g) to do whatever the parent's class said paintComponent(g) should do, including using the correct internal (hidden) rendering sequence. The code for BodyPartsCanvas illustrates this process. BodyPartsCanvas is where the list of body parts, BPList, draws itself. The view, BodyPartsGUI, contains two instances of BodyPartsCanvas in order to draw the two lists of body parts.

     public class BodyPartsCanvas extends JPanel
     {
         // Other fields and methods...

         // ...

          public void paintComponent(Graphics g)
          {
              super.paintComponent(g);
              // code to draw on g....
          }
     }

You never call paintComponent()directly. Instead, you should call repaint() to let Java schedule the repaint process and properly call paintComponent(). This is illustrated in the code for the action listeners for the left button in BPControl. The ActionListener object attached to the left button in the view is typically created as an anonymous inner class.

     _frame.get_jButtonLeft().addActionListener(
         new java.awt.event.ActionListener()  // anonymous inner class!
         {
             public void actionPerformed (ActionEvent e)
             {
                 // code to manipulate _rightBPList and _leftBPList here
           
                 _frame.get_pnlBodyPartsLeft().repaint();   // redraw the left body parts list
                 _frame.get_pnlBodyPartsRight().repaint(); // redraw the right body parts list.
             }
         });

Below is a UML diagram displaying a partial taxonomy tree for Java GUI components. We are only interested in working with Swing components. The Swing components all start with a capital 'J'.

swing.png (12190 bytes)

Note that JPanel extends JComponent, which extends Container. So >JPanel is a Container and can contains any AWT/Swing component. This is an example of the composite pattern.