The AWT (Abstract Window Toolkit) is
a large collection of classes geared towards letting the programmer
build GUI's (Graphical User Interfaces).
What can you do with the AWT library?
What can't you do with the AWT library?
Typical classes you can expect to use include:
Components and Containers:
The entire AWT library is divided into four sub-packages:
(Java does have other class libraries for this purpose).
It's almost impossible to figure out how to bring up a window
by looking at the library.
To get started, the following facts will be useful:
Let us create a simple blank window that does nothing:
Note:
Next, let's create a slightly improved window:
(source file)
Note:
import java.awt.*;
public class TestAwt1 {
public static void main (String[] argv)
{
Frame f = new Frame ();
}
}
The code compiles, but on execution nothing shows up and the
terminal hangs.
import java.awt.*;
public class TestAwt1 {
public static void main (String[] argv)
{
Frame f = new Frame ();
f.setSize (200, 100);
f.setVisible (true);
}
}
This does produce a window:
(On SUN Solaris running OpenWin)
(In Openwin: you can iconify, but not quit).
import java.awt.*;
public class TestAwt2 {
public static void main (String[] argv)
{
// Create a Frame instance.
Frame f = new Frame ();
// Set the size.
f.setSize (200, 100);
// Install a title for the titlebar.
f.setTitle ("A Test Window");
// A background color.
f.setBackground (Color.cyan);
// Display.
f.setVisible (true);
}
}
The result:
In-Class Exercise 9.1:
Use the above code in the following
template
to print out the screen size in inches. Next,
bring up a window that is 3 inches wide and 2 inches in height
and place the window approximately in the center of the screen.
(Use the setLocation method of Component).
f.setResizable ();
// Get a Toolkit instance.
Toolkit tk = Toolkit.getDefaultToolkit ();
// Get resolution in pixels per inch.
int pixels_per_inch = tk.getScreenResolution ();
// Screen dimensions can also be obtained in a Dimension instance.
Dimension screen_size = tk.getScreenSize ();
// Print out results.
System.out.println ("Resolution: " + pixels_per_inch);
System.out.println ("Size (pixels): Height=" + screen_size.height +
", Width=" + screen_size.width);
We will now look at some of the basic graphics (drawing and
lettering) offered in AWT:
Confusing? Let's look at a simple example:
An explanation:
Next, let us draw some geometric figures:
For example, consider the following code:
(source file)
We can improve the code slightly by placing all the
frame-related code inside NewFrame itself:
(source file)
In-Class Exercise 9.2:
Use the following template
to draw a standard 8x8 chessboard. Let the size of the chessboard
be determined by minimum of the two dimensions of the frame.
Place the topleft corner of the chessboard at the topleft corner
of the frame.
// Extend Frame in order to override paint()
class NewFrame extends Frame {
// Override paint():
public void paint (Graphics g)
{
// drawString() is a Graphics method.
// Draw the string "Hello World" at location 100,100
g.drawString ("Hello World!", 100, 100);
}
}
public class TestAwt4 {
public static void main (String[] argv)
{
// Create an instance of NewFrame
NewFrame nf = new NewFrame ();
// Set the title and other parameters.
nf.setTitle ("Hello World Test");
nf.setResizable (true);
nf.setBackground (Color.cyan);
nf.setSize (500, 300);
// Show the frame.
nf.setVisible (true);
}
}
Here is the result:
class NewFrame extends Frame {
public void paint (Graphics g)
{
// drawString() is a Graphics method.
// Draw the string "Hello World" at location 100,100
g.drawString ("Hello World!", 100, 100);
}
}
(The origin, for undiscernible reasons, is at the topleft corner).
(If the lines are axis-parallel, you can use filled rectangles).
class NewFrame extends Frame {
// Override paint():
public void paint (Graphics g)
{
// Draw a Square:
g.drawRect (50,50,50,50);
g.drawString ("Square", 50, 115);
// Circle:
g.drawOval (200,50,50,50);
g.drawString ("Circle", 200, 115);
// Rounded rectangle:
g.drawRoundRect (350,50,75,50,20,20);
g.drawString ("Rectangle", 350, 115);
// Draw a line across the middle:
g.drawLine (0,150,500,150);
// Now draw some filled shapes:
// Square:
g.fillRect (50,200,50,50);
g.drawString ("Square", 50, 265);
// Circle:
g.fillOval (200,200,50,50);
g.drawString ("Circle", 200, 265);
// Rounded rectangle:
g.fillRoundRect (350,200,75,50,20,20);
g.drawString ("Rectangle", 350, 265);
}
}
public class TestAwt5 {
public static void main (String[] argv)
{
// Create an instance of NewFrame
NewFrame nf = new NewFrame ();
// Set the title and other parameters.
nf.setTitle ("Some Geometric Figures");
nf.setResizable (true);
nf.setBackground (Color.cyan);
nf.setSize (500, 300);
// Show the frame.
nf.setVisible (true);
}
}
The result produced is:
import java.awt.*;
class NewFrame extends Frame {
// Constructors.
public NewFrame (int width, int height)
{
// Set the title and other parameters.
this.setTitle ("Some Geometric Figures");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// No-parameter constructor - use a default size.
public NewFrame ()
{
this (500, 300);
}
// Override paint():
public void paint (Graphics g)
{
// Draw a Square:
g.drawRect (50,50,50,50);
g.drawString ("Square", 50, 115);
// Circle:
g.drawOval (200,50,50,50);
g.drawString ("Circle", 200, 115);
// Rounded rectangle:
g.drawRoundRect (350,50,75,50,20,20);
g.drawString ("Rectangle", 350, 115);
// Draw a line across the middle:
g.drawLine (0,150,500,150);
// Now draw some filled shapes:
// Square:
g.fillRect (50,200,50,50);
g.drawString ("Square", 50, 265);
// Circle:
g.fillOval (200,200,50,50);
g.drawString ("Circle", 200, 265);
// Rounded rectangle:
g.fillRoundRect (350,200,75,50,20,20);
g.drawString ("Rectangle", 350, 265);
}
}
public class TestAwt6 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (500, 300);
}
}
Note:
In the above chessboard exercise you may have noticed two
oddities about AWT:
The problem of handling insets is more involved:
Finally, let us clean up the code by placing the inset
computation in the constructor:
(source file)
One last point:
In-Class Exercise 9.3:
Modify your Ex 9.3 code or use this
template to solve the inset problem for the chessboard.
In addition, use the getSize() method to dynamically
compute the size in paint(). This way, if the window
is re-sized, the chessboard will fit the new window.
To fix the latter problem, you can draw a line around the periphery
of the chessboard.
import java.awt.*;
class NewFrame extends Frame {
// Constructors.
public NewFrame (int width, int height)
{
// Set the title and other parameters.
this.setTitle ("Inset problem");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// No-parameter constructor - use a default size.
public NewFrame ()
{
this (500, 300);
}
// Override paint():
public void paint (Graphics g)
{
// Topleft at 0,0:
g.drawOval (0,0, 100,100);
// Topleft at (0, 300-100):
g.drawOval (0,200, 100,100);
// Topleft at (300-100, 0):
g.drawOval (200,0, 100,100);
// Topleft at (300-100, 300-100):
g.drawOval (200,200, 100,100);
}
}
public class TestAwt7 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 300);
}
}
public class Insets {
// ...
public int top;
public int bottom;
public int left;
public int right;
// ...
}
Insets I = this.getInsets ();
public void paint (Graphics g)
{
Insets I = this.getInsets ();
// Draw circles of diameter 100 at each corner.
// Topleft at 0,0:
g.drawOval (0+I.left, 0+I.top, 100,100);
// Topleft at (0, height-100):
g.drawOval (0+I.left, height-I.bottom-100, 100,100);
// Topleft at (width-100, 0):
g.drawOval (width-I.right-100, 0+I.top, 100,100);
// Topleft at (width-100, width-100):
g.drawOval (width-I.right-100, height-I.bottom-100, 100,100);
}
public void paint (Graphics g)
{
Insets I = this.getInsets ();
// Draw circles of diameter 100 at each corner.
// Topleft at 0,0:
g.drawOval (0+I.left, 0+I.top, 100,100);
// Topleft at (0, height-100):
g.drawOval (0+I.left, height-I.bottom-1-100, 100,100);
// Topleft at (width-100, 0):
g.drawOval (width-I.right-1-100, 0+I.top, 100,100);
// Topleft at (width-100, width-100):
g.drawOval (width-I.right-1-100, height-I.bottom-1-100, 100,100);
class NewFrame extends Frame {
int width, height;
int originx, originy;
int draw_width, draw_height;
// Constructors.
public NewFrame (int width, int height)
{
// Set the title and other parameters.
this.setTitle ("Inset problem");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
this.width = width;
this.height = height;
// Show the frame.
this.setVisible (true);
// Compute insets.
Insets I = this.getInsets ();
originx = 0+I.left;
originy = 0+I.top;
draw_width = width - (I.right + 1);
draw_height = height - (I.bottom + 1);
}
// No-parameter constructor - use a default size.
public NewFrame ()
{
this (500, 300);
}
// Override paint():
public void paint (Graphics g)
{
// Draw circles of diameter 100 at each corner.
// Topleft at 0,0:
g.drawOval (originx, originy, 100,100);
// Topleft at (0, height-100):
g.drawOval (originx, draw_height-100, 100,100);
// Topleft at (width-100, 0):
g.drawOval (draw_width-100, originy, 100,100);
// Topleft at (width-100, width-100):
g.drawOval (draw_width-100, draw_height-100, 100,100);
}
}
Note:
(Because the native Window must be created first).
However, only the visible area will be shown.
public void paint (Graphics g)
{
// Draw a wide rectangle:
g.fillRect (-100, 100, 800, 50);
}
AWT's support for text is somewhat limited:
The following code tells you what fonts are supported:
About fonts:
Consider this example, which prints out Serif
and SansSerif strings in two sizes and all the available
styles:
(source file)
Note:
Typesetting:
We will consider an example in which:
This prints out the following:
In-Class Exercise 9.4:
Use the following
template to create a frame in which you write the largest
possible "Hello World!" that will fit into the drawable area.
Start with a font size of 10 and increase the size in increments
of 10 until you find the largest possible font that will fit into
the drawable area.
Allow for the situation where the window may be resized.
String[] fontlist = Toolkit.getDefaultToolkit().getFontList ();
for (int i=0; i < fontlist.length; i++)
System.out.println (fontlist[i]);
Note:
Toolkit tk = Toolkit.getDefaultToolkit();
String[] fontlist = tk.getFontList();
Dialog
SansSerif
Serif
Monospaced
Helvetica
TimesRoman
Courier
DialogInput
ZapfDingbats
(Logical OR).
import java.awt.*;
class NewFrame extends Frame {
// Constructors.
public NewFrame (int width, int height)
{
// Set the title and other parameters.
this.setTitle ("Fonts");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// No-parameter constructor - use a default size.
public NewFrame ()
{
this (500, 300);
}
// Override paint():
public void paint (Graphics g)
{
// Create 10-point Serif fonts in all styles:
Font f1 = new Font ("Serif", Font.PLAIN, 10);
g.setFont (f1);
g.drawString ("Serif-Plain-10pt", 30, 60);
f1 = new Font ("Serif", Font.ITALIC, 10);
g.setFont (f1);
g.drawString ("Serif-Italic-10pt", 30, 90);
f1 = new Font ("Serif", Font.PLAIN | Font.BOLD, 10);
g.setFont (f1);
g.drawString ("Serif-Plain-Bold-10pt", 30, 120);
f1 = new Font ("Serif", Font.ITALIC | Font.BOLD, 10);
g.setFont (f1);
g.drawString ("Serif-Italic-Bold-10pt", 30, 150);
// Create 20-point SansSerif fonts in all styles:
f1 = new Font ("SansSerif", Font.PLAIN, 20);
g.setFont (f1);
g.drawString ("SansSerif-Plain-20pt", 140, 60);
f1 = new Font ("SansSerif", Font.ITALIC, 20);
g.setFont (f1);
g.drawString ("SansSerif-Italic-20pt", 140, 90);
f1 = new Font ("SansSerif", Font.PLAIN | Font.BOLD, 20);
g.setFont (f1);
g.drawString ("SansSerif-Plain-Bold-20pt", 140, 120 );
f1 = new Font ("SansSerif", Font.ITALIC | Font.BOLD, 20);
g.setFont (f1);
g.drawString ("SansSerif-Italic-Bold-20pt", 140, 150);
}
}
public class TestAwt11 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (450,200);
}
}
The result produced is:
Font f1 = new Font ("Serif", Font.PLAIN, 10);
f1 = new Font ("SansSerif", Font.ITALIC | Font.BOLD, 20);
g.drawString ("Hello World!", 30, 60);
- you need to compute line lengths, inter-word spacing, etc.
- usually, the lowest point of a non-descending character like "h".
(Space between lines, essentially).
public void paint (Graphics g)
{
// Create a font.
Font f = new Font ("Serif", Font.PLAIN | Font.BOLD, fontsize);
// Set the font in the graphics instance.
g.setFont (f);
// Get a FontMetrics instance from the graphics instance.
FontMetrics fm = g.getFontMetrics();
}
public abstract FontMetrics implements Serializable {
//...
// Some methods that return a font characteristic.
public int getAscent ();
public int getDescent ();
public int getLeading ();
public int getHeight ();
public int maxAscent ();
public int maxDescent ();
// Get the resulting width of a string.
public int stringWidth (String s);
//...
}
Here is code:
(source file)
import java.awt.*;
class NewFrame extends Frame {
String[] words; // List of words to display.
int fontsize; // Size of font.
// Constructor.
public NewFrame (int width, int height, String[] words, int fontsize)
{
// Retain data and font size.
this.words = words;
this.fontsize = fontsize;
// Set the title and other frame parameters.
this.setTitle ("Font metrics");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// Override paint():
public void paint (Graphics g)
{
// Create a Serif font in the given font size.
Font f = new Font ("Serif", Font.PLAIN | Font.BOLD, fontsize);
g.setFont (f);
// Get a FontMetrics instance from the graphics context.
FontMetrics fm = g.getFontMetrics();
// Get the height (height of font plus separator).
int fontheight = fm.getHeight ();
// Size of frame plus insets.
Dimension D = this.getSize ();
Insets I = this.getInsets ();
// Visible drawing area
int max_width = D.width - I.left - I.right - 1;
int max_height = D.height - I.top - I.bottom - 1;
// Start at topleft.
int startx = 0 + I.left;
// Must add font height since bottom left corner
// of font is used as starting point.
int y = 0 + I.top + fontheight;
int x = startx;
for (int i=0; i < words.length; i++) {
// Obtain pixel-length of string (with blank)
int len = fm.stringWidth (" " + words[i]);
if (x + len < max_width) {
// If it fits within the current line, draw it
g.drawString (" " + words[i], x, y);
x += len;
}
else {
// Go to next line.
x = startx;
y += fontheight;
g.drawString (" " + words[i], x, y);
x += len;
}
}
} // "paint"
} // End of class "NewFrame"
public class TestAwt12 {
public static void main (String[] argv)
{
String[] testwords = {
"There", "once", "was", "a", "poet", "named", "Heinz",
"All", "of", "whose", "poems", "had", "just", "two", "lines."
};
NewFrame nf = new NewFrame (600,200, testwords, 35);
}
}
Note:
(The window size may be changed.)
Dimension D = this.getSize ();
Insets I = this.getInsets ();
int max_width = D.width - I.left - I.right - 1;
int max_height = D.height - I.top - I.bottom - 1;
int startx = 0 + I.left;
int y = 0 + I.top + fontheight;
NewFrame nf = new NewFrame (600,200, testwords, 35);
Java provides some support for loading, manipulating and
displaying images in a window:
In this module, we will only consider simple image features.
About image formats
Let's look at a simple example:
(source file)
The result produced is:
Note:
In the next example, we will fetch an image from a URL:
(source file)
Note:
The following classes will be useful:
(Unisys holds the LZW patent).
public Image getImage (String filename);
public Image getImage (URL u);
import java.awt.*;
class NewFrame extends Frame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Bugs");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// Override paint():
public void paint (Graphics g)
{
// Get a Toolkit instance.
Toolkit tk = Toolkit.getDefaultToolkit ();
// Provide a filename to the getImage() method.
Image img = tk.getImage ("bugs.gif");
// Use the drawImage method.
g.drawImage (img, 0, 0, this);
// Note: we pass "this" as a parameter.
}
} // End of class "NewFrame"
public class TestAwt13 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
public void boolean drawImage (Image img, int x, int y, ImageObserver I);
Here:
public abstract class Component
implements ImageObserver, MenuContainer, Serializable {
// ...
}
g.drawImage (img, 0, 0, this);
import java.awt.*;
import java.net.*; // For class URL.
class NewFrame extends Frame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Gif image");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Show the frame.
this.setVisible (true);
}
// Override paint():
public void paint (Graphics g)
{
Toolkit tk = Toolkit.getDefaultToolkit ();
// try-catch needed since URL constructor throws an exception.
try {
// URL is in java.net.
URL u = new URL ("http://www.seas.gwu.edu/~simha/canyon.jpg");
// Load the image using the second form of getImage().
Image img = tk.getImage (u);
// Display image.
g.drawImage (img, 0, 0, this);
}
catch (MalformedURLException e) {
System.out.println (e);
}
} // "paint"
} // End of class "NewFrame"
public class TestAwt14 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (600, 300);
}
}
The result is:
URL u = new URL ("http://www.seas.gwu.edu/~simha/canyon.jpg");
In-Class Exercise 9.5:
Use the following
template to create a frame in which you
load the image at URL
http://www.seas.gwu.edu/~simha/mystery_person.jpg.
and then fit the image so that it fits exactly into the
drawable area. To do this:
Can you identify the person in the picture?
public boolean drawImage (Image img, int x, int y, int width,
int height, ImageObserver I);
Next, we will use a MediaTracker instance to complete loading before display: (source file)
public void paint (Graphics g) { Toolkit tk = Toolkit.getDefaultToolkit (); try { URL u = new URL ("http://www.seas.gwu.edu/~simha/canyon.jpg"); Image img = tk.getImage (u); // Create an instance of MediaTracker and // pass a Frame instance as parameter (via "this"). MediaTracker mt = new MediaTracker (this); // Add the image instance to the tracker. mt.addImage (img, 1); // We will use a "wait" (clock) cursor while the // image is loading. this.setCursor (Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR)); // Ask the MediaTracker to wait. try { mt.waitForID (1); } catch (InterruptedException e) { System.out.println (e); } // Now the image has been loaded. // Return to default cursor. this.setCursor (Cursor.getPredefinedCursor (Cursor.DEFAULT_CURSOR)); // Draw the complete image. g.drawImage (img, 0, 0, this); } catch (MalformedURLException e) { System.out.println (e); } } // "paint"
In-Class Exercise 9.6:
Use the following
template to create a frame in which you
load the four images guy1.gif, guy2.gif, guy3.gif
and guy4.gif at URL
http://www.seas.gwu.edu/~simha/.
(Thus, the URL for guy1.gif is
http://www.seas.gwu.edu/~simha/guy1.gif).
This time, instead of fitting the images to the frame, fit
the frame to hold all images in a row so that the frame width
at least the sum of the image widths and the frame height is
at least as large the the maximum height of the images.
The following methods will be useful:
Thus far, we have only drawn or painted on a window.
To allow a user to interact, we need to receive user input
in the form of mouse-clicks or keyboard characaters.
We will first consider a simple "quit" button as an example:
(source file)
The result produced is:
Note:
Next, let us try making small changes in the layout:
Next, we will make two improvements:
Note:
In-Class Exercise 9.7:
In this example, you will create a frame with some truly awful
color combinations.
Use the following
template to create a frame in which you post
four buttons using the FlowLayout manager:
import java.awt.*;
class NewFrame extends Frame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Create a Button instance and pass the button
// label as a parameter to the constructor.
Button b = new Button ("Quit");
// Set the layout manager for our Frame.
this.setLayout (new BorderLayout());
// Add the button to the frame.
this.add (b);
// Show the frame.
this.setVisible (true);
}
} // End of class "NewFrame"
public class TestAwt16 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
(This is a result of the layout method used).
(We haven't created a button-pressed event-handler yet).
public class Button extends Component {
// Constructors.
public Button ();
public Button (String label);
// Methods.
public synchronized void addActionListener (ActionListener a);
public String getLabel ();
public synchronized void setLabel (String label);
// ...
}
Button b = new Button ("Quit");
public Component add (Component c);
public void paint (Graphics g)
{
// Create a Button instance and pass the button
// label as a parameter to the constructor.
Button b = new Button ("Quit");
// Set the layout manager for our Frame.
this.setLayout (new BorderLayout());
// Add the button to the frame.
this.add (b);
// Call validate to re-compute what's
// inside a container.
this.validate();
}
public class TestAwt18 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
// Create a Button instance and pass the button
// label as a parameter to the constructor.
Button b = new Button ("Quit");
// Set the layout manager for the frame.
nf.setLayout (new BorderLayout());
// Add the button to the frame.
nf.add (b);
// Call validate to reset:
nf.validate();
}
}
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Create a new button.
Button b = new Button ("Quit");
// BorderLayout is already the manager so
// we leave the setLayout commented out.
// this.setLayout (new BorderLayout());
// Add the button to the frame.
this.add (b, BorderLayout.SOUTH);
// Show the frame.
this.setVisible (true);
}
This produces:
Note:
this.add (new Button ("South"), BorderLayout.SOUTH);
this.add (new Button ("North"), BorderLayout.NORTH);
this.add (new Button ("East"), BorderLayout.EAST);
this.add (new Button ("West"), BorderLayout.WEST);
this.add (new Button ("Center"), BorderLayout.CENTER);
// Create a new button.
Button b = new Button ("Quit");
// Use a FlowLayout manager.
this.setLayout (new FlowLayout());
// Add the button to the frame.
this.add (b);
// Show the frame.
this.setVisible (true);
Here is the code:
(source file)
import java.awt.*;
import java.awt.event.*; // Needed for ActionListener.
class NewFrame extends Frame implements ActionListener {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Create a new button.
Button b = new Button ("Quit");
// Set the background color of the button.
b.setBackground (Color.red);
// Set the font of the button label.
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
// Add an ActionListener to the button.
b.addActionListener (this);
// BorderLayout is already the manager so
// we leave the setLayout commented out.
// this.setLayout (new BorderLayout());
// Add the button to the south of the frame.
this.add (b, BorderLayout.SOUTH);
// Show the frame.
this.setVisible (true);
}
// This method is required to implement the
// ActionListener interface.
public void actionPerformed (ActionEvent a)
{
// Button must have been pressed - so really quit.
System.exit (0);
}
} // End of class "NewFrame"
public class TestAwt22 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
Here is the result:
public class Button extends Component {
// ...
public synchronized void addActionListener (ActionListener a);
// ...
}
public interface ActionListener extends EventListener {
public abstract void actionPerformed (ActionEvent e);
}
// Add an ActionListener to the button.
b.addActionListener (this);
This tells the button, that the listener has a method called
actionPerformed that can be called when the button
is pressed.
public void actionPerformed (ActionEvent a)
{
String event_desc = a.getActionCommand();
if (event_desc.equalsIgnoreCase("Quit"))
System.exit (0);
}
public void actionPerformed (ActionEvent a)
{
String event_desc = a.getActionCommand();
if (event_desc.equalsIgnoreCase("Quit"))
System.exit (0);
else if (event_desc.equalsIgnoreCase ("Redraw")) {
this.repaint ();
}
}
Thus, you need to add lines to actionPerformed() to set
a color. Then, you need to call repaint() at the end of
actionPerformed. Finally, you need to implement
the method paint (as we have done before) to actually
draw the string "Hello World!" in the desired color. Note
that the signature of paint must be:
public void paint (Graphics g);
We will now write a simple program to perform some drawing
based on mouse-clicks:
Here is the code:
(source file)
Note:
To "listen" for mouse-clicks, we need an object that implements
the MouseListener interface:
public interface MouseListener extends EventListener {
public abstract void mouseClicked (MouseEvent e);
public abstract void mouseEntered (MouseEvent e);
public abstract void mouseExited (MouseEvent e);
public abstract void mousePressed (MouseEvent e);
public abstract void mouseReleased (MouseEvent e);
}
class NewFrame extends Frame
implements ActionListener, MouseListener {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Create a quit button.
Button b = new Button ("Quit");
b.setBackground (Color.red);
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
b.addActionListener (this);
// this.setLayout (new BorderLayout());
this.add (b, BorderLayout.SOUTH);
// Add mouse-listening to the frame itself.
this.addMouseListener (this);
// Show the frame.
this.setVisible (true);
}
// This method is required to implement the
// ActionListener interface.
public void actionPerformed (ActionEvent a)
{
// Button must have been pressed - so really quit.
System.exit (0);
}
int current_x=0, current_y=0;
// These methods are required to implement
// the MouseListener interface.
public void mouseClicked (MouseEvent m)
{
System.out.println ("mouseClicked event: " + m.paramString());
int x = m.getX();
int y = m.getY();
Graphics g = this.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"
The result (after a few random mouse clicks):
this.add ( /* mouse listener */ );
// Add mouse-listening to the frame itself.
this.addMouseListener (this);
public void mouseEntered (MouseEvent m) {}
public void mouseExited (MouseEvent m) {}
public void mousePressed (MouseEvent m) {}
public void mouseReleased (MouseEvent m) {}
Graphics g = this.getGraphics();
g.drawLine (current_x, current_y, x, y);
AWT provides several widgets for GUI's. We will look at two
of these now:
In our example, we will:
The code:
(source file)
In-Class Exercise 9.8:
Use the following template
to 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 (as you did in Exercise 9.7) and when a
color button is clicked, change the canvas' Foreground
color.
Here is what we want the frame to look like:
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.
this.setTitle ("Panel and canvas example");
this.setResizable (true);
this.setBackground (Color.cyan);
this.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);
// this.setLayout (new BorderLayout());
this.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.
this.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.
this.add (p, BorderLayout.NORTH);
// Show the frame.
this.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);
}
}
Note:
quitb.addActionListener (this);
c.addMouseListener (this);
c.addMouseListener (this);
// 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);
The result:
String s = a.getActionCommand();
class NewFrame extends Frame
implements ActionListener, MouseListener {
Button quitb, clearb, startb;
// ...
}
public void actionPerformed (ActionEvent a)
{
if (a.getSource() == quitb) {
// ... etc
}
// ...
}
c.setBackground (Color.white);
c.repaint ();
Graphics g = c.getGraphics();
g.drawLine (current_x, current_y, x, y);
The class Component defines methods called
paint(), repaint() and update().
The way these methods interact can sometimes create strange
results.
First, consider what the methods are intended for:
Here's an example of a weird effect:
This problem can be fixed by calling paint instead
of repaint:
To solve the above problem, we simply override update()
and make sure the background is not cleared:
(source file)
The code: (source file)
class NewFrame extends Frame
implements ActionListener, MouseListener {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Paint and Update");
this.setResizable (true);
this.setBackground (Color.cyan);
this.setSize (width, height);
// Create a quit button.
Button b = new Button ("Quit");
b.setBackground (Color.red);
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
b.addActionListener (this);
// this.setLayout (new BorderLayout());
this.add (b, BorderLayout.SOUTH);
// Add mouse-listening to the frame itself.
this.addMouseListener (this);
// Show the frame.
this.setVisible (true);
}
public void actionPerformed (ActionEvent a)
{
System.exit (0); // Quit button pressed.
}
int current_x=0, current_y=0;
int new_x, new_y;
// These methods are required to implement
// the MouseListener interface.
public void mouseClicked (MouseEvent m)
{
new_x = m.getX();
new_y = m.getY();
// Call repaint to reflect new line.
repaint();
}
public void mouseEntered (MouseEvent m) {}
public void mouseExited (MouseEvent m) {}
public void mousePressed (MouseEvent m) {}
public void mouseReleased (MouseEvent m) {}
public void paint (Graphics g)
{
System.out.println ("Paint: cx=" + current_x + ",cy=" + current_y
+ ", nx=" + new_x + ",ny=" + new_y);
g.drawLine (current_x, current_y, new_x, new_y);
current_x = new_x;
current_y = new_y;
}
} // End of class "NewFrame"
Note:
public void mouseClicked (MouseEvent m)
{
new_x = m.getX();
new_y = m.getY();
// Instead of calling repaint(),
// call paint() directly, with the
// correct graphics context.
Graphics g = this.getGraphics();
paint (g);
}
Note:
// Override update() and make sure the
// background is not cleared.
public void update (Graphics g)
{
paint (g);
}
Note:
Applets are Java's mechanism for executing code inside a
browser.
An applet is created by extending the class Applet
in the package java.applet.
As an example, let us create an applet version of the
mouse-click drawing code we created in a frame:
Here is the applet code, in TestApplet.java:
(source file)
To execute the applet, there are several options:
<html>
<body>
An applet to test mouse-clicks:
<applet code="TestApplet.class" width=300 height=200>
<!-- The line below will appear if Java is not supported-->
Browser does not support Java 1.1.
</applet>
</body>
</html>
Note:
import java.awt.*;
import java.awt.event.*;
import java.applet.*; // Must import the Applet class in here.
public class TestApplet extends Applet
implements ActionListener, MouseListener {
// Data.
Button quitb, clearb, startb;
Canvas c;
Panel p;
boolean start = false;
// Constructor.
public void init()
{
// Title and size cannot be set in an applet.
this.setBackground (Color.cyan);
// 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);
// Default for an applet is FlowLayout.
this.setLayout (new BorderLayout());
this.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.
this.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);
// Create a start button.
startb = new Button ("Start");
startb.addActionListener (this);
startb.setBackground (Color.green);
// Add start and clear buttons to panel.
p.add (clearb);
p.add (startb);
// Now add the panel to the frame.
this.add (p, BorderLayout.NORTH);
// Show the frame.
this.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;
}
public void mouseEntered (MouseEvent m) {}
public void mouseExited (MouseEvent m) {}
public void mousePressed (MouseEvent m) {}
public void mouseReleased (MouseEvent m) {}
} // End of class "TestApplet"
% appletviewer TestApplet.html
This produces a window containing the applet. For example,
here is what we get after a few mouse-clicks: