INFORMATION & COMPUTER SCIENCE DEPARTMENT, KFUPM

ICS201, SECTIONS 52  (002 Semester)

INTRODUCTION TO COMPUTER SCIENCE

LAB  #04 Experience with Graphical User Interfaces and Event Handling

 

Instructor: Bashir M. Ghandi

 


Objectives:

To gain experience with:

 

1.         Example 1: Experience with Simple GUI Components and Events.

In Example 2 of Lecture 12, we considered an applet that tracks the position of the mouse and displays the coordinates of the point at which the different mouse events take place and prints then on the DOS window.  A better behavior for this applet could be to display the message on the applet window itself.  This is what the first example below does:

 

import java.applet.Applet;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.TextField;
 
public class AWTMouseSpyApplet extends Applet implements MouseListener{
   private TextField textField = new TextField(23);
 
   public void init() {
        add(textField);
        addMouseListener(this);
   }
   public void mouseClicked(MouseEvent me){
     textField.setText("Clicked at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseEntered(MouseEvent me){
     textField.setText("Entered at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseExited(MouseEvent me){
     textField.setText("Exited at ("+me.getX()+", "+me.getY()+")");
   }
   public void mousePressed(MouseEvent me){
     textField.setText("Pressed at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseReleased(MouseEvent me){
     textField.setText("Released at ("+me.getX()+", "+me.getY()+")");
   }
}

 

Notes:   The only changes made to the program in Example 2 of Lecture 12 to obtain the above are:

 

1.1       Using Swing Components in Example 1.

We now modify Example 1 slightly by using JApplet and JTextfield instead of Applet and Textfield.  Recall that for the JApplet, we cannot call the add() method of Component directly to add the desired components.  We have to get the content pane of the JApplet window first and then add the components. 

Make these changes and save the new applet as SwingMouseSpyApplet and run it side-by-side the one using the AWT components.  Do you notice any differences?

One obvious difference you'll notice is that the text field onto which mouse coordinates are written spans the whole applet window in the JApplet  version.  This is because the default layout manager for the content pane of JApplet  window is BorderLayout, while that of  applets is FlowLayout (as inherited from Panel).  Thus, if you want the text area in the JApplet-based program to occupy a small portion of the window as in the Applet-based program, you have to change the layout of the content pane to FlowLayout.  Do it!

 

For both these programs, you'll notice that the mouse coordinate displayed in the text field can be edited.  You can make this message uneditable using the setEditable() method.  Again, do this!

 

1.1.1    Why do we need to call getContentPane()?

The following figure should give an idea of the differences between AWT frames and Swing Frames. Note that the requirement of getting the content pane applies to JDialog and JInternalFrame instances as well.

1.2    Making the applet in Example 1 into an application.

The next minor modification is to change the program into an application. You need to make the following changes:

 

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import javax.swing.JFrame;
import javax.swing.JTextField;
 
public class MouseSpyApplication extends JFrame implements MouseListener{
   private JTextField textField = new JTextField(23);
 
   public MouseSpyApplication() {
        Container cp = getContentPane();
        cp.setLayout(new FlowLayout());
        cp.add(textField);
        textField.setEditable(false);
        addMouseListener(this);
   }
   public void mouseClicked(MouseEvent me){
     textField.setText("Clicked at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseEntered(MouseEvent me){
     textField.setText("Entered at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseExited(MouseEvent me){
     textField.setText("Exited at ("+me.getX()+", "+me.getY()+")");
   }
   public void mousePressed(MouseEvent me){
     textField.setText("Pressed at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseReleased(MouseEvent me){
     textField.setText("Released at ("+me.getX()+", "+me.getY()+")");
   }
   public static void main(String[] args) {
        MouseSpyApplication application = new MouseSpyApplication();
  
        application.addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent event) {
                               System.exit(0);
                       }
               });
        application.setTitle("Applet Coverted into Application");
        application.setSize(300, 300);
        application.show();  
 } 
}

 

1.3       Modifying Example 1 to work as an applet as well as an application (two programs into 1!).

Now that we have modified the applet, converted it into an application we are ready to make the program into both an applet and an application.  It is clear from the above examples that the program should contain both the applet code as well as the main() method.  The steps for making an applet into an application could be summarized thus:

 

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JTextField;
 
public class MouseSpyAppletAndApplication extends JApplet implements MouseListener{
   private JTextField textField = new JTextField(23);
 
   public void init() {
        Container cp = getContentPane();
        cp.setLayout(new FlowLayout());
        cp.add(textField);
        textField.setEditable(false);
        addMouseListener(this);
   }
   public void mouseClicked(MouseEvent me){
     textField.setText("Clicked at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseEntered(MouseEvent me){
     textField.setText("Entered at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseExited(MouseEvent me){
     textField.setText("Exited at ("+me.getX()+", "+me.getY()+")");
   }
   public void mousePressed(MouseEvent me){
     textField.setText("Pressed at ("+me.getX()+", "+me.getY()+")");
   }
   public void mouseReleased(MouseEvent me){
     textField.setText("Released at ("+me.getX()+", "+me.getY()+")");
   }
   public static void main(String[] args) {
       MouseSpyAppletAndApplication applet=new MouseSpyAppletAndApplication();
        applet.init();
        JFrame application = new JFrame();
        application.getContentPane().add(applet);
        application.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                               System.exit(0);
                       }
               });
        application.setTitle("Applet Coverted into Application");
        application.setSize(300, 300);
        application.show();  
   } 
}

 

Now you can run this applet both using the appletviewer as well as using the java virtual machine. Note that the line 

    application.setSize(300,300);

in the main() method above sets the dimensions of the window into which the applet will be displayed when run as an application.  Where are the dimensions set when run on the browser?

    

1.4       Using Command-line Arguments in Java Programs.

Since ICS102, you have taken the signature of the main() method from us on trust.  You would have wondered what purpose the parameter to this method serves.  In this section we will illustrate the use of that parameter.

 

The window dimension in the above application is fixed.  If you wish to change that then you have to change the setSize() method and recompile. A better way of doing this modification without recompilation is to pass the dimensions as command-line parameters. 

To do this, we add the following fields and methods:

 

       private static int width, height;
       static void setDefaultSize() {
         width  = 300;
         height = 300;
       }
       if (args.length == 2 ) {
         width  = Integer.parseInt( args[0] );
         height = Integer.parseInt( args[1] );
       } else setDefaultSize(); // no command-line arguments
       application.setSize(width,height);
 

These two fields are now used to set the display window dimensions when the program is run as an application.  With this you can now call the program, for example, as follows:

            C:\>java MouseSpyAsAppletAndApplication 400 300

            C:\>java MouseSpyAsAppletAndApplication 500 700

            C:\>java MouseSpyAsAppletAndApplication

 

2.            Random Graphics Generator

From the above ideas we are going to build an applet-cum-application program which, on button presses, generates and draws graphics shapes at random positions in the program's window.

In similarity with the program in Example 1, this program has a JPanel (compared to the text field in Example 1) where the random graphics objects will be drawn.

Panels are one of the containers frequently used to properly lay out different components inside a container. 

·                JPanels, like other Swing components, inherit the paintComponent() method from JComponent.  

·                 This method, which needs to be overridden, helps to draw graphics properly. 

·                Unlike buttons, JPanels do not create events but can recognize lower-level events like mouse and key events.

Here is the code that specifies a dedicated panel for drawing the figures. We override the paintComponent() method to draw a random shape based on the user's selection

 

import java.awt.Graphics;

import javax.swing.JPanel;

 

public class DrawingPanel extends JPanel {

   private int currentChoice = -1;  // don't draw first time

   private int width = 100, height = 100;

  

   public DrawingPanel(int w, int h) {

      width = ( w >= 0 ? w : 100 );

      height = ( h >= 0 ? h : 100 );

   }

   public void paintComponent(Graphics g) {

      super.paintComponent( g );

      switch( currentChoice ) {

         case 0:

            g.drawLine( randomX(), randomY(), randomX(), randomY() );

            break;

         case 1:

            g.drawRect( randomX(), randomY(), randomX(), randomY() );

            break;

         case 2:

            g.drawOval( randomX(), randomY(), randomX(), randomY() );

            break;

      }

   }

   public void setCurrentChoice(int c) {

      currentChoice = c;

      repaint();

   }

   private int randomX() {

      return (int) (Math.random() * width);

   }

   private int randomY() {

      return (int) (Math.random() * height);

   }

}

 

We now turn to the applet which makes use of the panel to draw the random figures.

 

import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;
 
public class RandomShapes extends JApplet {
   private JButton choices[];
   private String names[] = {"Line", "Rectangle", "Oval" };
   private JPanel buttonPanel;
   private DrawingPanel drawingArea;
   private int width = 300, height = 200;
   public void init() {
      drawingArea = new DrawingPanel( width, height );
      choices = new JButton[ names.length ];
      buttonPanel = new JPanel();
      buttonPanel.setLayout(new GridLayout( 1, choices.length ) );
      ButtonHandler handler = new ButtonHandler();
      for ( int i = 0; i < choices.length; i++ ) {
         choices[i] = new JButton( names[i] );
         buttonPanel.add( choices[i] );
         choices[i].addActionListener(handler);
      }
      Container c = getContentPane();
      c.add(buttonPanel, BorderLayout.NORTH );
      c.add(drawingArea, BorderLayout.CENTER );
   }
   public void setWidth( int w ) {
      width = ( w >= 0 ? w : 300 );
   }
   public void setHeight( int h ) {
      height = ( h >= 0 ? h : 200 );
   }
   public static void main( String args[] ) {
      int width, height;
      if ( args.length != 2 ) {  // no command-line arguments
         width = 600;
         height = 400;
      }
      else {
         width = Integer.parseInt( args[ 0 ] );
         height = Integer.parseInt( args[ 1 ] );
      }
      // create window in which applet will execute
      JFrame applicationWindow =
         new JFrame( "An applet running as an application" );
      applicationWindow.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e ) {
               System.exit( 0 );
            }
         }
      );
      RandomShapes appletObject = new RandomShapes();
      appletObject.setWidth( width );
      appletObject.setHeight( height );
      appletObject.init();
      applicationWindow.getContentPane().add( appletObject );
      applicationWindow.setSize( width, height );
      applicationWindow.show();
   }
   private class ButtonHandler implements ActionListener {
      public void actionPerformed( ActionEvent e )
      {
         for ( int i = 0; i < choices.length; i++ )
            if ( e.getSource() == choices[ i ] ) {
               drawingArea.setCurrentChoice(i);
               break;
            }
      }
   }

 

3.            Enhancements.

       Enhance the above program as suggested below.

1.             Modify the buttons  labels as: RandomCar, RandomTruck and RandomShape respectively.  When the first button is pushed, it should display an image of a car at a random location on the window.  The other two buttons should do similarly but for trucks and random graphic shapes (line, rectangle and circle).  Hint: Refer to Exercise P9.6 on Page 392-393 of your Java Textbook for the car and truck drawings.

2.             You will notice that when the random graphics are displayed, they are sometimes not visible on the window.  Is it possible to force the random graphics drawing to be displayed within the set window size? Modify the program to achieve this or explain why this may not be done and the possible implications.