AWT provides several widgets for GUI's. We will look at two of these now:
In our example, we will:
The code:
import java.awt.*; import java.awt.event.*; // Needed for ActionListener. class NewFrame extends Frame implements ActionListener, MouseListener { // Data. Button quitb, clearb, startb; Canvas c; Panel p; boolean start = false; // Constructor. public NewFrame (int width, int height) { // Set the title and other frame parameters. setTitle ("Panel and canvas example"); setResizable (true); setBackground (Color.cyan); setSize (width, height); // Create a quit button. quitb = new Button ("Quit"); quitb.setBackground (Color.red); quitb.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15)); quitb.addActionListener (this); // setLayout (new BorderLayout()); add (quitb, BorderLayout.SOUTH); // Create a white canvas. c = new Canvas (); c.setBackground (Color.white); c.setForeground (Color.blue); c.addMouseListener (this); // Add canvas to frame in the center. add (c, BorderLayout.CENTER); // Create a Panel p = new Panel (); p.setLayout (new FlowLayout()); // Create a clear button. clearb = new Button ("Clear"); clearb.addActionListener (this); clearb.setBackground (Color.green); // Add clear button to panel. p.add (clearb); // Create a start button. startb = new Button ("Start"); startb.addActionListener (this); startb.setBackground (Color.green); // Add start button to panel. p.add (startb); // Now add the panel to the frame. add (p, BorderLayout.NORTH); // Show the frame. setVisible (true); } // This method is required to implement the // ActionListener interface. public void actionPerformed (ActionEvent a) { String s = a.getActionCommand(); if (s.equalsIgnoreCase ("Quit")) System.exit(0); else if (s.equalsIgnoreCase ("Clear")) { // Note: must call repaint() of canvas // to reset the background. c.setBackground (Color.white); c.repaint (); current_x = current_y = 0; } else if (s.equalsIgnoreCase ("Start")) start = true; } int current_x=0, current_y=0; // These methods are required to implement // the MouseListener interface. public void mouseClicked (MouseEvent m) { if (!start) // User must click start once to draw. return; int x = m.getX(); int y = m.getY(); Graphics g = c.getGraphics(); g.drawLine (current_x, current_y, x, y); current_x = x; current_y = y; } // We need to implement these methods, but // don't actually have to do anything inside. public void mouseEntered (MouseEvent m) {} public void mouseExited (MouseEvent m) {} public void mousePressed (MouseEvent m) {} public void mouseReleased (MouseEvent m) {} } // End of class "NewFrame" public class TestAwt24 { public static void main (String[] argv) { NewFrame nf = new NewFrame (300, 200); } }
The frame continues to use a BorderLayout: The canvas is placed in the center (BorderLayout.CENTER). The quit button is placed SOUTH. The panel (containing the other two buttons) is placed NORTH.
Since the frame implements the listeners, the frame itself is passed via this to the add-listener methods:
quitb.addActionListener (this); c.addMouseListener (this);
Since we want only the canvas to react to mouse-clicks, we set only its mouse-listener (to this).
c.addMouseListener (this);
We used a FlowLayout for the Panel: A FlowLayout does not "stretch" buttons (or other components). Note: the default layout for a Panel is FlowLayout. Here is what we could do with a GridLayout:
// Create a Panel p = new Panel (); // Set the Panel's layout to a GridLayout // with one row and two columns p.setLayout (new GridLayout(1,2)); // Create the start and clear buttons ... // Add start and clear buttons to panel. p.add (clearb); p.add (startb);
Observe that every button-press (for any button) results in a call to the same method: actionPerformed() in the frame:
To know which button was pressed, the parameter is used. The String corresponding to the button name can be extracted from the parameter:
String s = a.getActionCommand();
Alternatively, the method getSource() in the event can be used, for example: The quit button was declared as:
class NewFrame extends Frame implements ActionListener, MouseListener { Button quitb, clearb, startb; // ... }
Then, inside actionPerformed():
public void actionPerformed (ActionEvent a) { if (a.getSource() == quitb) { // ... etc } // ... }Here, the getSource() method returns the object for which the event occured.
To clear the canvas' background, we set the background color and repaint the canvas:
c.setBackground (Color.white); c.repaint ();
To draw on the canvas, we must use the graphics context of the canvas:
Graphics g = c.getGraphics(); g.drawLine (current_x, current_y, x, y);
Modify the above drawing canvas so that a user may select a line color
from among orange, pink and yellow. Place buttons with those names and when a color button is clicked, change
the canvas' Foreground color.
Note that we are not using inner classes.
Most GUI widgets are interactive (e.g., a button) and thus, can cause (via the user) events to be generated. Programmers generally desire control when events are generated. (For example, when a user presses a button, you the programmer may need to perform some computation). Where do you find classes related to events?
java.awt.event: this package has many event-related classes, especially for commonly used widgets like JButton. javax.swing.event: this package has classes for more, pure-swing events. Classes related to events:
Event classes: A number of classes inherit from the class EventObject. These are used to pass information about the event that has just taken place.
Event listeners: These are interfaces defined in java.awt.event that a programmer must implement in order to handle events.
Event adapters: These are abstract classes provided for convenient implementation of listeners. They need not be used. We have already seen, for example, that a Button can generate an ActionEvent that must be handled by an ActionListener instance.
There are several ways to create a class that implements the interface ActionListener:
b.addActionListener (this); // "this" refers to the frame.
b.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { // ... do whatever needs to be done ... } } );
When you get control, you need to implement whatever needs to be done in the method actionPerformed.
How to work with events without losing your mind:
Some listeners:
public interface ActionListener extends EventListener { public void actionPerformed (ActionEvent a); }
public interface MouseListener extends EventListener { public void mouseClicked (MouseEvent m); public void mouseEntered (MouseEvent m); public void mouseExited (MouseEvent m); public void mousePressed (MouseEvent m); public void mouseReleased (MouseEvent m); }
public interface MouseMotionListener extends EventListener { public void mouseDragged (MouseEvent m); public void mouseMoved (MouseEvent m); }
public interface KeyListener extends EventListener { public void keyPressed (KeyEvent k); public void keyReleased (KeyEvent k); public void keyTyped(KeyEvent k); }
public interface ItemListener extends EventListener { public void itemStateChanged (ItemEvent i); }
public interface FocusListener extends EventListener { public void focusGained (FocusEvent f); public void focusLost (FocusEvent f); }
public interface AdjustmentListener extends EventListener { public void adjustmentValueChanged (AdjustmentEvent a); }
public interface WindowListener extends EventListener { public void windowOpened (WindowEvent w); public void windowClosed (WindowEvent w); public void windowClosing(WindowEvent w); public void windowIconified (WindowEvent w); public void windowDeiconified (WindowEvent w); public void windowActivated (WindowEvent w); public void windowDeactivated (WindowEvent w); }
public interface TextListener extends EventListener { public void textValueChanged (TextEvent t); }
Generally, the information you need related to an event can be found in the parameter: For example, for a mouse event, you need the mouse location (coordinates). You can get the coordinates in the MouseEvent instance that gets passed to you.
It is possible to set it up so that multiple event listeners are called by a single event.
It is possible to create altogether new events and perform low-level manipulation of event-handling. (For advanced programmers).