CS 4773 Object Oriented Systems


The Java Language (continued)


Writing Text

Choosing a font:
/* 12 point Courier bold font */
myGC1.setFont(new Font("Courier",Font.BOLD,12));

/* 20 point Times font */
myGC2.setFont(new Font("Times",Font.PLAIN,20));
To write text use

void drawString(String str, int x, int y)

myGC1.drawString("Hi there",10,20);
myGC2.drawString("Hi there",10,60);
Information about the size of a string in a font can be obtained using FontMetrics
FontMetrics fm;

fm = getFontMetrics(myGC1.getFont());
ascent = fm.getMaxAscent();
descent = fm.getDescent();
width = fm.stringWidth("How are you");

A Simple Applet

/* < applet code="animation_test.T1" width=200 height = 100 >
 * < PARAM NAME = fontsize VALUE = 30 >
 * < PARAM NAME = message VALUE = hello >
 * < /applet > */
package animation_test;
import java.awt.*;
import java.applet.*;

public class T1 extends Applet {
   Image myimage; 
   Graphics myGC1; 
   Graphics myGC2; 
   int sizex = 150;
   int sizey = 80;
   int Times_Fontsize;
   String Times_String;
   
   public void paint(Graphics g) {
      g.drawImage(myimage,0,0,this);
   }

   public void init() {
      Times_Fontsize = Integer.parseInt(getParameter("fontsize"));
      Times_String = getParameter("message");
      myimage = createImage(sizex,sizey); 
      myGC1 = myimage.getGraphics(); 
      myGC2 = myimage.getGraphics(); 
                          /* 12 point Courier bold font */ 
      myGC1.setFont(new Font("Courier",Font.BOLD,12));  
                     /* Times_Fontsize point Times font */ 
      myGC2.setFont(new Font("Times",Font.PLAIN,Times_Fontsize)); 
      myGC1.setColor(Color.blue); 
      myGC2.setColor(Color.red); 
       
      myGC1.drawString("Hi there",10,20); 
      myGC2.drawString(Times_String,10,60); 
      myGC1.drawRect(100,20,30,10); 
      myGC2.fillRect(100,60,30,10); 

      repaint();
   }
}
This produces the following:

Click Here to run this applet.


Mouse Events

Mouse events are handled by overriding the handleEvent method.

Here is how some events are handled:

   public boolean handleEvent(Event e) {
      if (e.id == Event.MOUSE_DOWN) {
         showStatus("Down at ("+e.x+","+e.y+")");
         ...
      }  
      if (e.id == Event.MOUSE_UP) {
         showStatus("Down at ("+e.x+","+e.y+")");
         ...
      }  
      if (e.id == Event.MOUSE_DRAG) {
         showStatus("Drag to ("+e.x+","+e.y+")");
         ...
      }  
      return super.handleEvent(e);
   }

Buffering

The idea: draw into an image that is not being displayed.

When done, display the entire image.

Some useful methods:

In class Component

Image createImage(int width, int height)
creates a new image of a given size.

In class Image

Graphics getGraphics()
creates a graphics context for this image.

In class Graphics

Graphics create()
returns a new graphics context which is a copy of this one.

boolean drawImage(Image img, int x, int y, ImageObserver)
draws the image with its top corner at (x,y)
Typical usage: drawImage(im, 0, 0, this)


The Applet T2.java

This example draws a rectangle each time a mouse button is pushed.

/*
 * < applet code="animation_test.T2" width=200 height = 100 %gt
 * < /applet >
*/
package animation_test;
import java.awt.*;
import java.applet.*;

// This simple applet draws some text and a circle and
// then waits for mouse events.  It draws a red rectangle
// at the position of a mouse up.
public class T2 extends Applet {

   Image background; 
   Image foreground; 
   Graphics myGC1; 
   Graphics myGC2; 
   Graphics foreGC;
   int sizex = 150;
   int sizey = 80;
   int rectangle_count = 0;
   int last_rect_x;
   int last_rect_y;
   int rect_width = 30;
   int rect_height = 10;
   
   public void paint(Graphics g) {
      g.drawImage(foreground,0,0,this);
   }

   public void init() {
      background = createImage(sizex,sizey); 
      foreground = createImage(sizex,sizey); 
      myGC1 = background.getGraphics(); 
      myGC2 = background.getGraphics(); 
      foreGC = foreground.getGraphics(); 
                          /* 12 point Courier bold font */ 
      myGC1.setFont(new Font("Courier",Font.BOLD,12));  
                                 /* 20 point Times font */ 
      myGC2.setFont(new Font("Times",Font.PLAIN,20)); 
      myGC1.setColor(Color.blue); 
      myGC2.setColor(Color.green); 
      foreGC.setColor(Color.red); 
       
      myGC1.drawString("Hi there",10,20); 
      myGC2.drawString("Hi there",10,60); 
      myGC1.fillOval(100,30,20,20); 
      foreGC.drawImage(background,0,0,this);

      repaint();
      System.out.println("init done");
   }

   public boolean handleEvent(Event e) {
      int x;
      int y;
      if (e.id == Event.MOUSE_DOWN) {
         showStatus("Down at ("+e.x+","+e.y+")");
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_UP) {
         x = e.x;
         y = e.y;
         foreGC.fillRect(x,y,rect_width,rect_height);
         last_rect_x = x;
         last_rect_y = y;
         rectangle_count++;
         show_rectangle_count();
         repaint(1);
         return true;
      }
      return super.handleEvent(e);
   }

   void show_rectangle_count() {
      if (rectangle_count == 0)
         showStatus("No rectangles drawn yet");
      else
         showStatus("Rectangles: "+rectangle_count+
            ", Last at ("+last_rect_x+","+last_rect_y+")");
   }
}

Click Here to run this applet.


T3.java

This is similar to T2.java but it erases the old rectangle before drawing the new one.

   public boolean handleEvent(Event e) {
      int x;
      int y;
      if (e.id == Event.MOUSE_DOWN) {
         showStatus("Down at ("+e.x+","+e.y+")");
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_UP) {
         x = e.x;
         y = e.y;
         foreGC.drawImage(background,0,0,this);
         foreGC.fillRect(x,y,rect_width,rect_height);
         last_rect_x = x;
         last_rect_y = y;
         rectangle_count++;
         show_rectangle_count();
         repaint(1);
         return true;
      }
      return super.handleEvent(e);
   }
Click Here to run this applet.

T4.java and T5.java

If you watch at T3.java running, you will see a flashing of the screen when the new rectangle is drawn.

T4 is identical to T3, except that the region is bigger and the flashing is more apparent.

Click Here to run the T4 applet.

T5 is identical to T4 but overrides update to prevent the flashing

   public void update(Graphics g) {
      paint(g);
   }
Click Here to run the T5 applet.


T6.java

T6.java is similar to T5 but it drags the rectangle around when the mouse button is held down.
   public boolean handleEvent(Event e) {
      int x;
      int y;
      if (e.id == Event.MOUSE_DOWN) {
         showStatus("Down at ("+e.x+","+e.y+")");
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_UP) {
         x = e.x;
         y = e.y;
         foreGC.drawImage(background,0,0,this);
         foreGC.fillRect(x,y,rect_width,rect_height);
         last_rect_x = x;
         last_rect_y = y;
         rectangle_count++;
         show_rectangle_count();
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_DRAG) {
         x = e.x;
         y = e.y;
         foreGC.drawImage(background,0,0,this);
         foreGC.fillRect(x,y,rect_width,rect_height);
         last_rect_x = x;
         last_rect_y = y;
         rectangle_count++;
         show_rectangle_count();
         repaint(1);
         return true;
      }
      return super.handleEvent(e);
   }
Click Here to run the T6 applet.


The Applet java_test.java

This is the one you copied as part of your first assignment.
/*
   < Applet code = "java_test"
           width = 400 height = 400 >
   < /applet >
 */

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

public class java_test extends Applet {
   int width;
   int height;
   Button clearit;
   Image main_image;
   Color backColor;
   Color foreColor;
   Graphics backGC;
   Graphics foreGC;
   int image_width = 40;
   int image_height = 20;
   int down_x;
   int down_y;
   int drag_x;
   int drag_y;
   boolean drag_flag = false;

   public void init() {
      width = bounds().width;
      height = bounds().height;
      main_image = createImage(width,height);
   
      backColor = new Color(255,255,255);      // white
      foreColor = new Color(0,0,255);          // blue

      backGC = main_image.getGraphics();
      backGC.setColor(backColor);
      foreGC = main_image.getGraphics();
      foreGC.setColor(foreColor);
      clear_it(); 
      set_layout();
   }

   private void clear_it() {
      backGC.fillRect(0,0,width,height);
      foreGC.drawString("Click the mouse to plot down an oval.",10,50);
   }

   private void set_layout() {
      setLayout(new BorderLayout());
      add("South",clearit= new Button("Clear"));
   }

   public void update(Graphics g) {
      paint(g);
   }

   public boolean check_close(int x1, int y1, int x2, int y2) {
      if ( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) <= 10 )
         return true;
      return false;
   }

   public void paint(Graphics g) {
      g.drawImage(main_image,0,0,this);
      if (!drag_flag || check_close(down_x,down_y,drag_x,drag_y)) return;
      g.fillOval(drag_x-image_width/2,drag_y-image_height/2,
                         image_width,image_height);
      g.drawLine(drag_x,drag_y,down_x,down_y);

   }

   public boolean action(Event e, Object arg) {
      if ("Clear".equals(arg)) {
         clear_it();
         showStatus("Clear button pushed");
         repaint(1);
         return true;
      }
      return super.action(e,arg);
   }

   public boolean handleEvent(Event e) {
      if (e.id == Event.MOUSE_DOWN) {
         down_x = e.x;
         down_y = e.y;
         foreGC.fillOval(down_x-image_width/2,down_y-image_height/2,
                         image_width,image_height);
         showStatus("Plopping at ("+down_x+","+down_y+")");
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_UP) {
         if (check_close(e.x,e.y,down_x,down_y)) return true;
         foreGC.fillOval(e.x-image_width/2,e.y-image_height/2,
                         image_width,image_height);
         foreGC.drawLine(e.x,e.y,down_x,down_y);
         showStatus("Plopping line to ("+e.x+","+e.y+")");
         drag_flag = false;
         repaint(1);
         return true;
      }
      if (e.id == Event.MOUSE_DRAG) {
         drag_x = e.x;
         drag_y = e.y;
         drag_flag = true;
         showStatus("At ("+drag_x+","+drag_y+")");
         repaint(1);
         return true;
      }
      return super.handleEvent(e);
   }
   
}
Click Here to run this applet.


Layout

How to place buttons and other widgets. The following are the basic layout managers: Borderlayout allows you to place things around the border:

Here is an example applet:

/* < applet code = "layouttest.UIApplet" WIDTH = 200 HEIGHT = 200 >
   < /applet >
*/
package layouttest;
import java.awt.*;
import java.applet.*;

public class UIApplet extends Applet {
   public void init() {
      setLayout(new BorderLayout());
      setBackground(Color.red);
      setForeground(Color.white);

      add("North", new Button("North"));
      add("South", new Button("South"));
      add("Center", new Button("Center"));
      add("West", new Button("West"));
      add("East", new Button("East"));
   }
   public boolean action(Event evt, Object arg) {
      showStatus(((Button)evt.target).getLabel());
      return true;
   }
}

Click Here to run this applet.


Layouts can be nested.
/* < applet code = "layouttest.UIApplet1" WIDTH = 300 HEIGHT = 200 >
   < /applet >
*/
package layouttest;
import java.awt.*;
import java.applet.*;

public class UIApplet1 extends Applet {
   public void init() {
      setLayout(new BorderLayout());
      setBackground(Color.red);
      setForeground(Color.white);

      add("North", new Button("North"));
      add("South", new Button("South"));

      Panel p = new Panel();
      p.setBackground(Color.lightGray);
      p.setLayout(new BorderLayout());
      add("Center",p);
      p.add("North", new Button("P North"));
      p.add("South", new Button("P South"));
      p.add("Center",new Button("P Center"));
      p.add("West", new Button("P West"));
      p.add("East", new Button("P East"));
      
      add("West", new Button("West"));
      add("East", new Button("East"));
   }
   public boolean action(Event evt, Object arg) {
      showStatus(((Button)evt.target).getLabel());
      return true;
   }
}

Click Here to run this applet.


Gridlayout puts widgets in rectangular arrays.
/* < applet code = "layouttest.UIApplet2" WIDTH = 300 HEIGHT = 200 >
   < /applet >
*/
package layouttest;
import java.awt.*;
import java.applet.*;

public class UIApplet2 extends Applet {
   public void init() {
      setLayout(new BorderLayout());
      setBackground(Color.red);
      setForeground(Color.white);

      add("North", new Button("North"));
      add("South", new Button("South"));

      Panel p = new Panel();
      p.setBackground(Color.lightGray);
      p.setLayout(new GridLayout(2,3));
      add("Center",p);
      p.add(new Button("P 0 0"));
      p.add(new Button("P 0 1"));
      p.add(new Button("P 0 2"));
      p.add(new Button("P 1 0"));
      p.add(new Button("P 1 1"));
      p.add(new Button("P 1 2"));
      
      add("West", new Button("West"));
      add("East", new Button("East"));
   }
   public boolean action(Event evt, Object arg) {
      showStatus(((Button)evt.target).getLabel());
      return true;
   }
}

Click Here to run this applet.


Flowlayout lays out panels left to right then top to bottom, placing as many panels in a row as will fit.
/* < applet code = "layouttest.UIApplet3" WIDTH = 300 HEIGHT = 200 >
   < /applet >
*/
package layouttest;
import java.awt.*;
import java.applet.*;

public class UIApplet3 extends Applet {
   public void init() {
      setLayout(new BorderLayout());
      setBackground(Color.blue);
      setForeground(Color.white);

      add("North", new Button("North"));
      Panel q = new Panel();
      q.setBackground(Color.gray);
      q.setLayout(new FlowLayout());
      q.add(new Button("Queue 1"));
      q.add(new Button("Q 2"));
      q.add(new Button("Queue 3"));
      q.add(new Button("Q 4"));
      q.add(new Button("Queue 5"));
      q.add(new Button("Q 6"));
      q.add(new Button("Queue 7"));
      q.add(new Button("Q 8"));
      add("Center",q);

      Panel p = new Panel();
      p.setBackground(Color.lightGray);
      p.setLayout(new GridLayout(2,3));
      add("South",p);
      p.add(new Button("P 0 0"));
      p.add(new Button("P 0 1"));
      p.add(new Button("P 0 2"));
      p.add(new Button("P 1 0"));
      p.add(new Button("P 1 1"));
      p.add(new Button("P 1 2"));
      
      add("West", new Button("West"));
      add("East", new Button("East"));
   }
   public boolean action(Event evt, Object arg) {
      showStatus(((Button)evt.target).getLabel());
      return true;
   }
}

Click Here to run this applet.