CSERD


  • userhome
  • catalog
  • resources
  • help

Java Applet Programming


Shodor > CSERD > Resources > Tutorials > Java Applet Programming

  


Java Applet Programming - Lesson 2

Making it More Interactive

All right, so by now you're drawing on the screen, and wondering when you are going to write the next killer game and be a multizillionaire.

That may take a while.

However, we can move on to the next part of the process. As we mentioned before, the primary aspect of applets and applications is the loop structure, you check for events, make any computations you need, and redraw the screen.

You've learned how to draw to the screen, now let's work on how to make this more interactive. In order to do that, we need some controls, and we need to know how to respond to those controls.

Laying out the applet

To have both controls and a drawing area, we need to partition the applet into two parts, one which contains the controls, and one which contains a drawing area. The Java AWT has a class designed for holding other screen objects called a Panel. The Panel is what you will use to place your controls.

A second object is available for the purposes of drawing called a Canvas.

The following code creates a screen which contains three Buttons, which will eventually change the color of the Canvas (after we add some functionality).

import java.awt.*;
import java.applet.*;

public class ColorChange extends Applet{

   Panel rightside;             //Panel to hold controls
   Canvas leftside;             //Canvas for drawing
   Button red;                  //first button
   Button blue;                 //second button
   Button green;                //third button

   public void init(){          //screen set up
                                //in init routine

      setLayout(new GridLayout(1,2));   //main applet
                                        //split into two
                                        //parts

      leftside = new Canvas();          //Canvas instantiated
      rightside = new Panel();          //Panel instantiated
      leftside.setSize(getSize().width/2,getSize().height);  
      rightside.setSize(getSize().width/2,getSize().height); 
                           //sizes are set to half the width of the screen
                           //but the whole height.
      add(leftside);       //elements are added to the applet
      add(rightside);
      
      rightside.setLayout(new GridLayout(3,1));
                           //control panel is divided into 3 parts
      
      rightside.add(red = new Button("Red"));      //add buttons
      rightside.add(blue = new Button("Blue"));    //to panel
      rightside.add(green = new Button("Green"));
   }
}

OK, so what does this applet do? We introduce three special classes from the AWT toolkit: Panels, Canvases, and Buttons. Both the applet and the Panel have their layout set with the GridLayout layout manager. What layout managers do is decide where to put stuff on the screen, and how big they should be. Check the AWT reference for more on the different layout managers. The GridLayout is perhaps the easiest to use, as it simply breaks up an object into an evenly spaced grid.

Variable scope

Notice that many of the variables are declared inside of the class, but not inside of the init() routine. Where a variable is declared tells the computer what scope the variable has, that is, who understands what that variable is. When you define a variable inside of a function, that variable cannot be used outside of the function. By declaring many of the variables at the same level as the routines that will be called in the ColorChange class, we ensure that all routines will have access to them

Applet layout: The init() routine

One of the functions you can override in an applet is the init() routine, which is called to set the layout of the applet. We use one of the most common and simple to use layouts for this applet, the GridLayout, which breaks up the applet into an evenly spaced grid. We will see in the next lesson that we can use panels within panels to further subdivide an applets layout, making robust designs with this simple layout manager. Notice that for this applet, we split the screen into two halves. On the left side of the applet, we place a Canvas, which is a class in AWT designed for a drawing space. On the right side of the applet, we place a Panel, which is a special class designed to hold other classes. We subdivided the panel into 3 parts, and add 3 Buttons to the panel.

Compile this applet, create a web page for it, and view it in your favorite browser.

Creating a drawing space

Notice that as you click the buttons, currently nothing happens. We still need to do two things, first, we need to set up the drawing area, and second, we need to add event handling. So how do we set up the drawing area? We mentioned earlier that a Canvas would be used, but very little other than that was said. The reason for this is that we don't use the Canvas directly, but rather we create our own version of a Canvas, with our own special instructions. This is called class inheritance. To create our own kind of canvas, in the file CanvasObject.java, enter the following code.
import java.applet.*;
import java.awt.*;
import java.lang.Math;

public class CanvasObject extends Canvas { 
     //we create our own version of the Canvas class to
     //meet our specific needs.

        Image im;          //We need an Image and Graphics       
        Graphics buffer;   //buffer in memory for
                           //double buffering
                           
        Color thecolor;    //We need to store the current
                           //color in memory


        public void initCan(){  //this routine handles the
                                //initial setup, including
                                //storing space in memory
                                //for the graphics buffer
                                
                im=createImage(getSize().width,getSize().height);
                buffer=im.getGraphics();
                
                thecolor = Color.black;
       }

        public void update (Graphics g) {
              //We override update to prevent the applet
              //from the default action of clearing
              //the screen every redraw, and causing screen
              //flicker
              paint(g);
        }

        public void prepaint()  {
              //prepaint draws to the graphics buffer, not
              //the screen, so that we do not see drawing
              //in progress.
              buffer.setColor(thecolor);
              buffer.fillRect(0,0,getSize().width,getSize().height);
              repaint();
        }

        public void paint( Graphics g ) {
              //paint places the image stored in memory
              //onto the screen as a single maneuver.
              g.drawImage(im, 0, 0, this);
        }

        public void changeColor(Color color){
              //changecolor allows the main applet to
              //change the canvases color.
              thecolor = color;
        }
}

This code creates a custom designed Canvas object, with our own instructions, but our original code needs to be told to use this CanvasObject instead of a Canvas. Make the following changes to you applet.

import java.awt.*;
import java.applet.*;

public class ColorChange extends Applet{

//...
//   Canvas leftside;             //Canvas for drawing
//becomes
   CanvasObject leftside;
//...
//      leftside = new Canvas();          //Canvas instantiated
//becomes
      leftside = new CanvasObject();
//...

//...
//at end of init() routine, add
      leftside.initCan();    //initialize graphics buffer
      leftside.prepaint();   //do initial screen draw

Custom classes

The benefit of using a predesigned class is that most of the work has been done for you, and the rules for using the classes are well documented. However, sometimes the classes provided in any API do not meet your specific needs. Drawing spaces are a prime example of this. The standard method of creating your own drawing space is to take advantage of class inheritance, and write your own class which inherits for the standard drawing space.

Double Buffering

In our first example, we overrode the Applet classes paint routine. Canvas also has a paint routine, and we will override it here. However, in order to have more fluid graphics, we will introduce what is known as double buffering. When you draw directly to the screen, animation can be very jumpy, as the user sees not only the drawing process as is takes place, but also the process of clearing the screen in between each call to paint. Double buffering refers to the process of creatin a graphics context in memory, drawing to that, and placing the entire image onto the screen at once, without clearing the screen. The key routines in Canvas which need to be overridden are update() and paint(). The update routine by default clears the screen and then calls paint, we just want it to call paint. Notice that all that the paint routine does is copy the memory image to the screen, we need a second routine, prepaint, to draw to the memory graphics context. Also, the computer needs to know how large to make the memory graphics context, so we need a routine which is called after the custom canvas is sized and placed on the applet to initialize the memory graphics context.

OK, so once that is done, compile it and see what you have.

You should now see the drawing screen as a black screen. The template drawing canvas presented here implements what is known as double buffering, that is, rather than drawing directly to the screen, you draw instead to memory, and place that memory on the screen all at once. This allows you to have flicker free animation, because the user never sees the screen get cleared in between two drawings.

Handling Events

All we need to do now is add in event handling. Event handling in Java 1.1 is handled by means of "listeners". Basically, you have an object which can say something (post an event). Other objects listen for those events. The process gernally boils down to

  1. Telling the compiler you are going to listen for events
  2. Telling the object you are listening to that you should be added to its list of people to tell things to
  3. Adding a routine to do something when told something

The first step involves importing the java.awt.event heirarchy

import java.awt.event.*;

and telling the applet that you are an ActionListener.

public class ColorChange extends Applet implements ActionListener {

The second step involves telling the buttons that you are going to listen for their action events, so that they will send them to you.

      rightside.add(red = new Button("Red"));      //add buttons
      rightside.add(blue = new Button("Blue"));    //to panel
      rightside.add(green = new Button("Green"));

      // add action listeners
      red.addActionListener(this);
      blue.addActionListener(this);
      green.addActionListener(this);

      leftside.initCan();
      leftside.prepaint();

Finally, we need an actionPerformed routine that lets the code know what to do when it gets an event.

   public void actionPerformed(ActionEvent e) {
      if (e.getSource()==red) {
         leftside.changeColor(Color.red);
         leftside.prepaint();
      } else if (e.getSource()==blue) {
         leftside.changeColor(Color.blue);
         leftside.prepaint();
      } else if (e.getSource()==green) {
         leftside.changeColor(Color.green);
         leftside.prepaint();
      }
   }

actionPerformed

There are many different types of events. Buttons post action events, Choice controls post item events, mouse movements will produce mouse motion events, mouse clicks will produce mouse events, and on and on. As you go on in your applet programming life, you will get to know and love each of these unique types of events, but a complete discussion is beyond the scope of this tutorial.

Compile and view. You should now have your first java applet with double buffered graphics, AWT controls, and event handling!

Check the examples page if you need a hint. Go on to the next lesson!


©1994-2025 Shodor