INFORMATION & COMPUTER SCIENCE DEPARTMENT, KFUPM

ICS201, SECTIONS 52  (002 Semester)

INTRODUCTION TO COMPUTER SCIENCE

LAB  #06 Simple Applications of Java Threads

 

Instructor: Bashir M. Ghandi

 


Objectives:

 

1.         How to write animation programs Using Java threads.

Animation may be defined as the creation of artificial moving images.  The motion effect of animation objects on the screen can be achieved by drawing successive frames at a relatively high speed (usually about 10-20 times per second).

 

It is more common to have animation programs as applets rather than as applications.  For this reason, our example animation programs will be applets rather than applications. In any case, we have learnt how to change an applet program into an application and vice-versa.

 

As you learnt in the lectures, a thread is typically executed in a loop which is normally controlled by some event within or outside the program.  In the same way, to update the screen multiple times per second (in order to create the animation effect), you need to create a new Java thread that contains an animation loop. The animation loop is responsible for keeping track of the current frame and for requesting periodic screen updates.

 

Since we want the thread to be updating the screen multiple times, we want to send the thread to sleep at intervals between the updates.  For how long should the thread sleep?  We can pass this as a command-line parameter (we have seen how to do this in Lab 4) if we are running the program as an application.  For applets we can do this by passing in an applet parameter.

 

Here is an example of what you would put in your HTML document:

 01   <applet code=AnimationApplet.class width=200 height=200>
 02   <param name=fps value=20>
 03   </applet>

Line 02 specifies the applet parameter named fps (frame per second) with value 20.

The following gives a general skeleton of an applet-based animation program using swing:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
class MyPanel extends JPanel implements Runnable {
    int delay;
    Thread animator;
    //instant variable declarations here
 
    public MyPanel(int delay) {
        setSize(400, 400);
        //other initializations here
        
        animator = new Thread(this);
        animator.start();
    }    
 
     public void paintComponent(Graphics  g) {
        super.paintComponent(g);
        //drawing statements here
     }
 
    public void run () {
       while(true){
               //statements to advanced animation frames
               try{
                  Thread.sleep(delay);
               } catch(InterruptedException e){}
               repaint();
        }
 
        //other methods may be here
    }
}
 
public class SalamShabab extends JApplet{
    private MyPanel panel;
    //declare other necessary components hare
    public void init() {
        String str = getParameter("fps");
        int fps = (str != null) ? Integer.parseInt(str) : 10;
        int delay = (fps > 0) ? (1000 / fps) : 100;
        Container cp = getContentPane();
        panel = new MyPanel(delay);
        
        //create other components here and there listeners and add them to cp
 
        cp.add(panel);
    }
}    
 
NOTES:
1.        The  init() method of the applet computes the delay between the screen update times.  As you can see this value is read from the applet parameter that we have given in the HTML file.
 
2.        The constructor of the class implementing the Runnable interface is used to create the thread and start it by calling the start() method.
 
3.        The run() method will be called by the start() method in some kind of loop by the system. The statements that advance the frame are usually placed in the run method (since the run method is called in a loop).  Before the end of the run method, the repaint() should be called so that the new frame will be drawn on the applet window.
 

With this introduction, we are now ready to take our first animation example.

 

2.         Example 1: Animating our Famous "Salam Shabab" Program


The following example animates the words “Salam” and Shabab”  so that they go up and down the screen repeatedly.

It also include a start/stop button which can be used to suspend and resume the animation.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
class DrawingArea extends JPanel implements Runnable {
    private Font myFont;
    private int increment = 1;
    public int xSize, ySize, yCoord = 0;
    int delay;
    Thread animator;
    private boolean onOff=true;
 
    public DrawingArea(int delay) {
        xSize=400; 
        ySize=350;
        setSize(xSize, ySize);
        myFont = new Font ("Serif", Font.ITALIC, 30);
        
        animator = new Thread(this);
        animator.start();
    }    
 
    public void setOnOff(boolean onOff) {
       this.onOff = onOff;
     }
 
        public void paintComponent(Graphics  g) {
            super.paintComponent(g);
        g.setColor(Color.yellow);
        g.fillRect(0,0,xSize, ySize);
        g.setColor (Color.red);
        g.setFont(myFont);
        if (onOff) {
                g.drawString ("Salaam ", xSize/2-100, ySize/2 + yCoord);
                g.drawString ("Shabab!", xSize/2, ySize/2 - yCoord);
            }
     }
 
    public void run () {
       while(true){
               yCoord = yCoord + increment;
               if((yCoord == (ySize-50)/2 || (yCoord == -(ySize-50)/2)))
                    increment = -increment;
               try{
                  Thread.sleep(delay);
               } catch(InterruptedException e){}
               repaint();
        }
    }
}
 
public class SalamShabab extends JApplet{
    private Button myButton;
    private boolean onOffButton = true;
    private DrawingArea da;
    public void init() {
        int delay = Integer.parseInt(getParameter("fps"));
        if (delay<10)
            delay = 10;   
        Container cp = getContentPane();
        cp.setLayout(new BorderLayout());
        da = new DrawingArea(delay);
        
        myButton = new Button ("Start/Stop");
        myButton.addActionListener(new ActionListener(){
             public void actionPerformed(ActionEvent ae){
                onOffButton = !onOffButton;
                da.setOnOff(onOffButton);
                }
        });
        cp.add(myButton,BorderLayout.NORTH);
        cp.add(da, BorderLayout.CENTER);
    }
}        

 

Note: Compare this program with the skeleton above.  Notice the additional declarations, the changes to the methods init(), run() and the  paintComonent() methods.

 

Notice that the variable yCoord is the one used to control the up-and-down movement of the "Salaam" and "Shabab" words; Play with this variable and the delay parameter and see the effect. See Exercise 1 at the end of this document.

 


3.         Example 2: Car Racing Applet.

The following example animates two cars racing across the screen.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
 
class DrivingLane extends JPanel implements Runnable {
    private int frame;
    private int delay;
    private Thread animator;
    private Image car;
    static final int WIDTH = 600;
    static final int HEIGHT = 200;
    private int xPosition, speed;
    private Random random;
 
    public DrivingLane(Image car, int delay) {
        this.car = car;
        this.delay = delay;
        frame = 0;
            setSize(WIDTH,HEIGHT);
        xPosition = getWidth();
        random = new Random();
        speed = random.nextInt(5)+1;
  
        animator = new Thread(this);
        animator.start();
    }
 
    public void run() {
        while (true) {
            repaint();
                speed = random.nextInt(5)+1;
               xPosition -= speed;
               if (xPosition < -60)
                   xPosition = getWidth();
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.white);
        g.fillRect(0, 0, getWidth(), getHeight());
        
        g.drawImage(car, xPosition, getHeight()/2, this);
    }
}
 
public class CarRacing extends JApplet {
        public void init() {
        int delay = Integer.parseInt(getParameter("fps"));
        if (delay<10)
            delay = 10;   
        Image car = getImage(getCodeBase(),"Lab6Images/car.gif");
        
        DrivingLane lane1 = new DrivingLane(car, delay);
        DrivingLane lane2 = new DrivingLane(car, delay);
        Container cp = getContentPane();
        cp.setLayout(new GridLayout(2,1));
        cp.add(lane1);
        cp.add(lane2);
    }
}

 

Notice that each car is drawn in a different panel control by a different thread.  Notice also how the speed of the cars was generated randomly.  Again play around with these random values and observe the effect.

 

4          More threads.
   

In the above two examples, we added only one and then two user-defined thread to the programs.  The following example shows how you can have many threads each controlling a particular task in a program.

 

The example creates a grid of boxes with each one being controlled by a separate thread, changing the colors of the boxes in a random manner.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
class ColorBox extends JPanel implements Runnable {
  private Thread t;
  private int pause;
  private static final Color[] colors = {Color.black, Color.blue, Color.cyan, 
                                   Color.darkGray, Color.gray, Color.green,
                                   Color.lightGray, Color.magenta, 
                                   Color.orange, Color.pink, Color.red, 
                                   Color.white, Color.yellow };
  private Color cColor = newColor();
 
  public ColorBox(int pause) {
    this.pause = pause;
    t = new Thread(this);
    t.start(); 
  }
  
  private static final Color newColor() {
    return colors[(int)(Math.random() * colors.length)];
  }
 
  public void paintComponent(Graphics  g) {
    super.paintComponent(g);
    g.setColor(cColor);
    Dimension s = getSize();
    g.fillRect(0, 0, s.width, s.height);
    System.out.println(s.width+","+s.height);
  }
 
  public void run() {
    while(true) {
      cColor = newColor();
      repaint();
      try {
        t.sleep(pause);
      } catch(InterruptedException e) {}
    } 
  }
} 
 
 
public class ColorBoxes extends JApplet {
  private int grid = 12;
  private int pause = 50;
  public void init() {
          String gsize = getParameter("grid");
          if(gsize != null)
              grid = Integer.parseInt(gsize);
          String pse = getParameter("pause");
          if(pse != null)
             pause = Integer.parseInt(pse);
      
      Container cp = getContentPane();
      cp.setLayout(new GridLayout(grid, grid));
      for (int i = 0; i < grid * grid; i++)
           cp.add(new ColorBox(pause));
  }
}
 

 

 

4          Assignment.

1.             Modify the program in Example 1 to make the "Salaam" and the "Shabab" in two different vertical panels and each controlled by its own thread.  (Similar to the Car racing example).

 

2.             Modify the Car racing example my adding one more Driving lane.  Note that you need to change the layout of the content pane to have three rows instead of two.

 

3.             Write an applet using swing (JApplet), which moves the world1.gif image in the folder Lab6Images, around the screen both horizontally and vertically.  You can open the file, MovingWorld.html and execute it to see the required effect.

 

4.             Modify each of the examples of this lab so that they can also function as applications.