Section 5.2
Introduction to Layouts, Components, and Events


JAVA HAS MANY CLASSES that work together to support a graphical user interface. These classes make up the Abstract Windowing Toolkit (AWT). The classes can be found in the packages java.awt and java.awt.event. The AWT is quite large and complex, more complex in fact than the basic Java programming language itself. This textbook will certainly not come close to telling you everything there is to know about it, but I will cover some of its major aspects in this chapter and the next.

To program with the AWT, you have to understand components, layouts, and events. Components are the visible objects that make up a GUI. Every component is an object that belongs to some subclass of the class java.awt.Component. Some components are containers, which can hold other components. An applet is an example of a container. The components in a container must be "laid out," which means setting their sizes and positions. This is ordinarily done by a layout manager, which is an object associated with a container that implements some policy for laying out the components in that container. Events are generated when the user interacts with a components. An event is represented by an object belonging to one of several classes in the java.awt.event package, such as ActionEvent and MouseEvent. An event has no effect unless a listener has been set up to listen for the event and respond to it.

So writing an applet generally involves setting up a layout for the applet, creating components and adding them to the applet, arranging for listeners to listen for events, and writing methods to respond when the events occur. For each of these steps there are many options or cases to consider. Rather than try to cover them all at once, in this section I will cover one possible way of doing things that will give you an idea of how it all works. Furthermore, this way of doing things is one that is often usable for real applets, and I will continue to use it for the rest of this chapter. The next chapter will cover many more types of components, events, and layout managers.

The layout that I will use will consist of a large drawing area with a row of controls above or below it. As an example, here is a modified version of the ColoredHelloWorldApplet from the previous section.

Sorry, but your browser
doesn't support Java.

I will use this applet as an example for the rest of this section. In this chapter, I'll stick to buttons for the controls, but there are several other types of components that could easily be added to the same general framework, such as checkboxes and text input boxes.


It is possible to draw directly on an applet, as I did in the previous section. However, it is not a good idea to do so when the applet contains components that will be laid out by a layout manager. The reason is that it's hard to be sure exactly where the components will be placed by the layout manager and how big they will be. A better idea is to add an extra component to the applet and do all the drawing on that component. The white rectangle in the above applet, where the "Hello World" message is displayed, is an example of such a component. This component is a member of a class ColoredHelloWorldCanvas which I have defined as a subclass of the class java.awt.Canvas. The Canvas class exists precisely for creating such drawing areas. An object that belongs to the Canvas class itself would be an empty "canvas." To create a canvas with content, you have to define a subclass of Canvas and write a paint() method for your subclass to draw the content you want.

When you use a canvas in this way, it's a good idea to put all the information necessary to do the drawing in the canvas object, rather than in the main applet object. The original colored hello world applet used an instance variable, textColor, to keep track of the color of the displayed message. In the new version, the textColor variable is moved to the ColoredHelloWorldCanvas class. This class also contains a method, setTextColor(), that the applet can use to tell the canvas to change the color of the message. This is good object-oriented program design: The ColoredHelloWorldCanvas class is responsible for displaying a colored greeting, so it should contain all the data and behaviors associated with its role. On the other hand, this class doesn't need to know anything about buttons, layouts, and events. Those are the job of the main applet class. This separation of responsibility helps reduce the overall complexity of the program.

So, here's the ColoredHelloWorldCanvas class:

        class ColoredHelloWorldCanvas extends Canvas {
        
              // A canvas that displays the message "Hello World" on
              // a white background in a big, bold font.  A method is
              // provided for changing the color of the message.

           Color textColor;  // Color in which "Hello World" is displayed.
           Font textFont;    // The font in which the message is displayed.
   
           ColoredHelloWorldCanvas() {
                 // Constructor.
              setBackground(Color.white);
              textColor = Color.red;
              textFont = new Font("Serif",Font.BOLD,24);
           }
   
           public void paint(Graphics g) {
                 // Show the message in the set color and font.
              g.setColor(textColor);
              g.setFont(textFont);
              g.drawString("Hello World!", 20,40);        
           }
   
           void setTextColor(Color color) {
                 // Set the text color and tell the system to repaint the canvas.
              textColor = color;
              repaint();
           }
   
        }  // end class ColoredHelloWorldCanvas

You should be able to understand most of this. The constructor calls the method setBackground() to specify that the background color of the applet should be white. The canvas is filled with this background color before the paint() method is called, so whatever the paint() method draws is displayed on a white background. The setTextColor() method is called by the applet when it wants to change the color of the displayed message. Note that setTextColor() calls repaint(). Since this repaint() method is in the ColoredHelloWorldCanvas class, it causes just the canvas to be repainted, not the whole applet. Every component has its own paint() and repaint() methods, and every component is responsible for drawing itself. This is another example of the way responsibilities are distributed in an object-oriented system.


The main applet class, ColoredHelloWorldApplet2, is responsible for managing all the components in the applet and the events they generate. The components include the drawing canvas and three buttons. These components are created and added to the applet in the applet's init() method, which looks like this:

      public void init() {

             // This routine is called by the system to initialize the applet.
             // It creates the canvas and lays out the applet to consist of a
             // bar of control buttons below the canvas.
          
          setBackground(Color.lightGray);

          canvas = new ColoredHelloWorldCanvas();

          Panel buttonBar = new Panel();  // a panel to hold the control buttons
       
          Button redBttn = new Button("Red");  // Create buttons and add them to the
          redBttn.addActionListener(this);     //    button bar.
          buttonBar.add(redBttn);
       
          Button greenBttn = new Button("Green");
          greenBttn.addActionListener(this);
          buttonBar.add(greenBttn);
       
          Button blueBttn = new Button("Blue");
          blueBttn.addActionListener(this);
          buttonBar.add(blueBttn);
       
          setLayout(new BorderLayout(3,3));  // Lay out the applet
          add("Center",canvas);
          add("South", buttonBar);

      }  // end init()

After setting the background color to light gray, this method creates the ColoredHelloWorldCanvas object that will be used for drawing. The variable canvas is an instance variable, which is defined outside the init() method. (It has to be an instance variable since it is used elsewhere in the applet, when it is necessary to change the canvas's display color.) The next line creates a Panel named buttonBar. A panel is a container that helps to organize other components. The buttons will be added to the panel, and then the panel will be added to the applet.

The next line, "Button redButtn = new Button("Red");", creates a button labeled "Red." Note that the variable redBttn is a local variable that does not exist outside the init() method. This is because once the button has been added to the applet, it will pretty much take care of itself. The statement "redBttn.addActionListener(this)" tells the button that the applet wants to be informed whenever the user clicks on the button. Recall that the word "this" refers to "this object," that is, to the applet itself. When the user clicks on the button, the button will call the applet's actionPerformed() method to let the applet know about it. We say that the applet is listening for action events from the button. Any object can be an action listener for a button, provided it implements the ActionListener interface and defines the actionPerformed method. The last thing we do with redBttn is to add it to the buttonBar. The "Green" and "Blue" buttons are handled the same way.

Now that the canvas and button bar have been created, it's time to lay out the applet as a whole. This is done by the last three lines of the init() method. We use a "BorderLayout," which can display one big component in the "Center" of the applet and up to four other components along the edges of the applet to the "North", "South", "East", and "West". In this case, the canvas is added in the "Center" position, with the button bar below it, to the "South".

When you write your own applets using a similar layout, you can follow the pattern in this sample init() method. You might want a different background color (which will show around the edges of the canvas and in the button bar). You'll be using a different class for your canvas. You might use more or fewer buttons, with different names. And you could put the button bar on the "North" instead of the "South".


The other major feature of the ColoredHelloWorldApplet2 class is its actionPerformed() method:

         public void actionPerformed(ActionEvent evt) {
         
            String command = evt.getActionCommand();
      
            if (command.equals("Red"))
               canvas.setTextColor(Color.red);
            else if (command.equals("Green"))
               canvas.setTextColor(Color.green);
            else if (command.equals("Blue"))
               canvas.setTextColor(Color.blue);
      
         }  // end init()

The parameter, evt, of this method is an object that carries information about the particular event that caused the routine to be called. Since the same method is called no matter which of the three buttons was clicked, we need to find out which button it was. The method evt.getActionCommand() returns the name of the button that was clicked (unless you've configured the button to send a different string). In this example, the command must be either "Red" or "Blue" or "Green". This method responds to the command by telling the canvas to set its text color to the appropriate color. The actionPerformed() method of any applet is likely to be similar to this one.


We can now put together the complete source code for the ColoredHelloWorldApplet2 class. The only remaining unknown in this code is a getInsets() method. The system uses this method to determine how wide a border to leave around the components in the applet. The color of the border will be the background color of the applet. I like using insets, but you can leave it out if you want.

        import java.awt.*;
        import java.awt.event.*;
        import java.applet.Applet;
        
        public class ColoredHelloWorldApplet2 extends Applet implements ActionListener {
        
           ColoredHelloWorldCanvas canvas;  // A canvas which actually displays the message
           
        
           public void init() {
        
                  // This routine is called by the system to initialize the applet.
                  // It creates the canvas and lays out the applet to consist of a
                  // bar of control buttons below the canvas.
                  
               setBackground(Color.lightGray);
        
               canvas = new ColoredHelloWorldCanvas();
        
               Panel buttonBar = new Panel();  // a panel to hold the control buttons
               
               Button redBttn = new Button("Red");  // Create buttons and add them to the
               redBttn.addActionListener(this);     //    button bar.
               buttonBar.add(redBttn);
               
               Button greenBttn = new Button("Green");
               greenBttn.addActionListener(this);
               buttonBar.add(greenBttn);
               
               Button blueBttn = new Button("Blue");
               blueBttn.addActionListener(this);
               buttonBar.add(blueBttn);
               
               setLayout(new BorderLayout(3,3));  // Lay out the applet
               add("Center",canvas);
               add("South", buttonBar);
        
           }  // end init()
           
           
           public Insets getInsets() {
           
                // This routine is called by the system to determine how much
                // space to leave between the edges of the applet and the
                // components that the applet contains.  It leaves a 3-pixel
                // border, which will be displayed in the background color.
                
              return new Insets(3,3,3,3);
              
           }
           
           
           public void actionPerformed(ActionEvent evt) {
           
                 // This routine is called by the system when an "action" is performed
                 // by the user, provided that the applet has been set as a "listener"
                 // for such events.  Responds to the buttons by setting the text
                 // display color of the canvas.
                 
              String command = evt.getActionCommand();
              
              if (command.equals("Red"))
                 canvas.setTextColor(Color.red);
              else if (command.equals("Green"))
                 canvas.setTextColor(Color.green);
              else if (command.equals("Blue"))
                 canvas.setTextColor(Color.blue);
              
           }  // end init()
           
           
} // end class ColoredHelloWorldApplet2

[ Next Section | Previous Section | Chapter Index | Main Index ]