- •CONTENTS
- •1.1 Introduction
- •1.2 What Is a Computer?
- •1.3 Programs
- •1.4 Operating Systems
- •1.5 Java, World Wide Web, and Beyond
- •1.6 The Java Language Specification, API, JDK, and IDE
- •1.7 A Simple Java Program
- •1.8 Creating, Compiling, and Executing a Java Program
- •1.9 (GUI) Displaying Text in a Message Dialog Box
- •2.1 Introduction
- •2.2 Writing Simple Programs
- •2.3 Reading Input from the Console
- •2.4 Identifiers
- •2.5 Variables
- •2.7 Named Constants
- •2.8 Numeric Data Types and Operations
- •2.9 Problem: Displaying the Current Time
- •2.10 Shorthand Operators
- •2.11 Numeric Type Conversions
- •2.12 Problem: Computing Loan Payments
- •2.13 Character Data Type and Operations
- •2.14 Problem: Counting Monetary Units
- •2.15 The String Type
- •2.16 Programming Style and Documentation
- •2.17 Programming Errors
- •2.18 (GUI) Getting Input from Input Dialogs
- •3.1 Introduction
- •3.2 boolean Data Type
- •3.3 Problem: A Simple Math Learning Tool
- •3.4 if Statements
- •3.5 Problem: Guessing Birthdays
- •3.6 Two-Way if Statements
- •3.7 Nested if Statements
- •3.8 Common Errors in Selection Statements
- •3.9 Problem: An Improved Math Learning Tool
- •3.10 Problem: Computing Body Mass Index
- •3.11 Problem: Computing Taxes
- •3.12 Logical Operators
- •3.13 Problem: Determining Leap Year
- •3.14 Problem: Lottery
- •3.15 switch Statements
- •3.16 Conditional Expressions
- •3.17 Formatting Console Output
- •3.18 Operator Precedence and Associativity
- •3.19 (GUI) Confirmation Dialogs
- •4.1 Introduction
- •4.2 The while Loop
- •4.3 The do-while Loop
- •4.4 The for Loop
- •4.5 Which Loop to Use?
- •4.6 Nested Loops
- •4.7 Minimizing Numeric Errors
- •4.8 Case Studies
- •4.9 Keywords break and continue
- •4.10 (GUI) Controlling a Loop with a Confirmation Dialog
- •5.1 Introduction
- •5.2 Defining a Method
- •5.3 Calling a Method
- •5.4 void Method Example
- •5.5 Passing Parameters by Values
- •5.6 Modularizing Code
- •5.7 Problem: Converting Decimals to Hexadecimals
- •5.8 Overloading Methods
- •5.9 The Scope of Variables
- •5.10 The Math Class
- •5.11 Case Study: Generating Random Characters
- •5.12 Method Abstraction and Stepwise Refinement
- •6.1 Introduction
- •6.2 Array Basics
- •6.3 Problem: Lotto Numbers
- •6.4 Problem: Deck of Cards
- •6.5 Copying Arrays
- •6.6 Passing Arrays to Methods
- •6.7 Returning an Array from a Method
- •6.8 Variable-Length Argument Lists
- •6.9 Searching Arrays
- •6.10 Sorting Arrays
- •6.11 The Arrays Class
- •7.1 Introduction
- •7.2 Two-Dimensional Array Basics
- •7.3 Processing Two-Dimensional Arrays
- •7.4 Passing Two-Dimensional Arrays to Methods
- •7.5 Problem: Grading a Multiple-Choice Test
- •7.6 Problem: Finding a Closest Pair
- •7.7 Problem: Sudoku
- •7.8 Multidimensional Arrays
- •8.1 Introduction
- •8.2 Defining Classes for Objects
- •8.3 Example: Defining Classes and Creating Objects
- •8.4 Constructing Objects Using Constructors
- •8.5 Accessing Objects via Reference Variables
- •8.6 Using Classes from the Java Library
- •8.7 Static Variables, Constants, and Methods
- •8.8 Visibility Modifiers
- •8.9 Data Field Encapsulation
- •8.10 Passing Objects to Methods
- •8.11 Array of Objects
- •9.1 Introduction
- •9.2 The String Class
- •9.3 The Character Class
- •9.4 The StringBuilder/StringBuffer Class
- •9.5 Command-Line Arguments
- •9.6 The File Class
- •9.7 File Input and Output
- •9.8 (GUI) File Dialogs
- •10.1 Introduction
- •10.2 Immutable Objects and Classes
- •10.3 The Scope of Variables
- •10.4 The this Reference
- •10.5 Class Abstraction and Encapsulation
- •10.6 Object-Oriented Thinking
- •10.7 Object Composition
- •10.8 Designing the Course Class
- •10.9 Designing a Class for Stacks
- •10.10 Designing the GuessDate Class
- •10.11 Class Design Guidelines
- •11.1 Introduction
- •11.2 Superclasses and Subclasses
- •11.3 Using the super Keyword
- •11.4 Overriding Methods
- •11.5 Overriding vs. Overloading
- •11.6 The Object Class and Its toString() Method
- •11.7 Polymorphism
- •11.8 Dynamic Binding
- •11.9 Casting Objects and the instanceof Operator
- •11.11 The ArrayList Class
- •11.12 A Custom Stack Class
- •11.13 The protected Data and Methods
- •11.14 Preventing Extending and Overriding
- •12.1 Introduction
- •12.2 Swing vs. AWT
- •12.3 The Java GUI API
- •12.4 Frames
- •12.5 Layout Managers
- •12.6 Using Panels as Subcontainers
- •12.7 The Color Class
- •12.8 The Font Class
- •12.9 Common Features of Swing GUI Components
- •12.10 Image Icons
- •13.1 Introduction
- •13.2 Exception-Handling Overview
- •13.3 Exception-Handling Advantages
- •13.4 Exception Types
- •13.5 More on Exception Handling
- •13.6 The finally Clause
- •13.7 When to Use Exceptions
- •13.8 Rethrowing Exceptions
- •13.9 Chained Exceptions
- •13.10 Creating Custom Exception Classes
- •14.1 Introduction
- •14.2 Abstract Classes
- •14.3 Example: Calendar and GregorianCalendar
- •14.4 Interfaces
- •14.5 Example: The Comparable Interface
- •14.6 Example: The ActionListener Interface
- •14.7 Example: The Cloneable Interface
- •14.8 Interfaces vs. Abstract Classes
- •14.9 Processing Primitive Data Type Values as Objects
- •14.10 Sorting an Array of Objects
- •14.11 Automatic Conversion between Primitive Types and Wrapper Class Types
- •14.12 The BigInteger and BigDecimal Classes
- •14.13 Case Study: The Rational Class
- •15.1 Introduction
- •15.2 Graphical Coordinate Systems
- •15.3 The Graphics Class
- •15.4 Drawing Strings, Lines, Rectangles, and Ovals
- •15.5 Case Study: The FigurePanel Class
- •15.6 Drawing Arcs
- •15.7 Drawing Polygons and Polylines
- •15.8 Centering a String Using the FontMetrics Class
- •15.9 Case Study: The MessagePanel Class
- •15.10 Case Study: The StillClock Class
- •15.11 Displaying Images
- •15.12 Case Study: The ImageViewer Class
- •16.1 Introduction
- •16.2 Event and Event Source
- •16.3 Listeners, Registrations, and Handling Events
- •16.4 Inner Classes
- •16.5 Anonymous Class Listeners
- •16.6 Alternative Ways of Defining Listener Classes
- •16.7 Problem: Loan Calculator
- •16.8 Window Events
- •16.9 Listener Interface Adapters
- •16.10 Mouse Events
- •16.11 Key Events
- •16.12 Animation Using the Timer Class
- •17.1 Introduction
- •17.2 Buttons
- •17.3 Check Boxes
- •17.4 Radio Buttons
- •17.5 Labels
- •17.6 Text Fields
- •17.7 Text Areas
- •17.8 Combo Boxes
- •17.9 Lists
- •17.10 Scroll Bars
- •17.11 Sliders
- •17.12 Creating Multiple Windows
- •18.1 Introduction
- •18.2 Developing Applets
- •18.3 The HTML File and the <applet> Tag
- •18.4 Applet Security Restrictions
- •18.5 Enabling Applets to Run as Applications
- •18.6 Applet Life-Cycle Methods
- •18.7 Passing Strings to Applets
- •18.8 Case Study: Bouncing Ball
- •18.9 Case Study: TicTacToe
- •18.10 Locating Resources Using the URL Class
- •18.11 Playing Audio in Any Java Program
- •18.12 Case Study: Multimedia Animations
- •19.1 Introduction
- •19.2 How is I/O Handled in Java?
- •19.3 Text I/O vs. Binary I/O
- •19.4 Binary I/O Classes
- •19.5 Problem: Copying Files
- •19.6 Object I/O
- •19.7 Random-Access Files
- •20.1 Introduction
- •20.2 Problem: Computing Factorials
- •20.3 Problem: Computing Fibonacci Numbers
- •20.4 Problem Solving Using Recursion
- •20.5 Recursive Helper Methods
- •20.6 Problem: Finding the Directory Size
- •20.7 Problem: Towers of Hanoi
- •20.8 Problem: Fractals
- •20.9 Problem: Eight Queens
- •20.10 Recursion vs. Iteration
- •20.11 Tail Recursion
- •APPENDIXES
- •INDEX
16.4 Inner Classes 541
43repaint();
44}
45
46/** Repaint the circle */
47protected void paintComponent(Graphics g) {
48super.paintComponent(g);
49g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
502 * radius, 2 * radius);
51}
52}
53}
Similarly you can add the code for the Shrink button to display a smaller circle when the the Shrink button Shrink button is clicked.
16.4 Inner Classes
An inner class, or nested class, is a class defined within the scope of another class. The code in Figure 16.7(a) defines two separate classes, Test and A. The code in Figure 16.7(b) defines A as an inner class in Test.
public class Test {
...
}
public class A {
...
}
(a)
public class Test {
...
// Inner class
public class A {
...
}
}
(b)
// OuterClass.java: inner class demo public class OuterClass {
private int data;
/** A method in the outer class */ public void m() {
// Do something
}
// An inner class class InnerClass {
/** A method in the inner class */ public void mi() {
//Directly reference data and method
//defined in its outer class data++;
m();
}
}
}
(c)
FIGURE 16.7 Inner classes combine dependent classes into the primary class.
The class InnerClass defined inside OuterClass in Figure 16.7(c) is another example of an inner class. An inner class may be used just like a regular class. Normally, you define a class an inner class if it is used only by its outer class. An inner class has the following features:
■An inner class is compiled into a class named OuterClassName$InnerClassName.class. For example, the inner class A in Test is compiled into Test$A.class in Figure 16.7(b).
■An inner class can reference the data and methods defined in the outer class in which it nests, so you need not pass the reference of an object of the outer class to the constructor of the inner class. For this reason, inner classes can make programs simple and concise.
■An inner class can be defined with a visibility modifier subject to the same visibility rules applied to a member of the class.
542Chapter 16 Event-Driven Programming
■An inner class can be defined static. A static inner class can be accessed using the outer class name. A static inner class cannot access nonstatic members of the outer class.
■Objects of an inner class are often created in the outer class. But you can also create an object of an inner class from another class. If the inner class is nonstatic, you must first create an instance of the outer class, then use the following syntax to create an object for the inner class:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
■ If the inner class is static, use the following syntax to create an object for it:
OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
A simple use of inner classes is to combine dependent classes into a primary class. This reduces the number of source files. It also makes class files easy to organize, since they are all named with the primary class as the prefix. For example, rather than creating two source files, Test.java and A.java, in Figure 16.7(a), you can combine class A into class Test and create just one source file Test.java in Figure 16.7(b). The resulting class files are Test.class and
Test$A.class.
Another practical use of inner classes is to avoid class-naming conflict. Two versions of CirclePanel are defined in Listings 16.1 and 16.2. You can define them as inner classes to avoid conflict.
16.5 Anonymous Class Listeners
A listener class is designed specifically to create a listener object for a GUI component (e.g., a button). The listener class will not be shared by other applications and therefore is appropriate to be defined inside the frame class as an inner class.
anonymous inner class Inner-class listeners can be shortened using anonymous inner classes. An anonymous inner class is an inner class without a name. It combines defining an inner class and creating an instance of the class in one step. The inner class in Listing 16.2 can be replaced by an anonymous inner class as shown below.
public ControlCircle2() {
// Omitted
jbtEnlarge.addActionListener( new EnlargeListener() );
}
class EnlargeListener implements ActionListener {
public void actionPerformed(ActionEvent e) { canvas.enlarge();
}
}
(a) Inner class EnlargeListener
public ControlCircle2() { // Omitted
jbtEnlarge.addActionListener( new class EnlargeListener
implements ActionListener() { public void
actionPerformed(ActionEvent e) { canvas.enlarge();
}
});
}
(b) Anonymous inner class
The syntax for an anonymous inner class is as follows:
new SuperClassName/InterfaceName() {
//Implement or override methods in superclass or interface
//Other methods if necessary
}
16.5 Anonymous Class Listeners 543
Since an anonymous inner class is a special kind of inner class, it is treated like an inner class with the following features:
■An anonymous inner class must always extend a superclass or implement an interface, but it cannot have an explicit extends or implements clause.
■An anonymous inner class must implement all the abstract methods in the superclass or in the interface.
■An anonymous inner class always uses the no-arg constructor from its superclass to create an instance. If an anonymous inner class implements an interface, the constructor is Object().
■An anonymous inner class is compiled into a class named OuterClassName$n.class. For example, if the outer class Test has two anonymous inner classes, they are compiled into Test$1.class and Test$2.class.
Listing 16.3 gives an example that handles the events from four buttons, as shown in Figure 16.8.
FIGURE 16.8 The program handles the events from four buttons.
LISTING 16.3 AnonymousListenerDemo.java
1 import javax.swing.*;
2 import java.awt.event.*;
3
4 public class AnonymousListenerDemo extends JFrame {
5 public AnonymousListenerDemo() {
6// Create four buttons
7JButton jbtNew = new JButton("New");
8 JButton jbtOpen = new JButton("Open");
9 JButton jbtSave = new JButton("Save");
10 JButton jbtPrint = new JButton("Print");
11
12// Create a panel to hold buttons
13JPanel panel = new JPanel();
14panel.add(jbtNew);
15panel.add(jbtOpen);
16panel.add(jbtSave);
17panel.add(jbtPrint);
18
19 add(panel);
20
21// Create and register anonymous inner-class listener
22jbtNew.addActionListener(
23new ActionListener() {
24public void actionPerformed(ActionEvent e) {
25System.out.println("Process New");
26}
27}
28);
Video Note
Anonymous listener
anonymous listener handle event
544 Chapter 16 Event-Driven Programming
29
30jbtOpen.addActionListener(
31new ActionListener() {
32public void actionPerformed(ActionEvent e) {
33System.out.println("Process Open");
34}
35}
36);
37
38jbtSave.addActionListener(
39new ActionListener() {
40public void actionPerformed(ActionEvent e) {
41System.out.println("Process Save");
42}
43}
44);
45
46jbtPrint.addActionListener(
47new ActionListener() {
48public void actionPerformed(ActionEvent e) {
49System.out.println("Process Print");
50}
51}
52);
53}
54
55/** Main method */
56public static void main(String[] args) {
57JFrame frame = new AnonymousListenerDemo();
58frame.setTitle("AnonymousListenerDemo");
59frame.setLocationRelativeTo(null); // Center the frame
60frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
61frame.pack();
62frame.setVisible(true);
63}
64}
The program creates four listeners using anonymous inner classes (lines 22–52). Without using anonymous inner classes, you would have to create four separate classes. An anonymous listener works the same way as an inner class listener. The program is condensed using an anonymous inner class.
Anonymous inner classes are compiled into OuterClassName$#.class, where # starts at 1 and is incremented for each anonymous class the compiler encounters. In this example, the anonymous inner class is compiled into AnonymousListenerDemo$1.class,
AnonymousListenerDemo$2.class, AnonymousListenerDemo$3.class,and AnonymousListenerDemo$4.class.
Instead of using the setSize method to set the size for the frame, the program uses the pack() pack() method (line 61), which automatically sizes the frame according to the size of the
components placed in it.
16.6 Alternative Ways of Defining Listener Classes
There are many other ways to define the listener classes. For example, you may rewrite Listing 16.3 by creating just one listener, register the listener with the buttons, and let the listener detect the event source—i.e., which button fires the event—as shown in Listing 16.4.
16.6 Alternative Ways of Defining Listener Classes 545
LISTING 16.4 DetectSourceDemo.java
1 import javax.swing.*;
2 import java.awt.event.*;
3
4 public class DetectSourceDemo extends JFrame {
5// Create four buttons
6 private JButton jbtNew = new JButton("New");
7 private JButton jbtOpen = new JButton("Open");
8 private JButton jbtSave = new JButton("Save");
9 private JButton jbtPrint = new JButton("Print");
10
11public DetectSourceDemo() {
12// Create a panel to hold buttons
13JPanel panel = new JPanel();
14panel.add(jbtNew);
15panel.add(jbtOpen);
16panel.add(jbtSave);
17panel.add(jbtPrint);
18 |
|
|
19 |
add(panel); |
|
20 |
|
|
21 |
// Create a listener |
|
22 |
ButtonListener listener = new ButtonListener(); |
create listener |
23 |
|
|
24 |
// Register listener with buttons |
|
25 |
jbtNew.addActionListener(listener); |
register listener |
26jbtOpen.addActionListener(listener);
27jbtSave.addActionListener(listener);
28jbtPrint.addActionListener(listener);
29}
30 |
|
|
31 |
class ButtonListener implements ActionListener { |
listener class |
32 |
public void actionPerformed(ActionEvent e) { |
handle event |
33if (e.getSource() == jbtNew)
34System.out.println("Process New");
35else if (e.getSource() == jbtOpen)
36System.out.println("Process Open");
37else if (e.getSource() == jbtSave)
38System.out.println("Process Save");
39else if (e.getSource() == jbtPrint)
40System.out.println("Process Print");
41}
42}
43
44/** Main method */
45public static void main(String[] args) {
46JFrame frame = new DetectSourceDemo();
47frame.setTitle("DetectSourceDemo");
48frame.setLocationRelativeTo(null); // Center the frame
49frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
50frame.pack();
51frame.setVisible(true);
52}
53}
546 Chapter 16 Event-Driven Programming
This program defines just one inner listener class (lines 31–42), creates a listener from the class (line 22), and registers it to four buttons (lines 25–28). When a button is clicked, the button fires an ActionEvent and invokes the listener’s actionPerformed method. The actionPerformed method checks the source of the event using the getSource() method for the event (lines 33, 35, 37, 39) and determines which button fired the event.
You may also rewrite Listing 16.3 by defining the custom frame class that implements ActionListener, as shown in Listing 16.5.
LISTING 16.5 FrameAsListenerDemo.java
|
1 |
import javax.swing.*; |
|||||
|
2 |
import java.awt.event.*; |
|||||
|
3 |
|
|
|
|
|
|
|
4 |
public class FrameAsListenerDemo extends JFrame |
|||||
implement ActionListener |
5 |
|
|
implements ActionListener |
{ |
||
|
6 |
|
// Create four buttons |
||||
|
7 |
|
private JButton jbtNew = new JButton("New"); |
||||
|
8 |
|
private JButton jbtOpen = new JButton("Open"); |
||||
|
9 |
|
private JButton jbtSave = new JButton("Save"); |
||||
|
10 |
|
private JButton jbtPrint = new JButton("Print"); |
||||
|
11 |
|
|
|
|
|
|
|
12 |
|
public FrameAsListenerDemo() { |
||||
|
13 |
|
|
// Create a panel to hold buttons |
|||
|
14 |
|
|
JPanel panel = new JPanel(); |
|||
|
15 |
|
|
panel.add(jbtNew); |
|||
|
16 |
|
|
panel.add(jbtOpen); |
|||
|
17 |
|
|
panel.add(jbtSave); |
|||
|
18 |
|
|
panel.add(jbtPrint); |
|||
|
19 |
|
|
|
|
|
|
|
20 |
|
|
add(panel); |
|||
|
21 |
|
|
|
|
|
|
|
22 |
|
|
// Register listener with buttons |
|||
register listeners |
23 |
|
|
jbtNew.addActionListener(this); |
|
||
|
24 |
|
|
jbtOpen.addActionListener(this); |
|||
|
25 |
|
|
jbtSave.addActionListener(this); |
|||
|
26 |
|
|
jbtPrint.addActionListener(this); |
|||
|
27 |
} |
|
|
|
|
|
|
28 |
|
|
|
|
|
|
|
29 |
|
/** Implement actionPerformed */ |
||||
handle event |
30 |
|
public void actionPerformed(ActionEvent e) { |
|
|||
|
31 |
|
|
if (e.getSource() == jbtNew) |
|||
|
32 |
|
|
System.out.println("Process New"); |
|||
|
33 |
|
|
else if (e.getSource() == jbtOpen) |
|||
|
34 |
|
|
System.out.println("Process Open"); |
|||
|
35 |
|
|
else if (e.getSource() == jbtSave) |
|||
|
36 |
|
|
System.out.println("Process Save"); |
|||
|
37 |
|
|
else if (e.getSource() == jbtPrint) |
|||
|
38 |
|
|
System.out.println("Process Print"); |
|||
|
39 |
} |
|
|
|
|
|
|
40 |
|
|
|
|
|
|
|
41 |
|
/** Main method */ |
||||
|
42 |
|
public static void main(String[] args) { |
||||
|
43 |
|
|
JFrame frame = new FrameAsListenerDemo(); |
|||
|
44 |
|
|
frame.setTitle("FrameAsListenerDemo"); |
|||
|
45 |
|
|
frame.setLocationRelativeTo(null); // Center the frame |
|||
|
46 |
|
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
|||
|
47 |
|
|
frame.pack(); |
|||
|
48 |
|
|
frame.setVisible(true); |
|||
|
49 |
} |
|
|
|
|
|
|
50 |
} |
|
|
|
|
|