While AWT is powerful enough to create many sophisticated
applications, and to develop custom components, it is cumbersome.
Java has now provided the "Swing" library as a standard part of
the JDK.
Swing differs from AWT:
What can't you do with Swing?
The really quick introduction to Swing, for an AWT programmer:
Typical classes you can expect to use include:
e.g., Swing's HTML component is nowhere as capable as Netscape's.
For example:
For example, use Swing's FileChooser instead of AWT's FileDialog.
Instead use it's ContentPane to add things.
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.*;
import javax.swing.*;
public class TestSwing1 {
public static void main (String[] argv)
{
JFrame f = new JFrame ();
}
}
The code compiles, but on execution nothing shows up and the
terminal hangs.
import java.awt.*;
import javax.swing.*;
public class TestSwing1 {
public static void main (String[] argv)
{
JFrame f = new JFrame ();
f.setSize (200, 100);
f.setVisible (true);
}
}
This does produce a window:
(On Linux running Gnome)
(In Openwin: you can iconify, but not quit).
import java.awt.*;
import javax.swing.*;
public class TestSwing2 {
public static void main (String[] argv)
{
// Create a Frame instance.
JFrame f = new JFrame ();
// Set the size.
f.setSize (200, 100);
// Install a title for the titlebar.
f.setTitle ("A Test Window");
// A background color:
// First, extract the contentPane
Container cPane = f.getContentPane();
// Then, set its color.
cPane.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 pixelPerInch = tk.getScreenResolution ();
// Screen dimensions can also be obtained in a Dimension instance.
Dimension screenSize = tk.getScreenSize ();
// Print out results.
System.out.println ("Resolution: " + pixelsPerInch);
System.out.println ("Size (pixels): Height=" + screenSize.height +
", Width=" + screenSize.width);
We will now look some basic graphics (drawing and
lettering):
Consider the appropriate widget for drawing:
All drawing occurs on a graphics context:
The all-important technique of overriding paintComponent()
(and, sometimes, repaint()):
Let's look at a simple example:
(source file)
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 panel.
Place the topleft corner of the chessboard at the topleft corner
of the panel.
In the above chessboard exercise you may have noticed two
things:
Note:
In-Class Exercise 9.3:
Modify your Ex 9.3 code or use this
template to dynamically
compute the size of the Panel in paintComponent().
You can do this by getting the width and height by calling
the getWidth() and getHeight() methods of the
Panel itself. This way, if the window
is re-sized, the chessboard will fit the new window.
Swing's support for text is better than AWT's, but still 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.
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
The following classes will be useful:
Let's look at a simple example:
(source file)
The result produced is:
Note:
Finally, we can clean up the code in NewPanel a little:
In the next example, we will fetch an image from a URL:
(source file)
Note:
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/~drum/mystery_person.jpg.
and then fit the image so that it fits exactly into the
drawable area. To do this:
Next, we will use a MediaTracker instance to
complete loading before display:
(source file)
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/~drum/.
(Thus, the URL for guy1.gif is
http://www.seas.gwu.edu/~drum/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:
NOTE:
Next, we will add an event-listener that handles the
case when the button is pressed.
Here is the code:
(source file)
Note:
In-Class Exercise 9.7:
Use the following
template to create a frame:
We will now write a simple program to perform some drawing
based on mouse-clicks:
Here is the code:
(source file)
Note:
Now, consider a different version of the program that
makes the JPanel the mouselistener:
(source file)
Thus far, we have used panels to draw. Panels are also used
as containers for layout purposes.
Suppose we wish to build the following feature into our
"click drawing" example:
Now, let's look at some code to make this happen:
(source file):
Note:
The class JComponent defines two methods
for use in drawing:
Comparison with AWT:
Applets are Java's mechanism for executing code inside a
browser.
There are two ways of creating applets:
Some terminology:
As an example, let us create an applet version of the
mouse-click drawing code we created above.
Here is the applet code, in TestApplet.java:
(source file)
To execute the applet, there are several options:
Important: Don't override paint() unless you
know what you are doing!
import java.awt.*;
import javax.swing.*;
// Extend JPanel to override its paintComponent() method:
class NewPanel extends JPanel {
// Set background in constructor.
public NewPanel ()
{
this.setBackground (Color.cyan);
}
// Override paintComponent():
public void paintComponent (Graphics g)
{
// Always call super.paintComponent (g):
super.paintComponent(g);
// drawString() is a Graphics method.
// Draw the string "Hello World" at location 100,100
g.drawString ("Hello World!", 100, 100);
// Let's find out when paintComponent() is called.
System.out.println ("Inside paintComponent");
}
}
public class TestSwing4 {
public static void main (String[] argv)
{
// Create a frame
JFrame f = new JFrame ();
// Set the title and other parameters.
f.setTitle ("Hello World Test");
f.setResizable (true);
f.setSize (500, 300);
// Add the panel using the default BorderLayout
NewPanel panel = new NewPanel ();
Container cPane = f.getContentPane ();
cPane.add (panel);
// Show the frame.
f.setVisible (true);
}
}
Here is the result:
class NewPanel extends JPanel {
// ...
}
Therefore, we set the Panel's background color to what we want.
(The origin is at the topleft corner).
(If the lines are axis-parallel, you can use filled rectangles).
import java.awt.*;
import javax.swing.*;
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (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 TestSwing5 {
public static void main (String[] argv)
{
// Create an instance of NewFrame
JFrame f = new JFrame ();
// Set the title and other parameters.
f.setTitle ("Some Geometric Figures");
f.setResizable (true);
f.setSize (500, 300);
// Create and add the panel.
NewPanel panel = new NewPanel ();
// Note alternative syntax:
f.getContentPane().add (panel);
// Show the frame.
f.setVisible (true);
}
}
The result produced is:
import java.awt.*;
import javax.swing.*;
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (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);
}
}
// Create a new Frame class.
class NewFrame extends JFrame {
public NewFrame ()
{
// Set the title and other parameters.
this.setTitle ("Some Geometric Figures");
this.setResizable (true);
this.setSize (500, 300);
// Create and add the panel.
NewPanel panel = new NewPanel ();
this.getContentPane().add (panel);
// Show the frame.
this.setVisible (true);
}
}
public class TestSwing6 {
public static void main (String[] argv)
{
// Simply fire up the whole application.
NewFrame f = new NewFrame ();
}
}
Note:
Container cPane = f.getContentPane ();
cPane.add (panel);
with the variable-free
f.getContentPane().add (panel);
If you are uncomfortable with this form, use the former syntax.
Frame insets
To fix the latter problem, you can draw a line around the periphery
of the chessboard.
However, only the visible area will be shown.
public void paintComponent (Graphics g)
{
super.paintComponent (g);
// Draw a wide rectangle:
g.fillRect (-100, 100, 800, 50);
}
// Create and add the panel.
this.getContentPane().add (new NewPanel());
Writing with fonts
// Print out available font names.
GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fNames = gEnv.getAvailableFontFamilyNames();
System.out.println ("Available font families: ");
for (int i=0; i < fNames.length; i++)
System.out.println (" " + fNames[i]);
Note:
Bitstream Charter
BookmanL
CenturySchoolbookL
ChanceryL
Courier
Courier 10 Pitch
Default
Dialog
DialogInput
Dingbats
GothicL
Lucida Bright
Lucida Sans
Lucida Sans Typewriter
Monospaced
NimbusMonoL
NimbusRomanNo9L
NimbusSansL
PalladioL
SansSerif
Serif
StandardSymbolsL
Utopia
Zapf Dingbats
(Logical OR).
import java.awt.*;
import javax.swing.*;
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (g);
// Create 10-point Serif fonts in all styles:
Font f = new Font ("Serif", Font.PLAIN, 10);
g.setFont (f);
g.drawString ("Serif-Plain-10pt", 30, 60);
f = new Font ("Serif", Font.ITALIC, 10);
g.setFont (f);
g.drawString ("Serif-Italic-10pt", 30, 90);
f = new Font ("Serif", Font.PLAIN | Font.BOLD, 10);
g.setFont (f);
g.drawString ("Serif-Plain-Bold-10pt", 30, 120);
f = new Font ("Serif", Font.ITALIC | Font.BOLD, 10);
g.setFont (f);
g.drawString ("Serif-Italic-Bold-10pt", 30, 150);
// Create 20-point SansSerif fonts in all styles:
f = new Font ("SansSerif", Font.PLAIN, 20);
g.setFont (f);
g.drawString ("SansSerif-Plain-20pt", 160, 60);
f = new Font ("SansSerif", Font.ITALIC, 20);
g.setFont (f);
g.drawString ("SansSerif-Italic-20pt", 160, 90);
f = new Font ("SansSerif", Font.PLAIN | Font.BOLD, 20);
g.setFont (f);
g.drawString ("SansSerif-Plain-Bold-20pt", 160, 120 );
f = new Font ("SansSerif", Font.ITALIC | Font.BOLD, 20);
g.setFont (f);
g.drawString ("SansSerif-Italic-Bold-20pt", 160, 150);
}
} // End of NewPanel
// Create a new Frame class.
class NewFrame extends JFrame {
public NewFrame ()
{
// Set the title and other parameters.
this.setTitle ("Some Geometric Figures");
this.setResizable (true);
this.setSize (500, 250);
// Create and add the panel.
NewPanel panel = new NewPanel ();
this.getContentPane().add (panel);
// Show the frame.
this.setVisible (true);
// Print out available font names.
GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fNames = gEnv.getAvailableFontFamilyNames();
System.out.println ("Available font families: ");
for (int i=0; i < fNames.length; i++)
System.out.println (" " + fNames[i]);
}
}
public class TestSwing11 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame ();
}
}
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).
// 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.*;
import javax.swing.*;
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
String[] words; // List of words to display.
int fontsize; // Size of font.
public NewPanel (String[] words, int fontsize)
{
// Retain data and font size.
this.words = words;
this.fontsize = fontsize;
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (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 ();
// Visible drawing area
int max_width = D.width;
int max_height = D.height;
// Start at topleft.
int startx = 0;
// Must add font height since bottom left corner
// of font is used as starting point.
int y = 0 + 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;
}
}
}
} // End of NewPanel
class NewFrame extends JFrame {
// Constructor.
public NewFrame (int width, int height, String[] words, int fontsize)
{
// Set the title and other frame parameters.
this.setTitle ("Font metrics");
this.setResizable (true);
this.setSize (width, height);
// Create and add the panel.
NewPanel panel = new NewPanel (words, fontsize);
this.getContentPane().add (panel);
// Show the frame.
this.setVisible (true);
}
} // End of class "NewFrame"
public class TestSwing12 {
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 (750, 200, testwords, 35);
}
}
Note:
(The window size may be changed.)
Dimension D = this.getSize ();
int startx = 0;
int y = 0 + fontheight;
NewFrame nf = new NewFrame (750, 200, testwords, 35);
Images
(Unisys holds the LZW patent).
public Image getImage (String filename);
public Image getImage (URL u);
import java.awt.*;
import javax.swing.*;
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (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 NewPanel
class NewFrame extends JFrame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Bugs");
this.setResizable (true);
this.setSize (width, height);
// Create and add the panel.
NewPanel panel = new NewPanel ();
this.getContentPane().add (panel);
// Show the frame.
this.setVisible (true);
}
} // End of class "NewFrame"
public class TestSwing13 {
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);
class NewPanel extends JPanel {
Image img;
public NewPanel ()
{
this.setBackground (Color.cyan);
// Get a Toolkit instance.
Toolkit tk = Toolkit.getDefaultToolkit ();
// Provide a filename to the getImage() method.
img = tk.getImage ("bugs.gif");
}
public void paintComponent (Graphics g)
{
super.paintComponent (g);
g.drawImage (img, 0, 0, this);
}
} // End of NewPanel
import java.awt.*;
import javax.swing.*;
import java.net.*; // For class URL.
// Extend JPanel to override paintComponent ()
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
public void paintComponent (Graphics g)
{
super.paintComponent (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/~drum/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);
}
}
} // End of NewPanel
class NewFrame extends JFrame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Gif image");
this.setResizable (true);
this.setSize (width, height);
// Create and add the panel.
NewPanel panel = new NewPanel ();
this.getContentPane().add (panel);
// Show the frame.
this.setVisible (true);
}
} // End of class "NewFrame"
public class TestSwing14 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (600, 300);
}
}
The result is:
URL u = new URL ("http://www.seas.gwu.edu/~drum/canyon.jpg");
Can you identify the person in the picture?
public boolean drawImage (Image img, int x, int y, int width,
int height, ImageObserver I);
public void paintComponent (Graphics g)
{
super.paintComponent (g);
Toolkit tk = Toolkit.getDefaultToolkit ();
try {
URL u = new URL ("http://www.seas.gwu.edu/~drum/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);
}
}
Interaction: buttons
import java.awt.*;
import javax.swing.*;
class NewFrame extends JFrame {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setSize (width, height);
// Extract the contentPane because we'll
// need to refer to it a couple of times.
Container cPane = this.getContentPane();
cPane.setBackground (Color.cyan);
// Create a Button instance and pass the button
// label as a parameter to the constructor.
JButton b = new JButton ("Quit");
// Set the layout manager for our Frame.
cPane.setLayout (new BorderLayout());
// Add the button to the frame.
cPane.add (b);
// Show the frame.
this.setVisible (true);
}
} // End of class "NewFrame"
public class TestSwing16 {
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 JButton extends AbstractButton implements Accessible {
// Constructors.
public JButton ();
public Button (String label);
public Button (Icon I);
public Button (String label, Icon I);
// Some important methods inherited from AbstractButton:
public void addActionListener (ActionListener a);
public String getText ();
public synchronized void setText (String label);
// ...
}
JButton b = new JButton ("Quit");
public Component add (Component c);
public void paintComponent (Graphics g)
{
super.paintComponent (g);
JButton b = new JButton ("QUIT");
// Add the button to the panel
this.add (b);
this.validate ();
}
public class TestSwing18 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
// Extract the contentPane because we'll
// need to refer to it a couple of times.
Container cPane = nf.getContentPane();
cPane.setBackground (Color.cyan);
// Create a Button instance and pass the button
// label as a parameter to the constructor.
JButton b = new JButton ("Quit");
b.setBackground (Color.cyan);
// Set the layout manager for our Frame.
cPane.setLayout (new BorderLayout());
// Add the button to the frame.
cPane.add (b);
nf.validate();
}
}
// Create a Button instance and pass the button
// label as a parameter to the constructor.
JButton b = new JButton ("Quit");
b.setBackground (Color.cyan);
// Set the layout manager for our Frame.
cPane.setLayout (new BorderLayout());
// Add the button to the frame.
cPane.add (b, BorderLayout.SOUTH);
// Show the frame.
this.setVisible (true);
This produces:
Note:
// Add five buttons at the different locations:
JButton b1 = new JButton ("South Quit");
b1.setBackground (Color.cyan);
b1.setForeground (Color.magenta);
cPane.add (b1, BorderLayout.SOUTH);
JButton b2 = new JButton ();
b2.setBackground (Color.red);
b2.setFont (new Font ("Serif", Font.PLAIN, 15));
b2.setText ("North Quit");
cPane.add (b2, BorderLayout.NORTH);
JButton b3 = new JButton ("<html> East <p> Quit </html>");
b3.setBackground (Color.blue);
cPane.add (b3, BorderLayout.EAST);
JButton b4 = new JButton ("West");
b4.setBackground (Color.green);
cPane.add (b4, BorderLayout.WEST);
JButton b5 = new JButton ("CENTER");
b5.setBackground (Color.yellow);
cPane.add (b5, BorderLayout.CENTER);
JButton b3 = new JButton ("<html> East <p> Quit </html>");
b2.setFont (new Font ("Serif", Font.PLAIN, 15));
b2.setText ("North Quit");
// Set the layout manager for our Frame.
cPane.setLayout (new FlowLayout());
// Add five buttons at the different locations:
JButton b1 = new JButton ("South Quit");
b1.setBackground (Color.cyan);
b1.setForeground (Color.magenta);
cPane.add (b1);
JButton b2 = new JButton ();
b2.setBackground (Color.red);
b2.setFont (new Font ("Serif", Font.PLAIN, 15));
b2.setText ("North Quit");
cPane.add (b2);
JButton b3 = new JButton ("<html> East <p> Quit </html>");
b3.setBackground (Color.blue);
cPane.add (b3);
JButton b4 = new JButton ("West");
b4.setBackground (Color.green);
cPane.add (b4);
JButton b5 = new JButton ("CENTER");
b5.setBackground (Color.yellow);
cPane.add (b5);
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener.
class NewFrame extends JFrame implements ActionListener {
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setSize (width, height);
Container cPane = this.getContentPane();
// Create a new button.
JButton b = new JButton ("<html> <b> Quit </b> </html>");
b.setBackground (Color.red);
// Add an ActionListener to the button.
b.addActionListener (this);
// BorderLayout is already the manager of the content pane
// but leave a comment as a reminder.
// cPane.setLayout (new BorderLayout());
// Add the button to the south of the frame.
cPane.add (b, BorderLayout.SOUTH);
// Show the frame.
this.setVisible (true);
}
// This method is required to implement the
// ActionListener interface.
public void actionPerformed (ActionEvent a)
{
System.out.println ("In actionPerformed");
// Button must have been pressed - so really quit.
System.exit (0);
}
} // End of class "NewFrame"
public class TestSwing22 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
Here is the result:
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 ("Refresh")) {
// Whatever...
}
}
Thus, you need to add lines to ActionPerformed() to
change the fontsize in the panel.
Then, you need to call repaint() at the end of
ActionPerformed. Finally, you need to implement
the method paintComponent (as we have done before) to actually
draw the string "Hello World!" in the desired size.
Explain where polymorphism was used in this example.
Interaction: mouse clicks
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);
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener.
class NewPanel extends JPanel {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
}
class NewFrame extends JFrame
implements ActionListener, MouseListener {
NewPanel panel;
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setSize (width, height);
Container cPane = this.getContentPane();
// cPane.setLayout (new BorderLayout());
// The panel for drawing.
panel = new NewPanel ();
cPane.add (panel, BorderLayout.CENTER);
// Add mouse-listening to panel.
panel.addMouseListener (this);
// Create a quit button.
JButton b = new JButton ("Quit");
b.setBackground (Color.red);
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
b.addActionListener (this);
cPane.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);
}
// These methods are required to implement
// the MouseListener interface.
int currentX=0, currentY=0;
public void mouseClicked (MouseEvent m)
{
System.out.println ("mouseClicked event: " + m.paramString());
int x = m.getX();
int y = m.getY();
Graphics g = panel.getGraphics();
g.drawLine (currentX, currentY, x, y);
currentX = x;
currentY = 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 TestSwing23 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
The result (after a few random mouse clicks):
panel.add ( /* mouse listener */ );
// Add mouse-listening to the frame itself.
panel.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 (currentX, currentY, x, y);
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener.
class NewPanel extends JPanel implements MouseListener {
public NewPanel ()
{
this.setBackground (Color.cyan);
}
// These methods are required to implement
// the MouseListener interface.
int currentX=0, currentY=0;
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 (currentX, currentY, x, y);
currentX = x;
currentY = 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) {}
}
class NewFrame extends JFrame
implements ActionListener {
NewPanel panel;
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setSize (width, height);
Container cPane = this.getContentPane();
// cPane.setLayout (new BorderLayout());
// The panel for drawing.
panel = new NewPanel ();
cPane.add (panel, BorderLayout.CENTER);
// Add panel's mouse-listening to panel.
panel.addMouseListener (panel);
// Create a quit button.
JButton b = new JButton ("Quit");
b.setBackground (Color.red);
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
b.addActionListener (this);
cPane.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 TestSwing24 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
Note:
public NewPanel ()
{
this.setBackground (Color.cyan);
// Make the panel the listener for the panel.
this.addMouseListener (this);
}
Panels as containers
Thus, this is what we want to observe:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener.
class NewPanel extends JPanel implements MouseListener {
Color drawColor = Color.green; // Default color.
public NewPanel ()
{
this.setBackground (Color.white);
// Add panel's mouse-listening to panel.
this.addMouseListener (this);
}
// These methods are required to implement
// the MouseListener interface.
int currentX=0, currentY=0;
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.setColor (drawColor);
g.drawLine (currentX, currentY, x, y);
currentX = x;
currentY = 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) {}
public void setDrawingColor (Color c)
{
this.drawColor = c;
}
}
class NewFrame extends JFrame
implements ActionListener {
NewPanel drawPanel;
// Constructor.
public NewFrame (int width, int height)
{
// Set the title and other frame parameters.
this.setTitle ("Button example");
this.setResizable (true);
this.setSize (width, height);
Container cPane = this.getContentPane();
// cPane.setLayout (new BorderLayout());
// The panel for drawing.
drawPanel = new NewPanel ();
cPane.add (drawPanel, BorderLayout.CENTER);
// Create a quit button.
JButton b = new JButton ("Quit");
b.setBackground (Color.red);
b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
b.addActionListener (this);
cPane.add (b, BorderLayout.SOUTH);
// Use a panel for clear and start buttons.
JPanel topPanel = new JPanel ();
topPanel.setLayout (new FlowLayout());
cPane.add (topPanel, BorderLayout.NORTH);
// Now insert the color buttons.
JButton orangeB = new JButton ("Orange");
orangeB.setBackground (Color.orange);
orangeB.addActionListener (this);
topPanel.add (orangeB);
JButton greenB = new JButton ("Green");
greenB.setBackground (Color.green);
greenB.addActionListener (this);
topPanel.add (greenB);
// Show the frame.
this.setVisible (true);
}
// This method is required to implement the
// ActionListener interface.
public void actionPerformed (ActionEvent a)
{
String label = a.getActionCommand();
if (label.equalsIgnoreCase ("Quit"))
System.exit (0);
else if (label.equalsIgnoreCase ("Orange"))
drawPanel.setDrawingColor (Color.orange);
else if (label.equalsIgnoreCase ("Green"))
drawPanel.setDrawingColor (Color.green);
}
} // End of class "NewFrame"
public class TestSwing25 {
public static void main (String[] argv)
{
NewFrame nf = new NewFrame (300, 200);
}
}
In-Class Exercise 9.8:
Run the above code and compare it with the picture before the
code? Fix the code so that it is compatible with the picture.
Next, use a BorderLayout for the top-panel instead
of its FlowLayout and report what you observe.
class NewPanel extends JPanel implements MouseListener {
Color drawColor = Color.green; // Default color.
// ...
}
Graphics g = this.getGraphics();
g.setColor (drawColor);
g.drawLine (currentX, currentY, x, y);
class NewPanel extends JPanel implements MouseListener {
// ...
public void setDrawingColor (Color c)
{
this.drawColor = c;
}
}
public void actionPerformed (ActionEvent a)
{
String label = a.getActionCommand();
if (label.equalsIgnoreCase ("Quit"))
System.exit (0);
else if (label.equalsIgnoreCase ("Orange"))
drawPanel.setDrawingColor (Color.orange);
else if (label.equalsIgnoreCase ("Green"))
drawPanel.setDrawingColor (Color.green);
}
drawPanel = new NewPanel ();
cPane.add (drawPanel, BorderLayout.CENTER);
and one to serve as a container:
JPanel topPanel = new JPanel ();
topPanel.setLayout (new FlowLayout());
cPane.add (topPanel, BorderLayout.NORTH);
// ...
topPanel.add (orangeB);
// ...
topPanel.add (greenB);
JPanel topPanel = new JPanel ();
// topPanel.setLayout (new FlowLayout());
cPane.add (topPanel, BorderLayout.NORTH);
The methods paintComponent()
and repaint()
(Unless you are an "expert" designing your own components.)
Applets - a first look
<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, orangeB, greenB;
Panel p;
Canvas c;
int currentX = 0, currentY = 0;
Color currentColor = Color.green;
// Applet's equivalent of constructor.
public void init()
{
// Title and size cannot be set in an applet.
this.setBackground (Color.cyan);
// Create a quit button: using AWT's 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 using java.awt.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());
p.setBackground (Color.white);
// Create a clear button.
orangeB = new Button ("Orange");
orangeB.addActionListener (this);
orangeB.setBackground (Color.orange);
// Create a start button.
greenB = new Button ("Green");
greenB.addActionListener (this);
greenB.setBackground (Color.green);
// Add start and clear buttons to panel.
p.add (orangeB);
p.add (greenB);
// 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 ("Orange")) {
currentColor = Color.orange;
}
else if (s.equalsIgnoreCase ("Green")) {
currentColor = Color.green;
}
}
// These methods are required to implement
// the MouseListener interface.
public void mouseClicked (MouseEvent m)
{
int x = m.getX();
int y = m.getY();
Graphics g = c.getGraphics();
g.setColor (currentColor);
g.drawLine (currentX, currentY, x, y);
currentX = x;
currentY = 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 "TestApplet"
% appletviewer TestApplet.html
This produces a window containing the applet. For example,
here is what we get after a few mouse-clicks: