Java Abstract Window Toolkit
Glenn D. Blank
(http://www.eecs.lehigh.edu/~glennb/oose/java/javaawt.htm)

These notes assume my Java lecture notes as background.  (Those notes also contain explain the JDK and JavaEdit.)

Most GUI class libraries in C++ are platform specific, not just because of different hardware capabilities,
    but subtle differences between the "look-and-feel" of various Windowing operating systems.
The Java Abstract Window Toolkit provides a  cross-platform library
        which seeks to observe look-and-feel conventions of various OS platforms.

                Toolkit --------------------------------------------------------- AWT
           --------|---------
           Button            List                                                                            JVM
      ------|-------------|-------------------------------------------------------------------
      Button Peer     List Peer                                            Native GUI (Windows, Mac, X)

The AWT uses a "common functionality/specific implementation" approach
    AWT GUI classes are platform-independent elements
    Each AWT platform-specific toolkit comes with peer class for each platform-independent class
        which implements the platform-specific behavior of the AWT class
    Thus, combining the platform-independent class with its platform-specific peer
        transforms generic, abstract windows behavior into specific, particular behavior.

That's the general idea...
    The JDK invokes peer classes, such as ButtonPeer, at runtime:

  class TestPeer
  { Frame myFrame = new Frame("my Frame");  //create window Frame
    Button myButton = new Button("my Button"); //create myButton
    myFrame.add("Center",myButton);  //put myButton in myFrame
    myFrame.setVisible(true); //button appears in window on screen
    //setVisible() creates peer objects for myFrame & myButton
    ComponentPeer buttonPeer = myButton.getPeer(); //now works
  }

    Peer classes are usually hidden from developers--why?
        In fact, in newer versions of JDK, getPeer() method is now "deprecated"
        I.e., peer classes are strongly discouraged for code maintenance purposes
 

JDK 1.0 went a long way to implementing these ideas, but (as Bruce Eckel puts it)
   "produced a GUI that looks equally mediocre on all systems." Just 4 fonts; can’t access GUI of native OS.
JDK 1.1 makes AWT more robust and extensible (i.e., more object-oriented), and supports Java Beans.
     New delegation-based event model more neatly separates user interface from problem domain classes:
     Instead of non-object-oriented cascaded if statements testing for object type that typified logic using old AWT,
     new AWT designates objects as "listeners" of events triggered by objects modeling the problem domain.
     Other enhancements: cut/paste to the clipboard, popup menus, printing, mouseless operation, etc.
JDK 1.2 adds Java Foundation Classes, the GUI portion of which is Swing.
     Much richer class library plus better integration with look and feel of GUI of OS.
     Eckel comments: "The ‘revision 3’ rule of software industry (a product isn’t good until revision 3) seems to hold true with programming languages as well."

There's lots of documentation about the JDK online!


AWT class hierarchy

AWT is a hierarchy of classes in the JDK.  Here's a snippet from the AWT hierarchy:

        Object
            ^  Graphics
                CheckboxGroup
                Color
                Component
                    ^  Button
                        Checkbox
                        Choice
                        Container
                            ^   Window
                                       ^ Frame
                        Label
                        Panel
                        TextComponent
                            ^  TextArea
                            ^   TextField
                FlowLayout
                BorderLayout
                ...

Component contributes several useful public methods to all its subclasses:

     public void setSize(int width, int height); //set in pixels
     public void setBackground(Color c);         //see class Color for colors
     public void setVisible(boolean b);          //cause it display on screen

Container is an abstract class:
    I.e., it cannot be instantiated; some of its methods must be implemented by subclasses.
    Nevertheless, Container does implement some useful methods, including:

    public Component add(Component comp); //put a Component into a Container
    public setLayout(LayoutManager mgr);  //lay out components in some pattern

A Window object is a top-level window with no borders and no menubar.
    It can generate a WindowOpened or a WindowClosed event,
    to which a WindowListener or WindowAdapter can respond.  (We'll discuss events further below.)

A Frame is a top-level window with a title and a border.
    Because it has more features, it can generate more events: WindowOpened, WindowClosing, WindowClosed,
        WindowIconified, WindowDeiconified, WindowActivated, WindowDeactivated.
        Again, respond to these events with a WindowListener or WindowAdapter.

Once a subclass of Container, such as Window or Frame or Panel, has been constructed,
    it can then invoke an add method to attach any AWT component within it,
    such as a Button or a Label or a TextField or another Frame or Panel.


A simple example

Here's a simple program (Ex_1.java) which constructs a Frame and an unresponsive Button:

    //program to demonstrate the construction of a Container and a Button
    import java.awt.*;

    class Gui extends Frame
    {
        // constructor
        public Gui(String s)
        {   super(s);    //construct Frame part of Gui
            setBackground(Color.yellow);
            setLayout(new FlowLayout());
            Button pushButton = new Button("press me");
            add(pushButton);
        }
    } //class Gui

    class Ex_1
    {
        public static void main(String[] args)
        {   Gui screen = new Gui("Example 1");
            screen.setSize(500,100);
            screen.setVisible(true);
        }
    } //class Ex_1

         What do you think this program does?  What doesn't it do?


Responding to events

The next example (Ex_3.java) adds the ability to responds to events, such as a mouse button click
        Uses the event delegation model of JDK 1.1
        When an event occurs, when a Button is pressed, an ActionEvent objects is generated
        The ActionListener interface listens for a particular ActionEvent and responds in its actionPerformed method
        The WindowListener interface listens for events associated with Window objects,
            such as closing a window, and responds in corresponding methods

    //Program to demonstrate action listeners and event handlers
    import java.awt.*;
    import java.awt.event.*;

    class Gui extends Frame implements ActionListener, WindowListener
    {
        //constructor
        public Gui(String s)
        { super(s);
          setBackground(Color.yellow);
          setLayout(new FlowLayout());
          addWindowListener(this);            //listen for events on this Window
          Button pushButton = new Button("press me");
          add(pushButton);
          pushButton.addActionListener(this); //listen for Button press
        }

        //define action for Button press
        public void actionPerformed(ActionEvent event)
        { final char bell = '\u0007';
         if (event.getActionCommand().equals("press me"))
         { System.out.print(bell);}
        }

        //define methods in WindowListener interface
        public void windowClosing(WindowEvent event) { System.exit(0); }
        public void windowClosed(WindowEvent event)  {} //do nothing for now
        public void windowDeiconified(WindowEvent event){}
        public void windowIconified(WindowEvent event){}
        public void windowActivated(WindowEvent event){}
        public void windowDeactivated(WindowEvent event){}
        public void windowOpened(WindowEvent event){}
    }

    class Ex_3
    {
        public static void main(String[] args)
        { Gui screen = new Gui("Example 3");
          screen.setSize(500,100);
          screen.setVisible(true);
        }
    }

        The program now has a live button, whose actionPerformed method rings a bell,
             as well as a live close window button, which performs System.exit(0)
        There are listeners associated with most Components in the AWT.
        Note: if you implement WindowListener interface, you have to define all of the methods in it.
            Alternatively, the abstract class WindowAdapter defines null methods for them all,
            so you can only have to define methods for events you care about, such as windowClosing.


Sketchpad example

Let's jump into the code for the Sketchpad example (Sketchpad.java):


Layout Managers

Sketchpad uses hard-coded layout, which depends on a 800x600 screen
        JDK also provides a set of generic layout manager classes
            which arrange Component objects within a Container object in various predictable ways

        setLayout(new FlowLayout(FlowLayout.LEFT,10,10);
        //align LEFT-justify, with 10 vertical & 10 horizontal pixels between components
        for (int counter=1; counter <= 6; counter++)
                        add(new Button(String.valueOf(counter)));
                    1    2    3
                    4    5    6

        setLayout(new GridLayout(3,2,5,5); //3 rows, 2 columns, 5 pixel gaps
        //align LEFT-justify, with 10 vertical & 10 horizontal pixels between components
       for (int counter=1; counter <= 6; counter++)
                        add(new Button(String.valueOf(counter)));
                    1        2
                    3        4
                    5        6


Applets

So far, these notes have looked at stand-alone applications using Java AWT
    On the web, Java programs are called Applets
    class java.applet is a subclass of Panel, designed to run within a Web browser

    For security reasons, Applets are forbidden many of the capabilities of applications,
            such as any file access, whether read, write or executing programs on a disk,
            or network socket connections anywhere but the server of the applet
    Nevertheless, applets have a fair amount of capability, since they are written in a general purpose programming language

    Of course, Web browsers read HTML, so to run an applet, you create HTML code which specifies an applet:

           <HTML
        <BODY
        <APPLET code="HelloWorld.class" width=600 height=300)
        </APPLET
        </BODY
       </HTML

HelloWorld.class is the Java byte code compiled from the source program HelloWorld.java
        the paint() method displays information in an applet's window (note that this is no main() method)
        its parameter, Graphics g, makes graphics capability available to an applet.

Since class java.applet inherits from Panel and Container, it has all the capabilities of the AWT.
        RadioButtons.java illustrates radio buttons and font control in an applet (run in browser).

Class java.applet also has a number of methods available for manipulating it size, web links and media content.

netlinks.java illustrates links to other web sites (run in browser)
          uses java.net package to connect to and communicate with other sites on the Internet
                1) This program sets up arrays of web site names and corresponding URLs
                2) Next, it creates an array of Buttons, each with the name of a web site
                3) Method actionPerformed responds to a Button by getting the corresponding URL
                getAppletConext().showDocument(site);   //retrieves page at a URL site

LoadImageAndScale.java illustrates displaying GIF images in an applet (run this program in browser)
           uses Applet.getImage() method to retreive an image from a web site
           also illustrates re-scaling the image
           Could also load JPG images

LoadAudioAndPlay.java illustrates playing sounds in an applet (run this program in browser)
           uses class AudioClip, which is part of the Applet package, to declare a variable sound:
                     AudioClip sound;
           uses Applet method getAudioClip to load a sound from a web page:
                     sound = getAudioClip(getCodeBase(),"audio\\"+source.toString()+".au");
           uses getCodebase() to return the URL from which the applet's code was loaded
           and finally plays the AudioClip:
                    sound.play();
           Until recently, the JDK only supported the .au format,
                but support for wav and aiff and midi is coming with JavaSound in the Java Media Framework.

DeitelLoop.java illustrates animation of GIF files in an applet (run this program in browser)
            This version simply loads a set of graphics into an array, then displays them in order.
DeitelLoop5.java illustrates techniques to improve the performance of animation in an applet
            (run this program in browser)
            This version lets you test the effect of changing the sleep time between displaying each image
                    (by changing a HTML parameter -- try running with different parameters)
            class MediaTracker determines when an image is completely loaded,
                  until tracker.imageImage() has loaded image before playing it in animation.
            This version also uses double-buffering, i.e., drawing to memory off screen to avoid flicker:
                  see buffer and gContext.
            And this version also uses threads (by implementing the Runnable interface), to permit a user
                  to stop the animation by leaving the page.

For more working example Java code, you can download the code from the Deitel & Deitel site
           (the same code that is in Java: How to Program)
or the code from the Bruce Eckel site (the code that is in Thinking in Java)


Good and bad programming practices with AWT

Separate user interface logic from "business logic," i.e., the problem that you are trying to model.
     AWT 1.1 "listeners" were designed for this purpose; inner classes facilitate it further
     Separation.java example illustrates this approach:
    class BusinessLogic knows nothing about UI;
     class Separation keeps track of all UI details and talks to BusinessLogic through its public interface.

    How does this design loosely coupled?
    How does it support reuse?
    How does it support legacy code?

Also note use of inner classes for all "listeners" nested within Separation
     Contrast code of badidea1.java: look at code in actionPerformed:

    public void actionPerformed(ActionEvent e)
    { Object source = e.getSource();
      if(source == b1)
         System.out.println("Button 1 pressed");
      else if(source == b2) System.out.println("Button 2 pressed");
      else System.out.println("Something else");
    }

    badidea2.java improves on things by using adapters, but still has non-object-oriented code.
    Inner classes help to avoid this code.

  Why is the cascaded if above a bad idea?
    (Apparently many textbooks encourage this ugly practice, probably betraying influence of AWT 1.0?)

Suggestion: to eliminate flicker, you may want to override update():
    public void update(Graphics g) { paint(g); }
Overrides default version of update() which clears the background,
    then calls paint() to redraw any graphics


Introduction to Swing

Swing appeared after JDK 1.1, but it’s designed to work with JDK 1.1 as an add-on; it comes with JDK 1.2.
Sun has an on-line tutorial. Swing includes lots of features that users have to expect from a GUI:

In C:\java\jdk1.2\demo\jfc\SwingSet, run java SwingSet

Much JDK 1.1 code is easily ported to Swing: simply add a prefix "J" to the classes: e.g., JButton for Button.
However, Swing adds a number of new types of buttons and changes the way they are organized:
All buttons, checkboxes, radio buttons and even menu items are inherited from AbstractButton.

See SwingSet demo’s ButtonPanel.java.

See Bruce Eckel’s Buttons.java example:

See Faces example: illustrate including ImageIcons in Jbuttons