JFrame Windows

The programs presented so far use either the console or JOptionPane dialog boxes to communicate with the user. In this section we'll explore the use of frame windows, which can be customized to hold any combination of grahical user interface (GUI) components, such as buttons, text fields, scroll bars, check boxes, etc. A frame window has a small frame around the window (i.e., the little strip on the edge of the window that a user can grab to resize the window) and a title bar at the top of the window:

Frame window with title bar and thin frame edge

To understand code that creates graphic images on the screen, you first need to understand how programs typically identify locations and distances on the screen.  The basic unit of measurement is a pixel -- a pixel is one tiny dot on the screen -- the combination of thousands (or millions) of these colored dots make up an image (i.e., several blue pixels in a row make a blue line).  The upper left hand corner of the screen (or window) is location 0,0.  The x-coordinate increases as you move to the right, and the y-coordinate increases as you move downward:

x and y coordinates

For example, in the image below the the red dot represents a greatly magnified red pixel at location 125,95:

sample x and y coordinates

In this section you will be creating many customize jFrame windows.  Before looking into customized JFrame windows, lets look at some simple JFrame windows. Below is a program that

Here is the SampleWin3 program:

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   
   public class SampleWin3
   {
      public static void main(String [] args)
      {
         JFrame frame = new JFrame("Alan Window");
         frame.setSize(400, 300);
         frame.setLocation(100, 75);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }

The frame window presented above is blank -- a title bar appears at the top of the window and a narrow border surrounds the window, but the content of the window is only a plain grey background.

  1. Copy the SimpleWin3 application shown above into a file named SimpleWin3.java. Compile and run the program.
  2. Modify the propram so that the frame window that is presented to the user is 250 x 80 pixels in size, and its upper lefthand corner is at position 20,20 on the screen.
  3. Modify the SimpleWin3 application again, so that it presents three different frame windows -- a 100x100 window in the upperleft side of the screen, a 150x450 window shown at the bottom lefthand corner of the screen, and a 300x200 window shown at the bottom righthand corner of the screen.  Give the windows titles of "Window 1", "Window 2" and "Window 3", respectively.

Here are the solutions to problem 1, problem 2, and problem 3.  Always try to come up with your own solutions before looking at what I have done.

Customizing JFrame -- Adding Components

This section will show how to visually add components, such as buttons and textfields to a window. A later section will show how to set up event handling to give these components some functionality.

A plain JFrame object displays an empty background, surrounded by a border frame and a title bar. In the example below we are going to customize the JFrame class via inheritance. Inheritance allows you to create a customized version of an existing class. In the example I create a customized a customized version of the JFrame class -- the customized class is called MyFrame. To customize a class you "extend" the definition of that class. MyClass's header line, below, is "class MyClass extends JFrame". The "extends" keyword pulls all of the JFrame class into the definition of the MyFrame class -- you then list only the new, extra, code in the MyFrame class. Below, the first attempt at the MyFrame class only adds a new constructor. To read more about inheritance, click here.

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   
   public class SampleWin4
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("Alan Window");
         frame.setSize(400, 300);
         frame.setLocation(100, 75);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {
      public MyFrame(String s)
      {
         super(s);
      }
   }

To add a component to a frame window you need to:

  1. Create name for the component (i.e., create a variable to hold a reference to the component)
  2. Create the component (via thew "new" operator)
  3. Visually add the component to the window

Additionally, in these examples we'll set the layout manager for the frame window to FlowLayout. When components are added to a window (or any other container) a layout manager determines how the components are placed onto the window. A flow layout indicates that the components are placed left-to-right across the window, wrapping back to the left edge once one "row" is filled up across the window.

The three step procedure described above is roughly the same for any visual component, such as JButtons, JTextFields, JCheckBoxes and JRadioButtons (among others). The steps below put a single JButton button onto the window.

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   
   public class SampleWin5
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("Alan Window");
         frame.setSize(400, 300);
         frame.setLocation(100, 75);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {
      JButton btnOK;          // Step 1 - a name
   
      public MyFrame(String s)
      {
         super(s);
         setLayout(new FlowLayout());
   
         btnOK = new JButton("OK"); // Step 2 - create the component
         add(btnOK);      // Step 3 - add it visually
      }
   }

Adding a text field component follows a similar three step procedure. Java text fields have several methods that allow you to control and access them. Two of the more useful methods are setText and getText:

   JTextField txt;
   txt = new JTextField("another");
   
   String s = txt.getText();
   txt.setText("the");
   txt.setText("cat");
   
   String s2;
   s2 = txt.getText();

The above code creates a text field object that initially contains the word "another". This is retrieved from the text field and stored in the String variable "s". The contents of the text field is then changed to "the", and then to "cat". The word "cat" is then retrieved and stored in the String variable "s2".

  1. Write a java application named SampleWin6 that presents a JFrame window with two buttons, one labeled "Submit" and another named "Clear".
  2. Add to your SampleWin6 java application from the previous question. Add a text field with the contents "100 Main Street" (the application will now have two buttons and a text field).
  3. Write a java application named SampleWin7 that presents a JFrame window with two buttons labled "Left" and "Right", and two textfields with the contents "Green" and "Blue".

Attempt to create your own solutions to the above problems.  Here is a solution to problem 2.  For a description of the solution to problem 2, click here Click for video.

Adding Event Handling

Clicking a button, putting text in a text field and presses the Enter key, selecting a checkbox, selecting an item out of a drop-down list -- these are all user actions that generate an event inside your Java application. The default response to an event is for your application is to do nothing. However, you can set up a chunk of code to get run when a specific event happens. Such a chunk of code is refered to as an "event handler".

For example, if your application presents a text field and a button labeled "Clear", then you could set up an event handler for the Clear button (i.e., you can specify that a certain chunk of code gets executed every time the clear button is pressed). The code associated with the Clear button (i.e., the event handler for the clear button) will set the contents of the text field to blanks. Once the event handler is set up, then every time the Clear button is pressed the content of the of text field is cleared. Note that in this example an event handler is setup for the button, but not for the text field. It is not necessary to set up an event handler for all of the visual components on the screen.

There are three steps required to setup event handling:

  1. Add the import statement "import java.awt.event.*;".
  2. Create the event handler class (here we use an innner class -- a class defined inside the MyFrame class).
  3. Create the handler object and CONNECT THE HANDLER OBJECT to the visually component.

Here is an application that presents a button and a text field. Every time button is pressed the text field is set to the word "Clicked".

   import java.awt.*;
   import java.awt.event.*;  // 1 - Add the import statement
   import javax.swing.*;
   
   public class SampleWin8
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("Alan Window");
         frame.setSize(400, 300);
         frame.setLocation(100, 75);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {
      JButton btnPress;
      JTextField text;
   
      public MyFrame(String s)
      {
         super(s);
         setLayout(new FlowLayout());
   
         btnPress = new JButton("Press");
         add(btnPress);
   
         text = new JTextField(20);
         add(text);
   
         btnPress.addActionListener(new ButtonHandler()); // 3 - connect
      }
   
      // 2 - Add the event handler class.
      // 
      // Note that this is defined INSIDE the ending curly brace for
      // the MyFrame class.
   
      class ButtonHandler implements ActionListener
      {
         public void actionPerformed(ActionEvent e)
         {
            text.setText("Clicked");
         }
      }
   
   }

Here is a description Click for video of a program very similar to the SampleWin8 program shown above.

There are many different kinds of events that occur while a Java program is running. A Java program with a GUI interface can handle mouse events (when the mouse moves, when the mouse buttons are clicked), window events (when a window is resized, when a window is moved), and so on. The SampleWin8 program, above is handing an action event. An action event occurs when:

Exercises

  1. Write an application SampleWin9 that presents two JButtons labeled "OK" and "Clear", and a JTextField component. Write event handlers for the two buttons so that when the OK button is clicked then the JTextField is set to "Alright" and when the Clear button is clicked the JTextField is set to "Cleared".
  2. Write an application SampleWin10 that presents two JButtons labeled "Left" and "Right", and two JTextField components. Write event handlers for the two buttons so that when the Left button is clicked then the text in the lefthand JTextField is set to whatever contents are currently in the righthand text field, and when the Right button is clicked the text moves from the text field displayed on the lef to the text field displayed on the right.

Changing a Component's Background Color

In addition to retrieving the current contents of a text field with the getText method

	String s = text.getText();  // s now references a copy of the textfield's text

and setting the text field text to something new

	text.setText("Something new");  // the user see's "Something new" appear in the text field

you can manipulate the text field in many other ways:  change the text field's background color, select part of the display text, disable user input into the box, etc. To see a full list of possible mainpulations, see Sun's official Java documentation (look up JTextField, and all of the methods that JTextField inherits from the JTextComponent, JComponent, Container, Component and Object classes).

The program below changes the text field's background color to red when the "OK" button is clicked.  Click here for a full description of the program:

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   
   public class DemoWindow3
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("Clicked! Window");
         frame.setSize(400, 300);
         frame.setLocation(300, 200);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {  
      JButton btnOK = new JButton("OK");
      JTextField text = new JTextField(20);
      
      public MyFrame(String s)
      {
         super(s);
         setLayout(new FlowLayout());
         
         add(btnOK);
         add(text);
         btnOK.addActionListener(new ButtonHandler());
      }
      
      class ButtonHandler implements ActionListener
      {
         public void actionPerformed(ActionEvent event)
         {
            text.setText("Clicked!");
            text.setBackground(Color.RED);
         }
      }
   }

Note that older versions of Java (1.4.x and earlier) required that constants for predefined color names be defined in lowercase letters (e.g., Color.red), but with Java 1.5 you should write the color name in uppercase letters (Color.RED).  Here is a description Click for video of the above program.

Two Event Handlers in the Same Program

GUI programs often are responding to events generated by two or more components.  The DemoWindow program, below, shows a program that responds to action events from two different buttons.  One button is labeld Red and the other Yellow.  The background color of a text field changes to red or yellow, depending on which button was clicked. 

In this program each button has its own event handler.  It also possible to write the program so that the buttons share one event handler (that technique will be covered later).

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   
   public class DemoWindow
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("Clicked! Window");
         frame.setSize(400, 300);
         frame.setLocation(300, 200);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {  
      JButton red = new JButton("Red");
      JButton yellow = new JButton("Yellow");
      JTextField txt = new JTextField("some text");
      
      public MyFrame(String s)
      {
         super(s);
         setLayout(new FlowLayout());
         
         add(red);
         add(txt);
         add(yellow);
         red.addActionListener(new RedHandler());
         yellow.addActionListener(new YellowHandler());
      }
      
      class RedHandler implements ActionListener
      {
         public void actionPerformed(ActionEvent event)
         {
            txt.setBackground(Color.RED);
         }
      }
      
      class YellowHandler implements ActionListener
      {
         public void actionPerformed(ActionEvent event)
         {
            txt.setBackground(Color.YELLOW);
         }
      }

   }

Here is a description Click for video of the above program.

JSlider

Another interesting component is JSlider. The JSlider component presents a slider to the user, and and user can slide a knob to any position along the slider's axis. The default range of values on the slider are from zero to one hundred, although the program can set other ranges if desired.

JSlider

Movement of the slider's knob generates change events, versus the action events that we've processed for buttons. To handle change events we'll have to implement a ChangeListener, and connect the JSlider to the ChangeListener object via call to addChangeListener. Whereas an ActionListener object must contain an actionPerformed method, a ChangeListener object contains a stateChanged method.

Here is a short program handles the change events. The SliderHandler event handler reports the current position of the knob to the JTextField named status. Note that you need to import a new package here -- javax.swing.event.*:

   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   import javax.swing.event.*;  // <--- NEW IMPORT HERE!
   
   public class JSliderExample
   {
      public static void main(String [] args)
      {
         MyFrame frame = new MyFrame("One Handler");
         frame.pack();
         frame.setLocation(300, 200);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      }
   }
   
   class MyFrame extends JFrame
   {  
      JSlider slider = new JSlider();
      JTextField status = new JTextField("Current position: ?", 15);
      
      public MyFrame(String s)
      {
         super(s);
         setLayout(new FlowLayout());
         
         add(slider);
         add(status);
         slider.addChangeListener(new SliderHandler());
      }
      
      class SliderHandler implements ChangeListener
      {
         public void stateChanged(ChangeEvent event)
         {
            int pos = slider.getValue();
            status.setText("Current position: " + pos);
         }
      }
   }

When this program runs, the following window is presented to the user:

JSlider Example

Every time the knob moves, a change event is generated and the code in the stateChanged method is performed.

Top