![]() ![]() ![]() |
|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Course OutlineGraphical User InterfacesThe JavaTM programming language provides a class library called the Abstract Window Toolkit (AWT) that contains a number of common graphical widgets. You can add these widgets to your display area and position them with a layout manager. AWT BasicsAll graphical user interface objects stem from a common superclass, Each AWT component uses native code to display itself on your screen. When you run a Java application under Microsoft Windows, buttons are really Microsoft Windows buttons. When you run the same application on a Macintosh, buttons are really Macintosh buttons. When you run on a UNIX machine that uses Motif, buttons are really Motif buttons. Applications versus AppletsRecall that an Applications run from a command prompt. When you execute an application from
the command prompt, the interpreter starts by calling the application's Basic GUI LogicThere are three steps you take to create any GUI application or applet:
When you display an AWT GUI, the interpreter starts a new thread to watch for user interaction with the GUI. This new thread sits and waits until a user presses a key, clicks or moves the mouse, or any other system-level event that affects the GUI. When it receives such an event, it calls one of the event handlers you set up for the GUI. Note that the event handler code is executed within the thread that watches the GUI! (This is an import point that will be revisited later when events are reviewed.) Because this extra thread exists, your main method can simply end after it displays the GUI. This makes GUI code very simple to write in AWT. Compose the GUI, setup event handlers, then display. A Simple ExampleThe following simple example shows some GUI code.
This example creates an
import java.awt.Button; import java.applet.Applet; public class AButton extends Applet { public void init() { // STEP 1: Compose the GUI Button beepButton = new Button("Beep"); add(beepButton); // STEP 2: Setup Event handlers beepButton.addActionListener(new Beeper()); // STEP 3: Display the GUI (automatic -- this is an applet) } } In step 2 from above, event handling is set up by adding an instance of
a listener class to the button. When the button is pressed, a certain
method in the listener class is called. In this example, the listener class
implements Suppose you want to produce a "beep" sound when the button is pressed. You can define your event handler as follows: import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.Component; public class Beeper implements ActionListener { public void actionPerformed(ActionEvent event) { Component c = (Component)event.getSource(); c.getToolkit().beep(); } } When To try this applet, create a simple HTML page as follows. <html> <applet code=AButton.class width=100 height=100> </applet> </html> Then test the HTML page by running appletviewer or by loading the HTML file in a browser that supports the Java Runtime Environment (JRE). Note that in this case, the browser must support at least version 1.1 of the JRE, as the example uses the event handling capabilities introduced with that release. AWT ComponentsAll AWT components extend class Next, examine each of the AWT components below. Most, but not all, directly
extend ButtonsA
import java.awt.*; import java.applet.Applet; public class ButtonTest extends Applet { public void init() { Button button = new Button("OK"); add(button); } } Note that in the above example there is no event handling added; pressing the button will not do anything. The AWT button has no direct support for images as labels. CanvasA
You can subclass import java.awt.Canvas; import java.awt.Graphics; class DrawingRegion extends Canvas { public DrawingRegion() { setSize(100, 50); } public void paint(Graphics g) { g.drawRect(0, 0, 99, 49); // draw border g.drawString("A Canvas", 20,20); } } Then you use it like any other component, adding it to a parent container, for example in an
import java.applet.Applet; public class CanvasPaintTest extends Applet { public void init() { DrawingRegion region = new DrawingRegion(); add(region); } The CheckboxA
import java.awt.*; import java.applet.Applet; public class CheckboxSimpleTest extends Applet { public void init() { Checkbox m = new Checkbox("Allow Mixed Case"); add(m); } } To set a
import java.awt.*; import java.applet.Applet; public class CheckboxSimpleTest2 extends Applet { public void init() { Checkbox m = new Checkbox("Label", true); add(m); } } CheckboxGroupA The following example illustrates the basic idea behind radio buttons.
import java.awt.*; import java.applet.Applet; public class CheckboxGroupTest extends Applet { public void init() { // create button controller CheckboxGroup cbg = new CheckboxGroup(); Checkbox cb1 = new Checkbox("Show lowercase only", cbg, true); Checkbox cb2 = new Checkbox("Show uppercase only", cbg, false); add(cb1); add(cb2); } } Choice
import java.awt.*; import java.applet.Applet; public class ChoiceSimpleTest extends Applet { public void init() { Choice rgb = new Choice(); rgb.add("Red"); rgb.add("Green"); rgb.add("Blue"); add(rgb); } } The first item added is the initial selection. LabelA
import java.awt.*; import java.applet.Applet; public class LabelTest extends Applet { public void init() { add(new Label("A label")); // right justify next label add(new Label("Another label", Label.RIGHT)); } } Like the ListA Multiple selections may be used by passing
import java.awt.*; import java.applet.Applet; public class ListSimpleTest extends Applet { public void init() { List list = new List(5, false); list.add("Seattle"); list.add("Washington"); list.add("New York"); list.add("Chicago"); list.add("Miami"); list.add("San Jose"); list.add("Denver"); add(list); } } The constructor may contain a preferred number of lines to display. The
current ScrollbarA
import java.awt.*; import java.applet.Applet; // A simple example that makes a Scrollbar appear public class ScrollbarSimpleTest extends Applet { public void init() { Scrollbar sb = new Scrollbar(Scrollbar.HORIZONTAL, 0, // initial value is 0 5, // width of slider -100, 105); // range -100 to 100 add(sb); } } The maximum value of the TextFieldA
import java.awt.*; import java.applet.Applet; public class TextFieldSimpleTest extends Applet { public void init() { TextField f1 = new TextField("type something"); add(f1); } } Tips:
TextAreaA
import java.awt.*; import java.applet.Applet; public class TextAreaSimpleTest extends Applet { TextArea disp; public void init() { disp = new TextArea("Code goes here", 10, 30); add(disp); } } There is no way, for example, to put the cursor at beginning of row five, only to put the cursor at single dimension position 50. There is a four-argument constructor
that accepts a fourth parameter of a scrollbar policy. The different settings are
the class constants:
import java.awt.*; import java.applet.Applet; public class TextAreaScroll extends Applet { String s = "This is a very long message " + "It should wrap when there is " + "no horizontal scrollbar."; public void init() { add(new TextArea (s, 4, 15, TextArea.SCROLLBARS_NONE)); add(new TextArea (s, 4, 15, TextArea.SCROLLBARS_BOTH)); add(new TextArea (s, 4, 15, TextArea.SCROLLBARS_HORIZONTAL_ONLY)); add(new TextArea (s, 4, 15, TextArea.SCROLLBARS_VERTICAL_ONLY)); } } Common Component MethodsAll AWT components share the 100-plus methods inherited from the
ContainersA Common Container MethodsBesides the 100-plus methods inherited from the ScrollPaneThe The following example demonstrates the scrolling of a large image. Since an
import java.awt.*; import java.applet.*; class ImageCanvas extends Component { private Image image; public ImageCanvas(Image i) { image = i; } public void paint(Graphics g) { if (image != null) g.drawImage(image, 0, 0, this); } } public class ScrollingImage extends Applet { public void init() { setLayout(new BorderLayout()); ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); Image im = getImage(getCodeBase(), "./images/SMarea.gif"); sp.add(new ImageCanvas(im)); add(sp, BorderLayout.CENTER); } } Event HandlingEventsBeginning with the 1.1 version of the JRE, objects register as listeners for events. If
there are no listeners when an event happens, nothing happens. If there are twenty listeners
registered, each is given an opportunity to process the event, in an undefined
order. With a import java.awt.*; import java.awt.event.*; import java.applet.Applet; public class SimpleButtonEvent extends Applet implements ActionListener { private Button b; public void init() { b = new Button("Press me"); b.addActionListener(this); add(b); } public void actionPerformed(ActionEvent e) { // If the target of the event was our Button // In this example, the check is not // truly necessary as we only listen to // a single button if ( e.getSource() == b ) { getGraphics().drawString("OUCH",20,20); } } } Notice that any class can implement So, here is how everything works:
AWTEventEvents subclass the Low-level EventsLow-level events represent a low-level input or window operation, like a key press, mouse movement, or window opening. The following table displays the different low-level events, and the operations that generate each event (each operation corresponds to a method of the listener interface):
For instance, typing the letter 'A' on the keyboard generates three events, one for pressing, one for releasing, and one for typing. Depending upon your interests, you can do something for any of the three events. Semantic EventsSemantic events represent interaction with a GUI component; for instance selecting a button, or changing the text of a text field. Which components generate which events is shown in the next section.
Event SourcesThe following table represents the different event sources. Keep in mind the
object hierarchy. For instance, when
Notice that although there is only one Event ListenersEach listener interface is paired with one event type and contains a method
for each type of event the event class embodies. For instance, the Summary of Listener interfaces and their methods
Event AdaptersSince the low-level event listeners have multiple methods to implement, there are event adapter classes to ease the pain. Instead of implementing the interface and stubbing out the methods you do not care about, you can subclass the appropriate adapter class and just override the one or two methods you are interested in. Since the semantic listeners only contain one method to implement, there is no need for adapter classes. public class MyKeyAdapter extends KeyAdapter { public void keyTyped(KeyEvent e) { System.out.println("User typed: " + KeyEvent.getKeyText(e.getKeyCode())); } } Button Pressing ExampleThe following code demonstrates the basic concept a little more beyond the
earlier example. There are three buttons within a
import java.awt.*; import java.awt.event.*; public class Activator { public static void main(String[] args) { Button b; ActionListener al = new MyActionListener(); Frame f = new Frame("Hello Java"); f.add(b = new Button("Hola"), BorderLayout.NORTH); b.setActionCommand("Hello"); b.addActionListener(al); f.add(b = new Button("Aloha"), BorderLayout.CENTER); b.addActionListener(al); f.add(b = new Button("Adios"), BorderLayout.SOUTH); b.setActionCommand("Quit"); b.addActionListener(al); f.pack(); f.show(); } } class MyActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { // Action Command is not necessarily label String s = e.getActionCommand(); if (s.equals("Quit")) { System.exit(0); } else if (s.equals("Hello")) { System.out.println("Bon Jour"); } else { System.out.println(s + " selected"); } } } Since this is an application, you need to save the source (as Adapters ExampleThe following code demonstrates using an adapter as an anonymous inner class to draw a rectangle within an applet. The mouse press signifies the top left corner to draw, with the mouse release the bottom right. import java.awt.*; import java.awt.event.*; public class Draw extends java.applet.Applet { public void init() { addMouseListener( new MouseAdapter() { int savedX, savedY; public void mousePressed(MouseEvent e) { savedX = e.getX(); savedY = e.getY(); } public void mouseReleased(MouseEvent e) { Graphics g = Draw.this.getGraphics(); g.drawRect(savedX, savedY, e.getX()-savedX, e.getY()-savedY); } } ); } } Applications and MenusGUI-based ApplicationsTo create a window for your application, define a subclass of Applications respond to events in the same way as applets do. The following
example,
import java.awt.*; import java.awt.event.*; public class BasicApplication extends Frame { public BasicApplication() { super("BasicApplication Title"); setSize(200, 200); // add a demo component to this frame add(new Label("Application Template...", Label.CENTER), BorderLayout.CENTER); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { setVisible(false); dispose(); System.exit(0); } }); } public static void main(String[] args) { BasicApplication app = new BasicApplication(); app.setVisible(true); } } Consider an application that displays the x,y location of the last mouse click and provides a button to reset the displayed x,y coordinates to 0,0:
import java.awt.*; import java.awt.event.*; public class CursorFrame extends Frame { TextField a, b; Button btn; public CursorFrame() { super("CursorFrame"); setSize(400, 200); setLayout(new FlowLayout()); add(new Label("Click the mouse...")); a = new TextField("0", 4); b = new TextField("0", 4); btn = new Button("RESET"); add(a); add(b); add(btn); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { a.setText(String.valueOf(e.getX())); b.setText(String.valueOf(e.getY())); } }); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { setVisible(false); dispose(); System.exit(0); } }); btn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { a.setText("0"); b.setText("0"); } }); } public static void main(String[] args) { CursorFrame app = new CursorFrame(); app.setVisible(true); } } This application provides anonymous classes to handle mouse events, application window closing events, and the action event for resetting the text fields that report mouse coordinates. When you have a very common operation, such as handling application window
closing events, it often makes sense to abstract out this behavior and handle it
elsewhere. In this case, it's logical to do this by extending the existing import java.awt.*; import java.awt.event.*; public class AppFrame extends Frame implements WindowListener { public AppFrame(String title) { super(title); addWindowListener(this); } public void windowClosing(WindowEvent e) { setVisible(false); dispose(); System.exit(0); } public void windowClosed(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} }
ExercisesApplications: Dialog BoxesA
import java.awt.*; import java.awt.event.*; public class DialogFrame extends AppFrame { Dialog d; public DialogFrame() { super("DialogFrame"); setSize(200, 100); Button btn, dbtn; add(btn = new Button("Press for Dialog Box"), BorderLayout.SOUTH); d = new Dialog(this, "Dialog Box", false); d.setSize(150, 150); d.add(new Label("This is the dialog box."), BorderLayout.CENTER); d.add(dbtn = new Button("OK"), BorderLayout.SOUTH); btn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(true); } }); dbtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(false); } }); d.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { d.setVisible(false); } }); } public static void main(String[] args) { DialogFrame app = new DialogFrame(); app.setVisible(true); } } Again, you can define anonymous classes on the fly for:
Although the anonymous class functionality is quite elegant, it is
inconvenient to have to repeatedly include the window-closing functionality for
every dialog instance that your applications instantiate by coding and
registering the anonymous window adapter class. As with import java.awt.*; import java.awt.event.*; public class WMDialog extends Dialog implements WindowListener { public WMDialog(Frame ref, String title, boolean modal) { super(ref, title, modal); addWindowListener(this); } public void windowClosing(WindowEvent e) { setVisible(false); } public void windowClosed(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} } ExerciseApplications: File Dialog BoxesThe utility class ExerciseApplications: MenusAn application can have a To add menus to any
The following program,
import java.awt.*; import java.awt.event.*; // Make a main window with two top-level menus: File and Help. // Help has a submenu and demonstrates a few interesting menu items. public class MainWindow extends Frame { public MainWindow() { super("Menu System Test Window"); setSize(200, 200); // make a top level File menu FileMenu fileMenu = new FileMenu(this); // make a top level Help menu HelpMenu helpMenu = new HelpMenu(this); // make a menu bar for this frame // and add top level menus File and Menu MenuBar mb = new MenuBar(); mb.add(fileMenu); mb.add(helpMenu); setMenuBar(mb); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { exit(); } }); } public void exit() { setVisible(false); // hide the Frame dispose(); // tell windowing system to free resources System.exit(0); // exit } public static void main(String args[]) { MainWindow w = new MainWindow(); w.setVisible(true); } } // Encapsulate the look and behavior of the File menu class FileMenu extends Menu implements ActionListener { MainWindow mw; // who owns us? public FileMenu(MainWindow m) { super("File"); mw = m; MenuItem mi; add(mi = new MenuItem("Open")); mi.addActionListener(this); add(mi = new MenuItem("Close")); mi.addActionListener(this); add(mi = new MenuItem("Exit")); mi.addActionListener(this); } // respond to the Exit menu choice public void actionPerformed(ActionEvent e) { String item = e.getActionCommand(); if (item.equals("Exit")) mw.exit(); else System.out.println("Selected FileMenu " + item); } } // Encapsulate the look and behavior of the Help menu class HelpMenu extends Menu implements ActionListener { MainWindow mw; // who owns us? public HelpMenu(MainWindow m) { super("Help"); mw = m; MenuItem mi; add(mi = new MenuItem("Fundamentals")); mi.addActionListener(this); add(mi = new MenuItem("Advanced")); mi.addActionListener(this); addSeparator(); add(mi = new CheckboxMenuItem("Have Read The Manual")); mi.addActionListener(this); add(mi = new CheckboxMenuItem("Have Not Read The Manual")); mi.addActionListener(this); // make a Misc sub menu of Help menu Menu subMenu = new Menu("Misc"); subMenu.add(mi = new MenuItem("Help!!!")); mi.addActionListener(this); subMenu.add(mi = new MenuItem("Why did that happen?")); mi.addActionListener(this); add(subMenu); } // respond to a few menu items public void actionPerformed(ActionEvent e) { String item = e.getActionCommand(); if (item.equals("Fundamentals")) System.out.println("Fundamentals"); else if (item.equals("Help!!!")) System.out.println("Help!!!"); // etc... } } ExerciseMenu ShortcutsOne nice feature of the If you want to create two menu items with speed keys, Ctrl-P for Print and Shift-Ctrl-P for Print Preview, the following code would do that: file.add (mi = new MenuItem ("Print", new MenuShortcut('p'))); file.add (mi = new MenuItem ("Print Preview", new MenuShortcut('p', true))); The example above uses Ctrl-P and Shift-Ctrl-P shortcuts on Windows/Motif.
The use of Ctrl for the shortcut key is defined by the Pop-up MenusOne restriction of the The actual mouse interaction to generate the event is platform specific so
there is the means to determine if a The following program,
import java.awt.*; import java.awt.event.*; public class PopupApplication extends AppFrame { Button btn; TextField msg; PopupAppMenu m; public PopupApplication() { super("PopupApplication"); setSize(200, 200); btn = new Button("Press for pop-up menu..."); add(btn, BorderLayout.NORTH); msg = new TextField(); msg.setEditable(false); add(msg, BorderLayout.SOUTH); m = new PopupAppMenu(this); add(m); btn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { m.show(btn, 10, 10); } }); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) m.show(e.getComponent(), e.getX(), e.getY()); } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) m.show(e.getComponent(), e.getX(), e.getY()); } }); } public static void main(String[] args) { PopupApplication app = new PopupApplication(); app.setVisible(true); } } class PopupAppMenu extends PopupMenu implements ActionListener { PopupApplication ref; public PopupAppMenu(PopupApplication ref) { super("File"); this.ref = ref; MenuItem mi; add(mi = new MenuItem("Copy")); mi.addActionListener(this); add(mi = new MenuItem("Cut")); mi.addActionListener(this); add(mi = new MenuItem("Paste")); mi.addActionListener(this); } public void actionPerformed(ActionEvent e) { String item = e.getActionCommand(); ref.msg.setText("Selected menu item: " + item); } } Copyright 1996-2000 jGuru.com. All Rights Reserved. |