Title: Basics
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

AWT Basics and Swing

AWT stands for Abstract Windowing Toolkit. Most of the notes for a while will contain an import of the package:
import java.awt.*;

The AWT library has been around for a long time and the Java Virtual Machine (JVM) in virtually every browser should understand any Applet written with the AWT library. The AWT library was written to make use of native GUI elements present on each platform where it ran. Consequently, each platform will tend to look a little different due to the fact that the underlying platform is different. Later the Java Sun team decided to create a new GUI library called SWING which was a rewrite this software to be more "bottom up". In otherwords, much less native GUI software was used and most of the software comes from the Java library. You still need to use many components in the AWT library, but SWING provides a more uniform look and feel no matter what platform you are executing on. Here is a list of comparisons between AWT and SWING:

1. Many old Microsoft I.E. browsers only execute an old JVM (around jdk 1.1.4). These browsers will only work with the AWT and work that needs to run in these browsers is best compiled with an old version of the JDK. In my setup notes, I can provide a JDK for 1.1.8. Newer browsers will work with SWING.
2. If you write your Applets for SWING you will use a set of classes that start with "J" and come from:
import javax.swing.*;
The old classes in the AWT are still available, but are somewhat obsoleted by the "J" classes. Here is a table of examples:

SWING class | AWT class
JApplet | Applet
JFrame | Frame
JButton | Button
JComponent | Component
JTextArea | TextArea
JTextField | TextField
JLabel | Label

3. There are a number of subtle changes which can be annoying in converting AWT work to SWING. Here is a list of some things which I have encoutered:
  - You can't just call the add routine in JFrame and JApplet. You need to first obtain the Container by calling getContentPane().
  - The default layout manager in a JApplet is BorderLayout instead of FlowLayout.
  - The default text size seems to be larger in Swing than in AWT
  - JTextArea doesn't automatically scroll when all of the rows have been used. There is a way to do it with a JScrollPane class, but it is certainly not compatibale with AWT.
4. Swing kept a lot of the original AWT concepts in the areas of dealing with actual drawing, Events (keystrokes, mouse activity), and layout managers. The major area that is impacted is the Component area where SWING provides a different set of classes for buttons, textareas, etc. The following figure gives you a class heirarchy of how AWT and SWING are related:

Concepts

I have updated the examples in this section to work with SWING. The original notes that were written for AWT can be found as a WebView link for AWT.

We will want to get some feedback from the GUI (Graphical User Interface). User feedback (i.e. keystrokes, mouse clicks, etc.) comes in the form of Events. Whenever we need events, we will also import from:
import java.awt.event.*;

The AWT supports a number of different Windowing types from Applets, Frames, Windows, Dialogs, etc. We will focus on the concepts that are the same no matter what windowing type you use. We will mostly focus on Frames and Applets. Later sections of the notes will deal with the other windowing types.

Applets are a special window that can live inside of a Browser web page. A Frame on the otherhand normally gets started from an application (i.e. java xyz). Our Frame based applications will always need a main routine where the actual Frame is created. The normal steps for starting up a Frame based application include:

1. Construct the Frame based class.
2. If you don't want the default layout manager (BorderLayout), you pick your desired Layout Manager. We will spend a lot of time on layout managers later.
3. Call the setSize method to set the width and height of the Frame in pixels
4. Add anything you want to the Frame.
5. Make the Frame visible. The default for Frames is invisible. So you typically create your Frame page and then make it visible.
6. Note that the X-box in the upper right corner doesn't work. We will deal with this later because its easy to fix, but adds some ugly stuff that I would like to avoid for now.

GUI Runnable from the Command line

BasicFrame.java


import java.awt.*;
import javax.swing.*;

public class BasicFrame extends JFrame{
    BasicFrame(String name)
    {
       super(name); // invoke Frame constructor that has a name
       Container container = getContentPane();

       container.setLayout(new FlowLayout());
       this.setSize(600,150);
       container.add(new JButton("HI There"));

     }

  public static void main(String[] args) {
    BasicFrame aFrame = new BasicFrame("BasicFrame");
    aFrame.setVisible(true);
  } // end of main
}


GUI Runnable Within a Browser

If you are running in an Applet that lives in a web page, then some of the above steps mentioned for Frame based applications are already done by the Browser. Here is the sequence of events that occur in the Applet case:

1. The browser recognizes some Html applet tags and determines from the Html how many pixels wide and high the applet will take from the phrase width=600 height=150--- see the BasicApplet.html file below.
2. The browser then loads in the java class file based on the code = BasicApplet.class phrase In the BasicApplet.html file below, the browser will download BasicApplet.class from the same directory where BasicApplet.html was found.
3. The browser has a built in Java Runtime Environment (JRE), and will attempt to construct a class named BasicApplet. If the class isn't derived from Applet, it won't work.
4. Once the Applet is constructed, the browser calls the Applet init routine to allow the Applet to initialize itself. Often you want to overrid the Applet init routine to do what you want to do here.
5. When the Browser wants to Applet to start executing, it calls the start routine. You may or may not want to override this routine.
6. Whenever it is necessary to paint the screen, the paint routine is called. If you are using higher level components (like the Button class), the paint occurs inside of the higher level component. We will start out with higher level components like buttons and textFields, so we won't see the paint routine much until we do some lower level Drawing.
7. When the user moves onto a different web page, the browser will call the stop routine. You can override the stop routine if you have any special stop code you want to include in your Applet.
8. Unless you override either paint, init or start, you won't have anything worthwhile in your applet.
9. If you want to publish the following Applet, compile it and place BasicApplet.html and BasicApplet.code in some web directory that you own. If you have never published a web page before, the easy approach is to take the following steps:
  - Create a directory called public_html in the your home directory of your Linux account.
  - Place BasicApplet.html and BasicApplet.java in your public_html directory. Compile BasicApplet.java in your public_html directory.
  - Access your web page with the following URL:
http://gettysburg.wccnet.org/~c269xx/BasicApplet.html
10. The second approach you can take on applets is to use the Fake Browser program: appletviewer. Wherever you have BasicApplet.code and BasicApplet.html, issue the command:
appletviewer BasicApplet.html
The appletviewer is an easier environment for debugging Applets.
11. One common problem with publishing web pages and especially Applets is the existence of a very Sticky Cache for applets. This means that you thought you changed the applet, but you still see the old code. You will need to flush the Browser cache --- reload sometimes doesn't work very well for applets. Sometimes you may even need to kill all of your browser windows and reload the applet in a new browser instance. You won't have these problems with the appletviewer.

BasicApplet.java


import java.awt.*;
import javax.swing.*;

public class BasicApplet extends JApplet {

    public void init() {
        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(new JButton("HI There"));
    }
}


BasicApplet.html


<html>
<body>
<h2>BasicApplet</h2>
<applet code=BasicApplet.class width=600 height=150>
</applet>
</body></html>


BasicApplet

BasicBoth.java

I can actually create a java class that can act both as an Applet and can be run from the command line. Try the following code at the command line (i.e. java BasicBoth). Also try out this code as an Applet. The steps are as follows:

1. Create a class derived from Applet and override the routines desired (i.e. paint, init, start, or stop)
2. Add a main routine that effectively executes the normal steps taken by a browser which are:
3. Create a Window Frame
4. Give the Window Frame a Size in pixels (width, height)
5. Construct the Applet derived class and add it to the window frame.
6. If your code uses an init routine call the init routine
7. If your code uses a start routine call the start routine
8. If your code uses a stop routine, I would recommend that you override the finalize method and call stop from there.


import java.awt.*;
import javax.swing.*;

public class BasicBoth extends JApplet {

    public void init() {
        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(new JButton("HI There"));
    }

  public static void main(String[] args) {
    BasicBoth applet = new BasicBoth();
    JFrame aFrame = new JFrame("Basic");

    aFrame.getContentPane().add(applet);
    aFrame.setSize(600,150);
    // Normally the following call comes from the Browser
    applet.init();

    aFrame.setVisible(true);
  } // end of main
}



BasicBoth

If you take the "Both" approach and you decide that you just want a pure applet and you want to remove the capability to run your code from the command line, just eliminate the main routine.

If you take the "Both" approach and you decide that you just want a pure Frame based application that runs from the command line, you would take the following steps:

1. Have your class derived from Frame instead of Applet.
2. Create a constructor for you class if you don't already have one.
3. If you don't want a BorderLayout(default for Frame) manager (we will discuss layout managers later), you need to override this in your constructor.
4. In your constructor you can all your init code or start code as necessary. Alternatively, you can move this code into your constructor.
5. From your main routine construct your class and remove the code that constructs the applet and adds it to the Frame.
6. The result of these steps would lead you to something like the following:


import java.awt.*;
import javax.swing.*;

public class BasicBoth extends JFrame {

    public void init() {
        getContentPane().add(new JButton("HI There"));
    }
    BasicBoth (String name)
    {
        super(name);
        getContentPane().setLayout(new FlowLayout());
        init();
    }

  public static void main(String[] args) {
    Frame aFrame = new BasicBoth("Basic");
    aFrame.setSize(600,150);
    aFrame.setVisible(true);
  } // end of main
}


Most of my notes are going to work with the "Both" approach in order to allow me to publish my notes on the web in a convenient manner. You can immediately see what the GUI looks like and you can play with it. You can also copy the code to a Java environment and compile and execute it.

BasicComponents.java

1. The AWT contains an abstract class called Component. A lot of useful classes are derived from Component ( Button, TextField, TextArea, Choice, CheckBox, Label, Canvas, List, etc). There is a lot of useful common software buried in the Component class. We will start out using some of these higher level classes. Check out the following image:
awt.component tree
2. You can also use the Component class as a basis for creating a GUI from more fundamental blocks. You can draw your own control and field your own keystrokes, mouse button clicks etc. We will do a little of this as well.
3. I would strongly recommend that you get familiar with navigating the java.awt package, because we will only be scratching the surface of the capabilities.
4. Another key class to understand is the notion of a Container. A Frame and and Applet are both instances of a Container. A Container has all of the properties of Component in addition to the capability of being able to hold other Components inside of it. For example on your Frame or your Applet, you may want to add several buttons, textFields, etc. You can do this because the Applet class has Container capabilities.
5. TextField, and TextArea - To have an online text field, use the TextField class. If you want a multi-line input area, use the TextArea class. Both of these classes are derived from TextComponent. Keep this in mind, because if you don't find what you want in online help under TextField, or TextArea, you might want to consider looking under the TextComponent class which has a lot of the basic functionality for both of these classes.
6. You may be wondering how you specify where on the screen these components show up. Java invented the concept of a Layout manager for determining where components show up on the screen. There are many different Layout manager options available and this is a major topic for later. For the time being don't worry where the Components show up. In fact, I have played some games with sizes of the container and sizes of the Components themselves to make it look not so bad.
7. In this example, we are also adding a Label class. A Label has no capability to receive user input. A Label merely holds onto static text.
8. Note that one of the problems with Applets is the fact that your Applet may be running in different versions of the JRE depending on what browser you are running. Normally the JREs tend to be quite old relative to the current version of Java available elsewhere. This is important when considering what you put into an Applet. My recommendation is that you stick with Java version 1.1.8 to avoid most problems. Running this Applet will show you what Java version your browser is actually running.


import java.awt.*;
import javax.swing.*;

public class BasicComponents extends JFrame {

	BasicComponents(String name){
		super(name);
		this.setSize(600,400);
        // Construct a Label and add it with one command
        Container container = getContentPane();
        container.setLayout(new FlowLayout());
        container.add(new JLabel("This is a long label ........."));

        // Single Line Input/Output Field
        JTextField t = new JTextField(40);
        container.add(t);

        // Button
        JButton b = new JButton("Click here to get something done");
        container.add(b);

        // Multple Line Input/Output Field
        JTextArea toutput = new JTextArea(4,40);
        container.add(toutput);

        // Print out the Java Version you are using

         String javaVersion = System.getProperty("java.version");
        toutput.append(javaVersion);

		setVisible(true);
     }

  public static void main(String[] args) {
    BasicComponents basic = new BasicComponents("basic components");
  } // end of main
}



BasicAction.java

We have to jump ahead a little so we can get input back. We will talk about the Listener interfaces a lot more later, but for now we want to have some code that gets called everytime a button gets clicked. The way you do it is as follows:

1. You need a class that implements the ActionListener interface. We are going to take the easy approach here and claim that our BasicAction class implements ActionListener.
2. The ActionListener interface only has one routine in it, so we just add it to our BasicAction class:
public void actionPerformed(ActionEvent e)
3. Lastly, after we create our Button, we pass a pointer to a class that implements the ActionListener interface. In our program it happens to be the BasicAction class itself, so we just pass the keyword this. We do this by taking the Button instance b and issuing the command:
b.addActionListener(this);
4. In our actionPerformed routine we are going to fetch the text typed into the TextField class (tinput) and append it to the end of our TextArea class (toutput). To do this we used the setText and getText methods.
5. So you type input into either a TextField or TextArea. If you want to set either of these classes to have a certain string, use
setText(String text);
6. If you want to append text to the end of the buffer use:
append(String text);
7. getSelectedText() - this routine will return the selected text in a text component.
8. If you want to fetch the text currently in one of these classes use the routine:
String getText();
9. When using TextArea, you need to explicitly enter in your newline (OS specific) string. So instead of using '\n' on Linux or '\r' '\n' on Windows, you can use System.getProperties to fetch the end of line separator.
10. Note that we have one System.out.println statement. This can be useful for debugging. If you are running from the command line or in the appletviewer, it is clear where this output is displayed. However, when this code is displayed in a real browser, you have to find the Java Console to see the output from your System.out.println. By the way sending a lot of output to the Java Console can slow things down considerably on the web --- the implementation is not efficient and should only be used for debug.
11. On I.E. the java console is available under the View menu only if it is configured. To configure the java console on I.E., go to tools/Internet Options and pick the Advanced tab.
12. On Netscape, the java console doesn't need configuration. On Netscape 6 it can be found under tasks/tools.



import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // New Import for Events

public class BasicAction extends JFrame
    implements ActionListener
{
   JTextField tinput = new JTextField("TextField class", 60);
   JTextArea toutput = new JTextArea("TextArea class", 4, 60);
   String endline;

   public BasicAction(String name) {
	    super(name);
		this.setSize(800,400);
		
        // Construct a Label and add it with one command
        Container container = getContentPane();

        container.setLayout(new FlowLayout());
        container.add(new JLabel("This is a long label ........."));

        container.add(tinput);

        JButton b = new JButton("Click here to get something done");
        container.add(b);
        container.add(toutput);

        b.addActionListener(this);
        endline= System.getProperty("line.separator");

		setVisible(true);
     }

    public void actionPerformed(ActionEvent e) {
        String str = tinput.getText();

        toutput.append(str + endline);

        // Where does the following go???
        System.out.println(str);
       }


  public static void main(String[] args) {
    BasicAction basicAction = new BasicAction("Basic Action");
  } // end of main
}









Exercises

1. Add another JButton to the BasicAction.java class. Add ActionListener events for both JButtons and the JTextField. Note that hitting the Enter key invokes the ActionListener event for a JTextField. Now the question is how can I tell which object caused the ActionEvent to occur? If you go to online help and look under ActionEvent, see if you can find a method called getSource and figure out how to use it.
2. See if you can add and ActionListener to the JTextArea class.

Last Updated: October 6, 2009 9:51 PM