Java 8 Programming Black Book
Java 8 Programming Black Book
Programming
AWT Controls, Swing Controls,
File and I/O Handling, Threading, Networking,
Java Beans, JDBC, Security, Packages,
Annotations Lambda expressions,
NIO, Java DB, Java FX
Black Book
TM
Authored by:
DT Editorial
Services
Published by:
Copyright 2015 by Dreamtech Press, 19-A, Ansari Road, Daryaganj, New Delhi-110002
Black Book is a trademark of Paraglyph Press Inc., 2246 E. Myrtle Avenue, Phoenix Arizona 85202,
USA exclusively licensed in Indian, Asian and African continent to Dreamtech Press, India.
This book may not be duplicated in any way without the express written consent of the publisher,
except in the form of brief excerpts or quotations for the purposes of review. The information
contained herein is for the personal use of the reader and may not be incorporated in any
commercial programs, other books, databases, or any kind of software without written consent of
the publisher. Making copies of this book or any portion for any purpose other than your own is a
violation of copyright laws.
Limits of Liability/disclaimer of Warranty: The author and publisher have used their best
efforts in preparing this book. The author make no representation or warranties with respect to
the accuracy or completeness of the contents of this book, and specifically disclaim any implied
warranties of merchantability or fitness of any particular purpose. There are no warranties which
extend beyond the descriptions contained in this paragraph. No warranty may be created or
extended by sales representatives or written sales materials. The accuracy and completeness of
the information provided herein and the opinions stated herein are not guaranteed or warranted
to produce any particulars results, and the advice and strategies contained herein may not be
suitable for every individual. Neither Dreamtech Press nor author shall be liable for any loss of
profit or any other commercial damages, including but not limited to special, incidental,
consequential, or other damages.
Trademarks: All brand names and product names used in this book are trademarks, registered
trademarks, or trade names of their respective holders. Dreamtech Press is not associated with any
product or vendor mentioned in this book.
ISBN: 978-93-5119-758-4
Edition: 2015
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts ............ 215
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes ....................... 245
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel .......................... 351
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees ....................... 443
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts................... 521
Contents at a Glance
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes............... 579
Chapter 18: Working with Streams, Files, and I/O Handling ................................................. 615
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations ............................. 823
Chapter 2: Java and XMLUsing the Simple API for XML ...................................................... 31
iv
Table of Contents
Introduction .......................................................................................................................... xxxiii
vi
Table of Contents
vii
Table of Contents
viii
Table of Contents
ix
Table of Contents
x
Table of Contents
xi
Table of Contents
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts ............ 215
In Depth .............................................................................................................................. 216
Text Fields .......................................................................................................................................................................... 216
Buttons ................................................................................................................................................................................ 216
Checkboxes ........................................................................................................................................................................ 216
Radio Buttons .................................................................................................................................................................... 216
Layouts ............................................................................................................................................................................... 216
Immediate Solutions .......................................................................................................... 218
Using Text Fields ............................................................................................................................................................... 218
Using Labels ....................................................................................................................................................................... 220
Using Buttons .................................................................................................................................................................... 221
Using Checkboxes ............................................................................................................................................................. 224
Using Radio Buttons ......................................................................................................................................................... 227
Layout Managers ............................................................................................................................................................... 228
Flow Layouts ..................................................................................................................................................................... 228
Grid Layouts ...................................................................................................................................................................... 231
Using Panels....................................................................................................................................................................... 232
Border Layouts .................................................................................................................................................................. 234
Card Layouts ..................................................................................................................................................................... 236
Grid Bag Layouts............................................................................................................................................................... 238
Using Insets and Padding ................................................................................................................................................ 243
xii
Table of Contents
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes ....................... 245
In Depth .............................................................................................................................. 246
Lists ..................................................................................................................................................................................... 246
Choices................................................................................................................................................................................ 246
Text Areas .......................................................................................................................................................................... 246
Scroll bars ........................................................................................................................................................................... 246
Scroll Panes ........................................................................................................................................................................ 247
Immediate Solutions .......................................................................................................... 248
Using Text Areas ............................................................................................................................................................... 248
Replacing Text in Text Areas ........................................................................................................................................... 251
Searching and Selecting Text in Text Areas ................................................................................................................... 252
Using Lists .......................................................................................................................................................................... 253
Using Multiple-Selection Lists ......................................................................................................................................... 257
Using Choice Controls ...................................................................................................................................................... 260
Using Scroll bars ................................................................................................................................................................ 265
Scroll bars and Border Layouts ....................................................................................................................................... 269
Using Scroll Panes ............................................................................................................................................................. 272
Summary ............................................................................................................................................................................ 274
xiii
Table of Contents
xiv
Table of Contents
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel .......................... 351
In Depth .............................................................................................................................. 352
The Java Foundation Classes ........................................................................................................................................... 352
Swing .................................................................................................................................................................................. 353
Heavyweight versus Lightweight Components............................................................................................................ 354
Swing Features .................................................................................................................................................................. 355
Graphics Programming Using Panes .............................................................................................................................. 356
Model View Controller Architecture .............................................................................................................................. 356
Immediate Solutions .......................................................................................................... 358
Working with Swing ......................................................................................................................................................... 358
Preparing to Create a Swing Applet ............................................................................................................................... 364
Understanding Root Panes ........................................................................................................................................... 366
Understanding Layered Panes ..................................................................................................................................... 368
Understanding Content Panes ......................................................................................................................................... 370
Working with Content Panes ....................................................................................................................................... 370
Creating a Swing Applet .................................................................................................................................................. 372
Painting in Swing vs. AWT........................................................................................................................................... 372
Displaying Controls in Swing Vs AWT ...................................................................................................................... 372
Using the JPanel Class .................................................................................................................................................. 373
Creating a Swing Application.......................................................................................................................................... 374
Closing JFrame Windows ................................................................................................................................................ 377
Using Insets for Selecting Component Borders ............................................................................................................. 379
Using Insets .................................................................................................................................................................... 381
The Synth Skinnable Look and Feel ................................................................................................................................ 383
The Pluggable Look and Feel........................................................................................................................................... 386
The Pluggable Look and Feel for Components ............................................................................................................. 390
The Nimbus Look and Feel .............................................................................................................................................. 392
Summary ............................................................................................................................................................................ 394
xv
Table of Contents
xvi
Table of Contents
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees ....................... 443
In Depth .............................................................................................................................. 445
Viewports ........................................................................................................................................................................... 445
Scroll Panes ........................................................................................................................................................................ 445
Sliders ................................................................................................................................................................................. 445
Scrollbars ............................................................................................................................................................................ 445
Lists ..................................................................................................................................................................................... 445
Tables .................................................................................................................................................................................. 445
Trees .................................................................................................................................................................................... 446
Immediate Solutions .......................................................................................................... 447
Handling Viewports ......................................................................................................................................................... 447
Creating Scroll Panes ........................................................................................................................................................ 450
Creating Scroll Pane Headers and Borders .................................................................................................................... 454
Scrolling Images ................................................................................................................................................................ 455
Creating Sliders ................................................................................................................................................................. 456
Filling a Slider .................................................................................................................................................................... 459
Painting Slider Tick Marks ............................................................................................................................................... 460
Painting Slider Labels ....................................................................................................................................................... 460
Setting the Slider Extent ................................................................................................................................................... 461
Creating Scrollbars ............................................................................................................................................................ 462
Creating Lists ..................................................................................................................................................................... 465
Handling Multiple List Selections ................................................................................................................................... 469
List Selection Modes ...................................................................................................................................................... 469
Displaying Images in Lists ............................................................................................................................................... 470
Creating a Custom List Model ......................................................................................................................................... 471
Creating a Custom List Cell Renderer ............................................................................................................................ 472
Handling Double Clicks in Lists...................................................................................................................................... 472
Drag and Drop Support.................................................................................................................................................... 473
Creating a Table................................................................................................................................................................. 476
Table Sorting and Filtering............................................................................................................................................... 478
Sorting Rows................................................................................................................................................................... 478
xvii
Table of Contents
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts................... 521
In Depth .............................................................................................................................. 522
Layered Panes .................................................................................................................................................................... 522
Tabbed Panes ..................................................................................................................................................................... 522
xviii
Table of Contents
xix
Table of Contents
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes............... 579
In Depth .............................................................................................................................. 580
Windows ............................................................................................................................................................................ 580
Dialog Boxes ...................................................................................................................................................................... 580
Immediate Solutions .......................................................................................................... 581
Creating a Window ........................................................................................................................................................... 581
Designing Shaped and Translucent Windows .............................................................................................................. 583
Creating Translucent Windows ................................................................................................................................... 583
Creating Different Shaped Windows .......................................................................................................................... 587
Creating a Frame Window ............................................................................................................................................... 588
Creating a Desktop Pane .................................................................................................................................................. 589
Creating Internal Frames .................................................................................................................................................. 591
Using JOptionPane to Create Dialog Boxes ................................................................................................................... 598
Creating Option Pane Confirmation Dialog Boxes ....................................................................................................... 604
Creating Option Pane Message Dialog Boxes................................................................................................................ 605
Creating Option Pane Text Field Input Dialog Boxes................................................................................................... 606
Creating Option Pane Combo Box Input Dialog Boxes ................................................................................................ 608
Creating Option Pane Internal Frame Dialog Boxes ..................................................................................................... 609
Creating Dialog Boxes with JDialog ............................................................................................................................... 609
Getting Input from Dialog Boxes Created with JDialog ............................................................................................... 613
Summary ............................................................................................................................................................................ 614
Chapter 18: Working with Streams, Files, and I/O Handling ................................................. 615
In Depth .............................................................................................................................. 616
Streams, Readers, and Writers ......................................................................................................................................... 616
NIO...................................................................................................................................................................................... 616
Essentials in NIO ............................................................................................................................................................... 616
Buffers ............................................................................................................................................................................. 617
Charsets and Selectors ................................................................................................................................................... 620
Enhancements in NIO with Java 8 .................................................................................................................................. 620
The Path Interface .......................................................................................................................................................... 620
The Files Class................................................................................................................................................................ 622
The Paths Class .............................................................................................................................................................. 624
The File Attribute Interfaces ......................................................................................................................................... 625
xx
Table of Contents
xxi
Table of Contents
xxii
Table of Contents
xxiii
Table of Contents
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations ............................. 823
In Depth .............................................................................................................................. 824
Packages and Interfaces .................................................................................................................................................... 824
JAR Files ............................................................................................................................................................................. 824
The Core Java API Package .............................................................................................................................................. 824
The java.lang Package ....................................................................................................................................................... 826
The java.lang.annotation Subpackage ........................................................................................................................ 826
The java.lang.instrument Subpackage ....................................................................................................................... 826
The java.lang.management Subpackage .................................................................................................................... 826
The java.lang.reflect Subpackage ................................................................................................................................ 826
The java.lang.invoke Subpackage ............................................................................................................................... 827
The java.lang.ref Subpackage ...................................................................................................................................... 827
xxv
Table of Contents
xxvi
Table of Contents
xxvii
Table of Contents
xxviii
Table of Contents
xxix
Table of Contents
xxx
Table of Contents
xxxi
Table of Contents
Chapter 2: Java and XMLUsing the Simple API for XML ...................................................... 31
xxxii
Introduction
Thanks for buying the Java 8 Programming Black Book. The book covers Java 8 a 2014-released Java version in
a comprehensive and accessible manner.
Java is a programming language that all novice programmers are willing to learn for building applications. Here
this book helps by offering simple to complex Java programming concepts along with various programming
examples. You will find programs on all Java concepts, which are meant for easy assimilation of a concept.
With the evolution of Java 8, various new concepts emerged, which are also part of this book. Its each chapter
has been divided into In Depth and Immediate Solutions sections: where the In Depth section is about the
theoretical understanding of one concept, the Immediate Solutions section is about the practical implementation of
the same.
The most important feature of Java programming language is that it offers security; therefore, it is preferred over
other programming languages. As most system applications are written in this language, it is only better that
programmers be well versed with Java programming language.
Java Swing
Swings pluggable look and feel
All Swing components
Swing text components
Java collections
Multithreading
I/O Streams
File handling
Networking and sockets
Split panes, editor panes, text panes, and more
Trees and tables
Java Beans
MXBeans
Packages, interfaces, and JAR files
Java Server Pages (JSP)
Reading applets from JAR files
Security issues
Java Database Connectivity (JDBC)
Servlets
Java DB
Java FX
You will also come to know of some good online resources. In addition, there are some bonus chapters in the
book on the topics like Java and XML, Groovy, Sounds in Java, and many more.
Conventions
There are a few conventions in the book that you should know in the first place. Some of them are as follows:
When some code is new and needs to be pointed out, itll appear shaded like this:
setLayout(null);
text1 = new TextField(20);
text1.setSize(200, 50);
text1.setLocation(20, 20);
add(text1);
xxxiv
Introduction
The book also gives many tips throughout for you to have more insight into the subject. Ex:
An untrusted applet is not allowed to read and write files at all. So unless you make specific security arrangements, you should
not try to read or write files from applets. Therefore, for the sake of convenience, all the programs in this chapter are
applications.
You will also see notes for some additional information on the subject. Ex:
It should be clear that there are situations where the Refresh response header can come in handy. Even though it is not a
standard HTTP 1.1 header, it is something that can be considered a de facto standard.
Other Resources
Java comes with an immense amount of documentation equal to and worth hundreds of books! This
documentation is stored in linked HTML pages, and you must have a web browser to view and work with it.
There are also many, many webpages out there on Java (a random Web search on Java turns up about
239,000,000 pages; in fact, searching for Java tutorial alone will turn up about 35,700,000 pages). Here are some
other useful resources:
The Java home page at http://www.oracle.com/technetwork/java/index.html
The Sun Java tutorial at http://docs.oracle.com/javase/tutorial/
The Java 8, version 1.8 documentation at http://docs.oracle.com/javase/8/docs/
xxxv
Introduction
xxxvi
1
Essential Java
If you need an immediate solution to: See page:
Getting and Installing Java 15
Subfolders Created by JDK 16
Creating Source Files 16
Knowing Javas Reserved Words 17
Creating an Application 19
Compiling Code 20
Running Code 23
Running Code: Using Command-Line Options 25
Commenting Your Code 26
Import Java Packages and Classes 27
Finding Java Classes with CLASSPATH 28
1
Chapter 1: Essential Java
In Depth
Welcome to our big book of Java programming. Herein, well cover as much Java programming as can be
crammed into one bookin depth and in detail. We wont turn away from the more difficult issues because the
aim of this book is to lay out all of Java for you, making it ready for use. If you are like us and have a few
programming packages, youll enjoy working with Java more than with others. And, we would like to presume
that Java would be your choice for programming platform as you finish the book.
This first chapter covers the fundamental Java skills that youll rely on in the coming chapters. In the next few
chapters, you are going to see a large amount of Java syntax at work, but none will be of any use unless you can
get Java running and create programs with it. That fundamental set of skillscreating and running Java
programsis the topic of this chapter, and you can put this information to work in the following chapters for
testing the Java syntax well develop.
In this chapter, we are going to work through the mechanics of creating Java programsfrom installation issues
to writing Java code and from making sure your Java program can find what it needs to displaying simple
output. These skills are the ones you can use in the coming chapters. The material in those chapters is all about
the internals of writing a Java code, and this chapter is all about the rest of the process that makes the code run.
You might already be knowing much of the material in this chapter, in which case it will provide a good review
(some of the material is bound to be newafter all, very few people know what all the Java compiler command-
line switches do). If youve already got a working installation of Java and can write and run basic Java programs,
you are already familiar with most of what youll see in this chapter. Therefore, you can just skim through the
following pages and continue with Chapter 2, where we start digging into Java syntaxthe internals that really
make Java work. Otherwise, you can work through the material in this chapter because it provides the
foundation for the next several chapters to come. Here, well also make you familiar with the Application
servers, Deployers, and various methods and constructors.
2
In Depth
object and can put it out of your mindno longer does every part of the code has to set up its own screen
handling; you can just use the Screen object instead.
When Object-Oriented Programming was added to C, it became C++, and the programmers had a new darling.
C++ let programmers deal with longer programs and object-oriented code, which helped to solve many other
problems as well. For example, supporting objects made it easier for the manufacturers that supply software to
provide you with lots of prewritten code, ready to use. To create an object, you use a class, which acts like a
template or cookie cutter for that object, that is, a class is to an object what a cookie cutter is to a cookie. In other
words, you can think of a class as an objects type, much like a variables type might be the integer type.
Because C++ supported classes, the software manufacturers could provide you with huge readymade libraries of
classes, ready for you to start creating objects from. For example, one of the most popular libraries of C++ classes
is the Microsoft Foundation Class (MFC) library that comes with Microsofts Visual C++. Earlier, you wrote a
Windows program in C, you needed about five pages of solid code just to display a blank window. However,
using a class in the MFC library, you could simply create an object of the kind of window you wanted to use
with a border, without a border, as a dialog box, and so on. The object already had built-in functionality of the
kind of window you wanted to create, so all it took to create that window was one line of codejust the line
where you create the new window object from the class you selected.
Even more impressive was the fact that you could use an MFC class as a base class for your own classes, adding
the functionality you want to that class through a process called inheritance in Object-Oriented Programming. For
example, suppose you want your window to display a menu bar. You can derive your own class from a plain
MFC window, adding a menu bar to that class to create a new class. In this way, you can build your own class
just by adding a few lines of code to what the Microsoft programmers have already done. (Note that youll see
how Object-Oriented Programming works in depth in this book.)
All this seemed great to programmers, and C++s star rose high. It appeared to many that the perfect
programming language had arrived. What could be better? However, the programming environment itself was
about to undergo a great change with the popularization of what amounted to an immense new programming
environmentthe Internet. And, thats what made Java so popular.
Java Appears
Java was not originally created for the Internet. The first version of Java appeared in 1991 and was written in 18
months at Sun Microsystems. In fact, it wasnt even called Java in those days; it was called Oak and was used
internally at Sun.
The original idea of Oak was to create a platform-independent, object-oriented language. Many programmers
were confining themselves to programming for the IBM PC at that time, but the corporate environment can
include all kinds of programming platformsfrom PC to huge mainframes. The driving inspiration behind Oak
was to create something that could be used on all those computers (and now that Java has been popularized by
the Internet, a huge and increasing number of corporations are adopting it internally instead of C++ for just that
reasonin fact, some versions of C++, such as Microsofts C#, are now being modeled after Java). The other
motivation behind the introduction of Oak was to bring a language in the picture that could be used in consumer
electronics.
Oak was renamed Java in 1995, when it was released for public consumption, and it was almost an immediate
hit. By that time, Java had adopted a model that made it perfect for the Internetthe bytecode model. At
present, Sun has been taken over by Oracle; therefore, the platforms of Java are the products of Oracle now.
3
Chapter 1: Essential Java
computer, it can run Java programs. Java programs, therefore, dont need to be self-sufficient, and they dont
have to include all the machine-level code that actually runs on the computer. Instead, they are compiled into
compact bytecodes, and its these bytecodes that JVM reads and interprets to run your program. When you
download a Java applet from the Internet, you are actually downloading a bytecode file.
In this way, your Java program can be very small, because all the machine-level code to run your program is
already on the target computer and doesnt have to be downloaded. To host Java on a great variety of
computers, Sun only had to rewrite JVM for wording on those computers. Because your program is stored in a
bytecode file, it will run on any computer on which the JVM is installed.
As Java programs were originally supposed to be interpreted by the JVM, that is, they were executed bytecode
by bytecode, interpretation was a slow process. For that reason, Java introduced the Just-In-Time (JIT) compiler,
which is built into JVM. The JIT compiler reads sections of the bytecode and compiles them dynamically into a
machine-level code. Java performs runtime checks on different code sections; therefore, the whole program is not
compiled at once, resulting in the a faster execution of the programs.
Using bytecodes means that the Java programs are very compact, making them ideal for downloading over the
Internet. Moreover, running such programs with the JVM rather than downloading full programs provides
security.
Features of Java
Java is a simple, robust, platform-independent, and portable programming language. It is designed to meet the
real-world requirements with its following features:
Simple
Secure
Portable
Robust
Multithreading
Platform independent
Distributed
Dynamic
Simple
Java is simple to learn and use. In Java, it is easy to write and debug programs because Java does not use
pointers. Moreover, it provides bug free system because to strong memory management and also has automatic
memory allocation and de-allocation system. Unlike other programming languages, which provide dozens of
complicated ways to perform a simple task, Java provides a simple and clear approach to achieve a given task. If
a programmer understands the basic concepts of OOP, it becomes easier for him/her to learn Java.
Secure
In todays world, everybody needs safety and security. Because of to the threat of hackers, people feel unsafe
while performing commerce over the Internet. To overcome such fears, Java provides safety and security
features.
While using Java-compatible browser, everyone can safely download Java applets by relaxing their minds from
the fear of virtual infection or malicious intent. The Java programs are confined to the Java runtime environment,
they can access only that part of your computer that is required for program execution. The data outside Java
runtime environment cannot be accessed by them and therefore, downloading a Java application through the
Internet will not harm your computer. Thats why Java is a secure language.
When Java executes a program, the JVM can strictly monitor what goes on, which makes it great for the Internet
applications. You are already aware that security has become an extremely important issue on the Internet, and
Java rises to the task of taking care of the same. JVM can watch all that a program does; and if it does something
questionable, such as trying to write a file, it can prevent that operation. That alone makes Java more attractive
than C++, which has no such restrictions, for the Internet.
4
In Depth
You can also tailor Java security the way you like it, which offers a very flexible solution. As youll see in this
book, you can now specify, on a program-by-program basis, just what privileges you want to give to the
downloaded code. You can now also sign your Java code in a way that shows it comes from you without any
malicious modifications. Well take a look at all this and more in this book.
In a nutshell, Java has a winning combination for the InternetJava programs are small, secure, platform-
independent, object-oriented, and powerful. They also implement other features that programmers like. Java
programs are often simple to write compared to C++. The end result is that you can write your Java program
once, and it can be easily downloaded and run on all kinds of machinesthe perfect recipe for the Internet!
Thats the reason Java has soared so high.
Portable
In the distributed world of the Internet, an application developed with the help of a programming language
might be accessed on various computers having different kinds of operating system. But, its not guaranteed that
the application is portable, that is, it runs successfully on all operating systems. To overcome this portability
issue, Java introduces a concept of what is known as bytecode.
Bytecode is a set of instructions generated by the Java compiler while compiling a Java program. In other
programming languages, a program is compiled into an executable code; but in Java, a program gets compiled
into an intermediate code called bytecode. This bytecode then gets executed by Java runtime system called the
JVM. So, in order to run your Java program, you should have only JVM installed. It is also considered to be the
interpreter of bytecode. In this way, Java has solved the problem of portability.
Robust
Generally, programs fail because of the following two reasons:
Memory ManagementLack of memory management for allocating and de-allocating memory for objects
Exceptional ConditionsOccurrence of unexpected exceptions
Considering these reasons, Java was designed to provide the ability to create robust programs. Therefore, Java
compels the programmers to resolve mistakes during compilation. Moreover, it also frees the programmer from
the worries of common causes of programming errors as the program code is verified during compilation.
Java also eradicates the problem of memory management by performing automatic garbage collection. It
manages the memory allocation and de-allocation for unused objects.
Multithreading
Java is a programming language that is designed for the distributed environment of the Internet; and for that,
the concept of multithreading is implemented. This feature helps you write interactive programs, wherein
multiple tasks can be performed simultaneously, thus making Java a robust programming language.
Java is inherently multi threaded as there can be multiple executing threads in a single Java program. For
example, a Java programmer can run three Java applets on the same page, provided that each applet gets equal
time from the CPU.
The multi threaded feature of Java makes it very responsive and robust. It is very important to note that as Java
is highly multi threaded, it is difficult to port it to architectures, such as Windows 3.1 or PowerMac, which do
not natively support multithreading.
Platform-Independent
It is one of the most important features of Java as it is the first programming language that is not bound to any
specific operating system. In other words, Java programs can be executed anywhere on any system. Before the
evolution of Java, no other programming language was platform-independent, and it can therefore be said that
Java is a revolutionary technology. Apart from cross-platform in source form, Java is also platform-independent
in complied binary form.
A Java program does not execute natively on the host machine; instead, a Java interpreter reads the bytecode
and executes the corresponding native machine instructions. The Java interpreter is a special naive program that
reads the bytecode, an intermediate form after compilation. Therefore, in order to port a Java program to a new
5
Chapter 1: Essential Java
platform, you need the interpreter and some of the library routines. Moreover, the Java compiler is also written
in Java, and the bytecodes are precisely defined, which remain the same on all platforms.
Distributed
Java is a distributed language as it can be used to create applications for communicating over the network. Java
can communicate over the network because it supports TCP/IP (Transmission Control Protocol/Internet
Protocol). The TCP/IP protocol is a set of network communication protocols.
Dynamic
During the runtime of a Java program, the relevant information that is used to verify and resolve access to
objects is required. This concept of providing runtime information is referred to as dynamically linking the code.
This feature of Java adds strength to the applet environment, in which small fragments of bytecode are
dynamically updated on a running system.
Java Environment
The Java environment comprises numerous development tools, classes, and methods. The development tools for
Java are provided as a part of the system known as Java Development Kit (JDK). Moreover, the Application
Programming Interface (API) comprises the classes and interfaces used in Java programming. In this section, we
discuss the following:
Java Development Kit
Java Platforms
Java Virtual Machine
Java API
Java Programs
Java Platforms
Oracle provides various Java editions to develop and run Java programs. The Java platform is not bound to any
one processor or operating system, but the execution engine (virtual machine) and a compiler can run identically
on any operating system. The following subsections are the different editions of the Java platform.
6
In Depth
Sets of APIs to build a wide variety of applications, comprising standalone applications that can run on
various operating systems, such as Microsoft Windows, Linux, and Solaris
7
Chapter 1: Essential Java
Java ME configurations: the Connected Limited Device Configuration (CLDC) and the Connected Device
Configuration (CDC).
Figure 1.2: Displaying the Process of Running a Program on Any Operating System
Java API
It is a collection of classes, interfaces, and methods provided in the form of Java packages. In other words, it is a
large collection of already created classes and interfaces, which provide many useful capabilities, such as
Graphical User Interface (GUI), date, time, and calendar capabilities. The categorization of Java API in the form
of Java packages is as follows:
Application Programming Packages
java.langProvides classes that are fundamental to the design of the Java programming language
java.utilProvides legacy collection classes, event model, collection framework, date and time
capabilities, internationalization, and other utility classes, such as string tokenizer
java.ioProvides classes for system input and output through data streams, serialization, and the file
system
Applet and Network Programming Packages
java.awtProvides classes for creating user interface and painting graphics and images
java.appletProvides classes that are necessary for creating an applet and those that are used to
communicate with its applet context
java.netProvides classes that are used for implementing networking in Java programs
8
In Depth
Java Programs
A Java programmer can create either a Java application or a Java applet depending upon the requirement. In
Java, you create the following types of program:
Applications
Applets
Well use the term program in this book to refer to both applets and applications. Now, lets discuss each of them
in detail.
Applications
A Java application is a program that is created by using Java programming language. Java applications are
console-based, Character User Interface (CUI)-based, and GUI-based standalone applications. Once you become
used to creating applications, you will find that creating an application by using Java is also as simple as creating
an application with any other programming language. In order to execute a Java application, you need to
perform the following steps:
Compile the Java source code by using javac compiler to translate the source code into bytecode
Execute the bytecode by using the Java interpreter
Apart from applications, you can also create applets in Java.
Applets
An applet is a program written in the Java programming language that can be included in an HTML page in the
same way as an image is included. An applet can be used in both static and dynamic web pages to either
display content or share information through the pages. You need to import the java.applet package that
provides classes to either create an applet or allow an applet to communicate with its applet context.
The applet context is an application that is responsible for loading and running applets. For example, the applet
context could be a web browser or an applet development environment. In other words, an applet is a Java
application designed to be transmitted over the Internet and is executed by a Java-compatible web browser.
After understanding the types of Java program, lets create a simple Java program. But to do this, you need to
create a source code file by using a text editor first. After creating the Java program, you need to compile it by
using the Java compiler javac and execute by using the Java interpreter java. The compiler generates a .class
file by translating the source code into bytecode, which is then executed by the Java interpreter.
9
Chapter 1: Essential Java
JRunJRun is an Application server of Adobe that is based on Oracles Java Enterprise Edition. It consists
of Java Server Pages, Java Servlets, Enterprise Java Beans, Java Transaction Service (JTS), and Java
Messaging Service (JMS).
JRun works with the most popular web servers, including Apache, Microsofts Internet Information Server
(IIS), and any other web server that supports Internet Server Application Program Interface (ISAPI) or the
Webs Common Gateway Interface (CGI).
JRun comes in four editionsDeveloper edition, Professional edition, Advanced edition, and Enterprise
edition. The Developer edition consists of the full JRun package, but it is meant for development use only
and is limited to three concurrent connections. The Advanced edition is designed to deploy JSP and Servlet
applications in a clustered-server environment. Corporates that host Servlet and JSP-based Web
applications from a single server use the Professional edition. Companies that build and deploy e-commerce
Java applications use the Enterprise edition.
WebLogicThe WebLogic Platform delivers application infrastructure technology in a single, unified,
easy-to-use platform for application development, deployment, and management. The Oracle WebLogic
Platform increases productivity and lowers total cost of ownership for IT organizations as it provides a
unified, simplified, and extensible platform for application development, deployment, and management.
WebLogic is the first platform to address the need for asynchronous Web services, which is a critical aspect
of application-to-application communication.
WebLogic gives developers the tools necessary to integrate different applications and platforms for
providing full leverage to organization in terms of data and software investments. It also provides an
enterprise class framework that ensures reliable, scalable, available, and secure applications.
To integrate different applications and platforms, the developers require Deployers for deploying Web and
EJB applications in the server environment.
DeployersThe Deployers are responsible for deploying EJB applications and Web applications into the
server environment. They are not responsible for deploying an Application client archive or a resource
adapter archive but may be responsible for additional configuration of these components.
Packaged as a part of Java EE EAR files, these archives are not considered when the Enterprise applications
are deployed. These are a part of Java EE applications but do not follow the runtime activation process that
Web application and EJB containers go through during deployment.
The Application client archives operate within the content of a Java EE container and are not deployed into
an Application server. The Application client program runs standalone, and the Deployers are not
responsible for configuring the container environment for these programs.
The resource adapter archives are the simple libraries that are dropped into a valid JCA implementation.
The Deployers produce container-ready EJB applications, Web applications, applets, and Application clients
that have been customized for target environment of the Application server. Some of the commonly used
Deployers are Ant, Junit, Cactus, and Maven.
AntApache Ant is a Deployer, which is a Java-based tool. Ant is like Make but without Makes
wrinkles. Unlike Make, Ant uses Java classes instead of writing shell commands.
JUnitDeveloped by Erich Gamma and Kent Beck, JUnit is an open source softwarea testing
framework. The developer who implements unit tests in Java uses it. It is a simple framework to write
the repeatable tests. JUnit is an instance of xUnit architecture for unit testing framework.
Cactus and MavenThe Apache Cactus and Maven, used as Deployers, are Java-based applications
that automatically start containers, run tests, and stop the containers.
Cactus is a simple framework for testing server-side Java code. Its purpose is to lower the cost of
writing tests for server side codes.
Maven is based on the concept of Project Object Model (POM), which provides a well-defined project
structure, well-defined development process, and cohesive body of documentation that keep the
developer updated regarding the project progress.
10
In Depth
Program Design
Program design in Java is not necessarily an easy task. Good programming design involves a number of overall
aspects, and its worth taking a look at some of them in this chapter before we start digging into Java syntax in
depth.
In fact, one of the most important aspects of creating a new application is designing that application. Poor
choices can end up hampering your application through many revisions of the product. Many books are
available on program design.
Microsoft, which should know something about it, breaks the process into four areas:
PerformanceThe responsiveness and overall optimization of speed and resource use
MaintainabilityThe ability of the application to be easily maintained
ExtensibilityThe ability of the application to be extended in well-defined ways
AvailabilityHow robust the implementation of the application is and how available it is for use
Lets take a quick look at these four areas now.
Performance
Performance is a design issue thats hard to argue with. If the users arent getting what they want from your
application, thats clearly a problem. In general, performance depends on the users needs. For some people,
speed is essential; for others, robustness or efficient use of resources is what they are looking for. Overall, the
performance of an application is an indication of how well it responds to the users needs. Here are some general
aspects of performance that you should consider while writing Java programs:
Algorithm efficiency
CPU speed
Efficient database design and normalization
Limiting external accesses
Network speed
Security issues
Speed issues
Use of resources
Web access speed
Well get to more specifics of performance throughout the book.
Maintainability
Maintainability is the measure of how easily you can adapt your application to future needs. This issue comes
down to using good programming practices, which well talk about throughout the book. Much of this is
common sensesimply keeping future coding needs in mind as you write your code. Some major issues in the
best programming arsenal include the following:
Avoid deep nesting of loops and conditionals
Avoid passing global variables to procedures
Be modular when you write code
Break code into packages
Document program changes
Give each procedure only one purpose
Make sure that your application can scale well for large tasks and large number of users
Plan for code reuse
Program defensively
11
Chapter 1: Essential Java
Extensibility
Extensibility is the ability of your application to be extended in a well-defined and relatively easy way. It is
usually a concern only with larger applications, and it often involves an entire interface specially designed for
extension modules. In fact, Java itself is designed to be extended by using the Java Extension Framework.
Availability
Availability is the measure of how much time your application can be used for in comparison to the time users
want to use it for. This includes everything, from the application not freezing up when performing a long task (at
the least, giving the user some feedback of the operations status) to working with techniques and methods not
likely to hang, to making backups of crucial data, and to planning for alternate resource useif possiblewhen
access to a desired resource is blocked.
Overall, the design process is one that involves quite a bit of time. In fact, the whole development cycle is the
subject of quite a few studiesyou may be surprised to learn that when field testing, in-house testing, planning,
designing, and user interface testing are added up, some studies allocate as little as 15 percent of total project
time to the actual coding.
So much has been written about the development cycle of software that we wont go into more details here. But,
its worth noting that programmers shouldnt short-change the crucial design steps because it can lead to more
problems in the long run than time saved in the short run.
12
In Depth
}
If you compile the previous class without using parameters argument and then run this program, you will
see the output as:
Parameter: arg0
However, if you compile the previous class with the parameters argument and then run this program, you
will see the output with the actual name of parameter that you have passed.
Parameter: args
Java libraries Following changes have taken place in Java libraries features:
Streams A new package, java.util.stream, provides a Stream API to support functional-style
operations on streams of elements. Stream API can be integrated with Collections API to perform bulk
operations on collections, such as sequential or parallel map-reduce transformations.
Date/Time API (JSR 310) Java 8 provides a new Date-Time API (JSR 310), which provides a new
package, called java.time. This package contains all the classes for date, time, date/time, time zones,
instants, duration, and clocks manipulation. Some examples of classes contained in this package are
Clock, LocaleDate, LocalTime, and Duration. The Clock class provides the access to the current instant,
date and time using a time zone. It can be used in place of using the System.currentTimeMillis()
and TimeZone.getDefault() methods. The LocaleDate class holds only the date part and the
LocaleTime class holds only the time part without a time-zone in the ISO-8601 calendar system. The
Duration class, finally, provides an amount of time in terms of seconds and nanoseconds.
Nashorn JavaScript engine Java 8 provides a new Nashorn JavaScript engine that allows you to
develop and execute certain kinds of JavaScript application on JVM. The engine works like
javax.script.ScriptEngine and permits Java and JavaScript interoperability.
Parallel Arrays Java 8 provides various new methods allowing parallel arrays processing. For
example, the parallelSort() method significantly speeds up the sorting on multicore machines.
Concurrency Java 8 adds new methods to the java.util.concurrent.ConcurrentHashMap
class that support aggregate operations on the basis of the newly added streams facility and lambda
expressions. A new class, java.util.concurrent.locks.StampedLock, has been added to
provide a capability-based lock with three modes for controlling read/write access. In addition, some
classes are added to the java.util.concurrent.atomic package, which includes
DoubleAccumulator, DoubleAdder, LongAccumulator, and LongAdder.
Java tools Java 8 provides a new set of command line tools, which include Nashorn engine (jjs command)
and class dependency analyzer (jdeps command). The role of these tools is described as follows:
Nashorn engine The jjs command accepts a list of JavaScript source code files as arguments and runs
them. For example, if a file, myfunc.js, is created with the following content:
function demofunc() {
return 1;
};
print( demofunc() + 1 );
Now, the jjs command is used to execute the myfunc.js file:
jjs myfunc.js
The output of the preceding code will be:
2
13
Chapter 1: Essential Java
Class dependency analyzer The jdeps command is used to show the package-level or class-level
dependencies of Java class files. It accepts .class file, a directory, or JAR file as an input, and displays
the dependencies to the console.
Java runtime (JVM) The PermGen space has been replaced with Metaspace (JEP 122). The JVM
options,XX:PermSize and -XX:MaxPermSize, are replaced with -XX:MetaSpaceSize and
XX:MaxMetaspaceSize, respectively.
JDBC The JDBC-ODBC Bridge has been removed. In addition, JDBC 4.2 has been introduced with
various new features. Some of these are as follows:
Addition of REF_CURSOR support
Addition of java.sql.DriverAction interface
Addition of security check on deregisterDriver method in the DriverManager class
Addition of the java.sql.SQLType interface
Addition of the java.sql.JDBCType enum
You would learn about these features of Java SE 8 in detail with their implementation in other chapters of the book.
14
Immediate Solutions
Immediate Solutions
Getting and Installing Java
The Big Boss (BB) gives you a callas usual at the last minute. You have 20 minutes to write a new Web page
that gives users an overview of your companys products. What are you going to do? Knowing how well Java
works in cases like this, you select Java as your language of choice to get the task done. Of course, youve got to
make sure you have it before you can use it.
Its time to download and install Java, which means downloading the Java Software Development Kit (SDK).
Currently, you can find it at http://www.oracle.com/technetwork/java/javase/downloads/jdk8-
downloads-2133151.html. The kit gets downloaded in the form of an executable application file. Next, you
can follow the instructions on the Oracles website in order to install JDK 1.8. Wed love to be able to provide the
actual installation instructions here, but thats one of the biggest pitfalls a Java book can fall into, even the one
thats designed to be as complete as possible. We have been writing about Java ever since it first came out, and it
turns out that the actual installation instructions are often very volatile. As these instructions are changed quite
frequently, the ones we have provided in the previous books instantly became obsolete. For that reason, the
absolutely best thing you can do is to see how Sun wants you to install the SDK; therefore, you should refer to
the installation instructions as posted on the Java site. The installation process has been getting easier with every
version and beta of Java, and now, it typically involves only running the file youve downloaded.
One thing you should be sure to do, as indicated in the Sun installation instructions, is to ensure your machine
can find the Java tools, including the Java compiler itself. To do that, verify that the Java bin directory is in your
computers path. For example, in Windows, usually the bin directory path is C:\Program
Files\Java\jdk1.8\bin for SDK 1.8.
The Java Software Development Kit was called the Java Development Kit, JDK, in earlier Java versions. In fact, Oracle often
seems to be of two minds heresometimes, youll see references to the SDK and sometimes, youll see references to JDK.
This is one of those timesalthough the kit is now called the SDK, its installed by default into a directory named \jdk1.8.
In Windows 7, you can follow these steps to configure Java 8 on your system:
Click the Windows icon on the taskbar, right click the Computer, and select the Properties option. You can
also reach the same location by opening the Control Panel| System and Security| System.
Click the Advanced system settings option in the System Properties window. This opens the System
Properties dialog box.
Click the Environment Variables button to open the Environment Variables dialog box.
Edit the PATH variable, setting the way you want. You may append the new path to the already existing
PATH variable or create a new PATH variable. Finally, click OK. Note that if you are appending the PATH
variable, the different paths must be separated by semicolons (;).
You can also set the PATH variable temporarily with the help of the command line. The path shall remain set
only till the command line is open; once you exit from the command line, the PATH variable set also gets erased.
The following command is used to temporarily set the PATH variable:
SET PATH= C:\Program Files\Java\jdk1.8\bin;
When the bin directory is in the path, youll be able to use the Java tools directly from the command line, instead
of having to preface them with a pathname each time you want to use them on the command line.
15
Chapter 1: Essential Java
When you install the SDK, you dont have to worry about setting the CLASSPATH now because the SDK will
know where to find its own installed libraries. However, if you want to search other custom bytecode files when
compiling a file, youll have to set the CLASSPATH yourself. Youll see how to do this when we will discuss
compiling programs in this chapter. (There are two ways to indicate to the Java compiler where to find bytecode
files you particularly want to searchby setting the CLASSPATH environment variable and by using the -
CLASSPATH compiler switch.)
The current version of the SDK does not require CLASSPATH to be defined; and if it has been defined by some
other Java version or system, it is likely to create problems. If you want to keep the CLASSPATH environment
variable for any reason, you need to use the command line option to define the CLASSPATH temporarily.
16
Immediate Solutions
using the File | Save As dialog box. The general rule is that if you can type the file out at the command line (note
that thats DOS on DOS- and Windows-based computers) and dont see any odd, non-alphanumeric characters,
its a plain text file. The real test, of course, is whether the Java compiler, which translates your program into a
bytecode file, can read and interpret your program.
In addition, your programs should be stored in files that have the extension .java. For example, if you are
writing an application named App, you should store the actual Java program in a file named App.java. You
pass this file to the Java compiler to create the actual bytecode file, as youll see in the next few pages.
So far, so goodwe have done the selection of the editor or word processor down. Now, how about writing
some code?
17
Chapter 1: Essential Java
18
Immediate Solutions
Creating an Application
The Big Boss arrives and says, So now you can write Java! Give me a demonstration! You turn to your terminal
and immediately your mind goes blank. What will you write?
Heres a sample Java application that well develop over the next few sections, all the way through the compiling
and running stages. Place this code in a file named App.java:
public class App {
public static void main(String[] args) {
System.out.println("Hello from Java!"); }
}
If you are new to Java, this might look strange to you. The idea here is that this application will print the text
Hello from Java! when you compile and run it. For example, heres how it looks in a DOS window under
Windows:
c:\>java App
Hello from Java!
Not the most significant of programs but a good one to get us started. Lets take this program apart line by line.
main is a class method, not an object method (youll see in Chapter 4). It must not return a value when its
finished executing, which is why we use the keyword void in this code (in other words, a return value of type
void means that there actually is no return value). Finally, note the argument in the parentheses following the
word main: String[] args. You place an argument list in the parentheses of a method declaration like this
to indicate what values are passed to the method and can be used by the code in the method. In this case, we are
indicating that main has passed an array of string values called args. These string values hold the values
passed from the command line when you start the application; for example, if you type java app Hello
there, Hello and there would be the two strings in the args array. The full details appear in Chapter 4.
Because we wont use any command-line arguments in this application, we wont use args in the code for the
main method.
This line of code then starts the main method. The whole job of this method is to print out the text Hello from
Java! which is done in the next line of code.
Compiling Code
The Big Boss is chomping a cigar while standing right behind you as you enter your new Java application into a
file. Hmm, says the Big Boss, clearly not impressed. Whats next? Now, you say, we have to compile the
program and then we can run it. OK, the Big Boss says. Amaze me.
To translate a Java program into a bytecode file that the JVM can use, you use the Java compiler javac (for
example, on Windows machines, this program will be called javac.exe, which is in the Java bin directory).
Heres how you use javac in general:
javac [options] [sourcefiles] [@files]
The arguments to javac are:
optionsCommand-line options
sourcefilesOne or more source files to be compiled (such as App.java)
@filesOne or more files that list source files
To compile App.java, use the following command:
C:\>javac App.java
Note that to make sure javac can find App.java, you should first make sure the current directory is the one
that has App.java in it. For example, in Windows, if youve stored App.java in C:\Nancy, to compile
20
Immediate Solutions
App.java, first make sure C:\Nancy is the current directory (you can use the change directory command, cd,
like this: cd C:\Nancy). Then, run javac like this: C:\Nancy>javac App.java. Alternatively, you can
specify the path of App.java like this: C:\>javac C:\Nancy\App.java.
In addition, note that in this book, well use the generic prompt C:\> for the command line, but this
actually stands for the current working directory, whatever that may be in your casefor
example, C:\Bertie\Development>, C:\Programs>, Unix prompts, such as %,
/home/Nancy/programs:, and so on. That is to say C:\> is just going to be a placeholder for the actual
prompt on your machine for the current directory you are in.
The Java compiler javac takes the file App.java(assuming there are no errors), compiles it, translates it, and
then creates a new file called App.class. If errors occur, the Java compiler will tell you what they are, including
what line of code is wrongin this case, we have forgotten the println method and tried to use the one called
printline:
C:\>javac App.java
App.java:3: error: cannot find symbol
System.out.printline(Hello from Java!); }
^
symbol: method printline(String)
location: variable out of type PrintStream
1 error
When App.java is successfully compiled to bytecode, the new file, App.class, contains all that JVM will need
to create objects from the App class. So, we have created App.class. Now, how do you actually run it in JVM?
See the next solution.
21
Chapter 1: Essential Java
-gIt generates all debugging information, including local variables. By default, only line number and
source file information are generated.
-g:noneIt makes the compiler unable to generate any debugging information.
-g:{keyword list} It generates only some kinds of debugging information, specified by a comma-
separated list of keywords. The valid keywords are source (source file debugging information), lines
(line number debugging information), and vars (local variable debugging information).
-nowarn It disables all warning messages.
-OIt optimizes code for performance in terms of the quickest execution time. Note that using the -O
option may slow down compilation, produce larger class files, and make the program difficult to debug.
Note that before version 1.2, the -g and -O options of javac could not be used together.
As of version 1.2, you could combine the -g and O options, but you might get odd results, such as missing
variables and relocated or missing code. The -O option no longer automatically turns on -depend or turns
off g.
-sourcepathIt specifies the source code path to search for class or interface definitions. As with the user
class path, source path entries are separated by semicolons (;) and can be directories, .jar (Java Archive)
files or zip files. If you use packages, the local pathname within the directory or archive must reflect the
package name, as youll see later. Note that classes found through the class path are subject to automatic
recompilation if their source code files are found.
-verboseIt creates verbose output. This includes information about each class loaded and each source
file compiled.
-XIt displays information about non-standard options and quits.
-XdependIt searches all reachable classes for more recent source files to recompile. This option will more
reliably discover classes that need to be recompiled, but it can slow down the compilation process
dramatically.
-XstdoutIt sends compiler messages to System.out. By default, the compiler messages go to
System.err, which youll learn more about later.
-XverbosepathIt describes how paths and standard extensions were searched to find source and
class files.
-JoptionYou use this option to pass an option to the Java launcher called by javac. For example, -J-
Xms64m sets the start-up memory to 64 MB. Although this option does not begin with -X, its not a standard
option of javac. Its a common convention for -J to pass options to the underlying JVM executing
applications written in Java.
Cross-Compilation Options
Cross-compilation options are considered an advanced topic; javac supports cross-compiling, where classes are
compiled with the bootstrap (default) and extension classes of a different Java platform implementation. You
must use -bootclasspath and -extdirs when cross-compiling. Here are the cross-compilation options:
-target versionIt generates class files that will work on JVMs with the specified version.
-bootclasspath bootclasspathIt cross-compiles against the specified set of boot classes. As with the
user class path, boot class path entries are separated by semicolons (;) and can be directories, .jar files or
.zip files.
-extdirs directoriesIt cross-compiles against the specified extension directories; directories is
a semicolon-separated list of directories. Each .jar file in the specified directories is automatically searched
for class files.
22
Immediate Solutions
You can also use Xlint compiler option to pinpoint the warning point in the program.
Running Code
The Big Boss is getting impatient. Youve written a new application and compiled it without errors for the first
time (which you can feel proud of), but nothing has really happened that the BB can see. Its time to run the new
application.
You run Java applications with the program named Java (in Windows, for example, this is the java.exe file in
the Java bin file). The Java program, called the java tool, is what actually runs JVM. Heres how you can use
the java tool:
java [options] class [argument ...]
java [options] -jar file.jar [argument ...]
The parameters used in the preceding lines are explained as follows:
optionsCommand-line options, which well cover in a topic coming right up.
classThe name of the class to be invoked.
file.jarThe name of the Java Archive (JAR) file to be invoked. This is used only with -jar. JAR files
are covered in Chapter 27.
argumentA command-line argument passed to the main method.
For example, to run the application named app, which is in the file App.class, you could execute the following
command at the command line (note that you omit the .class part of App.class here):
C:\>java App
The result appears immediately:
C:\>java App
Hello from Java!
To make sure the java tool can find App.class in this example, you should first make sure the current directory is the one that
has App.class in it. For example, in Windows, if youve stored App.class in C:\Nancy, to run it, first make sure C:\Nancy is the
current directory (you can use the change directory command, cd, like this: cd C:\Nancy). Then, run Java like this:
C:\Nancy>java App. Alternatively, you can specify the path of App.class like this: C:\>java classpath C:\Nancy App.
23
Chapter 1: Essential Java
You can see how this works in a DOS window under Windows in Figure 1.3:
When you launch a Java windowed application like this, the console window does not wait for the application to
finish; if you are running in DOS, the windowed application appears and the DOS prompt reappears in the DOS
window. This gives a more professional feel to those applications that you release for general use.
While we are discussing compiling and running code, theres another detail we should coverthe command-
line options you can use with the javac and java commands. Well take a look at them in the next two topics.
For more on CLASSPATH, an important topic in Java programming, see the upcoming solution Finding Java Classes with
CLASSPATH.
Well take a look at using the command-line options in this solution; you use these options with the java and
javaw tools as follows (for a discussion of these tools, see the solution Running Code, earlier in this chapter):
java [options] class [argument ...]
java [options] -jar file.jar [argument ...]
javaw [options] class [argument ...]
javaw [options] -jar file.jar [argument ...]
The command-line options you can use with these tools are as follows (note that non-standard options, which
means they might not be supported in the future, begin with an X):
-classpath classpath or -cp classpathIt specifies a list of directories, .jar files or .zip files to
search for class files. You separate class path entries with semicolons (;). Note that specifying -classpath
or -cp overrides any setting of the CLASSPATH environment variable. Used with java or javaw, -
classpath or -cp only specifies the class path for user classes. If -classpath and -cp are not used and
CLASSPATH is not set, the user class path is limited to the current directory, which is referred to with a dot
(.). See the topic Finding Java Classes with CLASSPATH later in this chapter for more information.
-Dproperty=valueIt sets a system property value.
-jarIt executes a program encapsulated in a JAR file. The first argument is the name of a JAR file instead
of a start-up class name. When you use this option, the JAR file is the source of all user classes, and the other
user class path settings are ignored.
-verbose or -verbose:classIt displays information about each class loaded.
-verbose:gcIt reports on each garbage collection event. Garbage collection involves automatic memory
management in Java.
-verbose:jniIt reports information about the use of native (that is, platform-specific) methods and other
Java Native Interface activity.
-versionIt displays version information and exits.
-? or -helpIt displays usage information and exits.
-XIt displays information about non-standard options and exits.
-Xbootclasspath:bootclasspathIt specifies a semicolon-separated list of directories, .jar files or
.zip files to search for boot class files. Note that these will be used in place of the boot class files included
with Java itself.
-XdebugIt starts with the debugger enabled.
-XnoclassgcIt disables class garbage collection.
25
Chapter 1: Essential Java
-XmsnIt indicates the initial size of the memory pool you want to use (this value must be greater than
1000). To multiply the value by 1000, append the letter k. To multiply the value by 1 million, append the
letter m. The default value is 1m.
-XmxnIt specifies the maximum size of the memory pool (this value must be greater than 1000). To
multiply the value by 1000, append the letter k. To multiply the value by 1 million, append the letter m. The
default value is 64m.
-Xrunhprof[:help][:<suboption>=<value>,...]It enables CPU, heap, or monitor profiling. This
option is usually followed by a list of comma-separated pairs of the form <suboption>=<value>.
-XrsIt reduces the use of operating system signals.
-Xcheck:jniIt performs additional checks for Java Native Interface (JNI) functions.
-XfutureIt performs strict class-file format checks.
26
Immediate Solutions
Java also supports a one-line comment using a double slash (//). The Java compiler will ignore everything on a
line after the // marker, so you can create whole lines that are comments or just add a comment to an individual
line as follows:
/* This application prints out "Hello from Java!" */
public class App { //Create the App class
//Create main(), the entry point for the application.
public static void main(String[] args) {
//Print out the message with
System.out.println("Hello from Java!"); }
}
Finally, Java also supports a documentation comment, which starts with /** and ends with */.This
comment is designed to be used with the javadoc tool, which can create documentation for you nearly
automatically. An example of using /** and */ is as follows:
/** This application prints out "Hello from Java!" */
public class App {
public static void main(String[] args) {
System.out.println("Hello from Java!"); }
}
Commenting your code can be invaluable in team environments where you share your code source files with
others. Its also handy if someone else is going to take over a project that you have been working on.
classes in a particular package. Heres how that would look if you wanted to import all the classes in the
java.util package at once:
import java.util.*;
public class App {
public static void main(String[] args) {
System.out.println("Today = " + new Date()); }
}
Importing packages and classes only indicates to the compiler where to look for the code it needsit does not increase the size
of your code. For that reason, the bytecode file App.class will be of the same size regardless of whether you use the import
java.util.Date; statement or the import java.util.*; statement.
This is fine if you stick with importing the Sun-provided classes because Java knows where to look for the
classes it was installed with. But what if you want to import your own classes or ones provided by a third party?
Heres an example. Suppose you have a user-defined package named printer, having a class named Printer
in a file named Printer.java, and that class has one method named print:
package printer;
public class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
You might want to make use of the print method in other classes. In this case, we are creating a new object of
the Printer class using the new operator and using that objects print method in an application named App:
public class App {
public static void main(String[] args) { (new Printer()).print(); }
}
To do this, you can import the Printer class as follows (note that you can also place the code for the Printer
class in the same file as the App class, in which case you wouldnt have to import the Printer class):
import printer.*;
public class App {
public static void main(String[] args) { (new Printer()).print(); }
}
Here, we have learned how to import a Java built-in and a user-created class in our Java program. To learn about
the implementation part and how to actually create and import packages in our classes, refer Chapter 27.
However, suppose you want to store all your classes in a directory named, say, c:\classes. How will the Java
compiler find Printer.class there? To answer that question, take a look at the next solution on CLASSPATH.
Bootstrap classes are the classes that come by default with JDK, and Extension classes are the classes that use the Java
Extension Framework. But, what if you want to have Java search for classes in another directory or in a .jar file supplied by a
third party? You can do that with the CLASSPATH environment variable because Java uses this variable to determine where
you want to search for classes.
28
Immediate Solutions
Heres an example that was first introduced in the previous solution. Say that you have a class named Printer
in a file named Printer.java and that class has one method named print:
public class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
In the previous solution, you want to use the print method in another classas in this case where we are
creating a new object of the Printer class by using the new operator and using that objects print method in
an application named App:
import printer.*;
public class App {
public static void main(String[] args) { (new Printer()).print(); }
}
This works if Printer.class is in the same directory in which you are compiling this application, because the
Java compiler will search the current directory by default. But, suppose you want to store all your classes in a
directory named c:\classes. How will the Java compiler find Printer.class there?
To make the Java compiler search c:\classes, you can set the CLASSPATH environment variable to include
that directory. By default, there are no paths or directories in CLASSPATH, but you can add a semicolon-
separated list to CLASSPATH, like this (note that its important here not to have any spaces around the equals
sign):
SET CLASSPATH=c:\classes;c:\newclasses
You can also determine the current CLASSPATH setting by typing the SET CLASSPATH at the command line and
pressing Enter. To permanently set the classpath in Windows 7, follow these steps:
1. Click the Windows icon on the taskbar, right-click the Computer, and select the Properties option. You can
also reach the same location by opening the Control Panel| System and Security| System.
2. Click the Advanced system settings option in the System Properties window. This opens up the System
Properties dialog box.
3. Click the Environment Variables button to open the Environment Variables dialog box.
4. Edit the CLASSPATH setting the way you want.
5. You may append the new classpath to the already existing CLASSPATH variable or create a new
CLASSPATH variable.
6. Finally, click OK.
Note that if you are appending the CLASSPATH variable, the different paths must be separated by
semicolons (;).
Now, the Java compiler (and other Java tools, such as the java tool) will know enough to search c:\classes
and c:\newclasses automatically. This means that the following code will now work if Printer.class is
in c:\classes because that directory is in CLASSPATH:
import printer.*;
public class App {
public static void main(String[] args) { (new Printer()).print(); }
}
You can append the current settings in CLASSPATH to a new setting, like this:
SET CLASSPATH=c:\classes;c:\newclasses;%CLASSPATH%
Note that you can also search .jar and .zip files for classes, as shown here:
SET CLASSPATH=server.jar;classes.zip;%CLASSPATH%
Originally, CLASSPATH was a big headache for beginners in Java programming because no classes were
considered bootstrap classes, which meant that you had to set up and understand CLASSPATH before you could
use Java at all. Thats been fixed with the concept of bootstrap classes, which are the classes that come with Java
(and are searched automatically). However, if you want to use non-standard packages or store your own classes
in other directories, its important to know how to set CLASSPATH.
29
Chapter 1: Essential Java
Summary
In this chapter, you got familiar with Java 8, its environment, and designing of programs. The chapter
introduced you to Swings and Utilities. In addition, it discussed the enhancements in JDBC and provided a brief
description of garbage collector. You also learned how to install Java. Toward the end, you developed simple
Java programs with the introduction of how to import the packages.
In the next chapter, you will learn about the variables, arrays, and strings.
30
Chapter 2: Variables, Arrays, and Strings
2
Variables, Arrays,
and Strings
If you need an immediate solution to: See page:
What Data Types are Available? 37
Creating Integer Literals 37
Creating Floating-Point Literals 38
Creating Boolean Literals 39
Creating Character Literals 39
Creating String Literals 40
Creating Binary Literals 40
Using Underscores in Numeric Literals 41
Declaring Integer Variables 42
Declaring Floating-Point Variables 42
Declaring Character Variables 43
Declaring Boolean Variables 43
Initializing Variables Dynamically 44
Conversion between Data Types 45
Declaring One-Dimensional Arrays 47
Creating One-Dimensional Arrays 47
Initializing One-Dimensional Arrays 48
Declaring Multi-Dimensional Arrays 48
Creating Multi-Dimensional Arrays 48
Initializing Multi-Dimensional Arrays 49
Creating Irregular Multi-Dimensional Arrays 50
Getting an the Length of an Array 51
31
Chapter 2: Variables, Arrays, and Strings
32
In Depth
In Depth
This chapter begins our discussion of Java syntax, and youll see a great deal of syntax usage in this chapter. We
are going to cover how Java stores and retrieves data in variables, arrays, and strings. Working with data is a
fundamental part of any significant program, and the information in this chapter is essential for any Java
programmer. Even if you are familiar with Java and have already been programming in it, take a look at the
material in this chapter because theres a lot coming up.
Variables
There are various kinds of variable that serve as containers for storing data in the memory. Different kinds of
variable store data in different formats, and the selection of variable should be made depending upon the data
that they will be storing and the memory that will be required to be kept aside for storing it. For example, an
integer variable type, the int type, can store up to 4 bytes (or 32 bits) and contain only integer values between
2,147,483,648 and 2,147,483,647. There are some more variables that Java provides such as floating-point
numbers, short, long, byte, and char, and all of them will be explained in this chapter.
Before you use a variable in Java, you must declare it, specifying its data type. Heres how you declare variables
in Java:
type name [= value][, name [= value]...];
Heres an example showing how to declare a variable of the int type, which means a numeric value will be
stored in it (the variable is named days):
public class App {
public static void main(String[] args) {
int days;
. . . }
}
This code allocates 32 bits of storage in memory and labels the location of that storage, as far as the Java compiler
is concerned, as days, which means you can now refer to that name in code. Heres how to store a numeric
value 365 in the days variable using the Java assignment operator (=):
public class App {
public static void main(String[] args) {
int days;
days = 365;
. . . }
}
Here, the value 365 is an integer literal, which means a literal value that you place directly in your code. Well
take a look at what kinds of literal Java allows throughout this chapter. To verify that days now hold 365, you
can print it out on the console:
public class App {
public static void main(String[] args) {
int days;
days = 365;
System.out.println("Number of days = " + days); }
}
Heres the result of this code:
C:\>java App
Number of days = 365
As you can see, we have created a variable, stored data in it, and fetched the same data to print it on the screen.
Thats how it works.
Theres also a convenient shortcut that lets you initialize a variable when you declare it. Here, days are declared
and initialized to 365 in one step:
public class App {
public static void main(String[] args) {
int days = 365;
33
Chapter 2: Variables, Arrays, and Strings
Data Typing
Java puts considerable emphasis on its data types. Its a strongly-typed language, which means it insists that the
simple variables you declare and use must fit in the listed types.
Every simple variable must have a type (and in fact, every expressionevery combination of terms that Java can
evaluate to get a valuehas a type as well). Also, Java is very particular about maintaining the integrity of those
types, especially if you try to assign a value of one type to a variable of another type. In fact, Java is more
strongly typed than a language such as C++. In C++, for example, you can assign a floating-point number to an
integer, and C++ will handle the type conversion for you, but you cannot do that in Java. You can, however,
convert between certain data types in Java such as between the integer types. Well take a look at that later in this
chapter.
When working with variables, you might find the Java compiler issuing a lot of errors and warnings about data types, which can
take some time getting used to; bear in mind that the inspiration for making Java very particular about adhering to data types
and not mixing them easily is to prevent errors in your code.
Thats an overview of whats going on in Java with simple data types and variables; its now time to take a look
at compound data storage in depth, which as far as this chapter is concerned means arrays.
Arrays
Simple types are good only for storing single data items. However, sometimes the data that needs to be stored is
a lot more complex. For instance, you want to start a new bank, say, JP Bank (short for Java Programming Bank)
and keep a track of the amount in each account indexed by account number. This situation presents the need to
work with compound data. The usage of arrays is appropriate in such a scenario.
An array allows grouping of simple data to form a compound data structure that can be referred to by using a
single name. Every data item stored in that compound data structure is stored at a particular position in the
array and can be referred by the numeric index (or position) of the data in the data structure. It is vital to store
the data in indexed form with the index sorted numerically because computers perform millions of operations
in a second and data stored in indexed form can be referenced using the numerical value. This way the entire
data structure can be traversed by simply incrementing the indexs value, and the values can be accessed with
ease.
Heres an example. In this case, well start the Java Programming Bank out with 100 new accounts, and each one
will have its own entry in an array named accounts[]. The square braces at the end of the accounts[]
represent that it is an array and the value of the index can be placed enclosed in those braces to refer to the value
stored at a particular position. Heres how we create the accounts[] array, making each entry in it of the
floating-point type double for extra precision. First, we declare the array; then, we create it with the new
operator, which is what Java uses to actually allocate memory:
public class App {
34
In Depth
Note that we have given account 3 a checking balance of $2,385,489,382.06 (wishful thinking) and that Java has
printed that out as 2.38548938206E9. This is Javas shorthand for 2.38548938206X10 9not an inconsiderable bank
balance by any means.
Youll see a lot of arrays in this chapter, but you should know that Java now supports much more complex data structures than
arrays. These data structures are built into the language. Java now supports hashes and maps as well as other types of data
structure, and as youll see all that when we take a look at the collection classes in the forthcoming chapter.
Strings
You may have noticed that we have been using the + operator to create the text to print in the previous examples
like this:
public class App {
public static void main(String[] args) {
double accounts[][] = new double[2][100];
accounts[0][2] = 43.95;
accounts[1][2] = 2385489382.06;
System.out.println("Savings account 3 has $" + accounts[0][2]);
System.out.println("Checking account 3 has $" + accounts[1][2]); }
}
Thats because their own class in Javathe String classsupports text strings and you can think of the
String class as defining a new data type.
For example, heres how we create a string named greeting that holds the text Hello from Java!:
public class App {
public static void main(String[] args) {
String greeting = "Hello from Java!";
. . .
Now we can treat this string as we would other types of variables, including printing it out:
public class App {
public static void main(String[] args) {
String greeting = "Hello from Java!";
System.out.println(greeting); }
}
Heres the result of this application:
C:\>java App
Hello from Java!
Although strings are not one of the simple data types in Java, yet they deserve a place in this chapter because
most programmers treat them as they would any other data type. In fact, many programmers would argue that
strings should be a simple data type in Java as they are in other languages. The reason they are not has to do
with Java lineage, which stretches back to C. C has no string simple data type; in C, you handle strings as one-
dimensional arrays of characters, which is pretty awkward. One of the things that made programmers happy
about C++ was that most implementations included a String class that you could use much as you would any
other data type. Java follows this usage, implementing strings as a class, not as an intrinsic data type, but string
handling is so fundamental to programming that it makes sense to start looking at string variables in this
chapter.
There are two string classes in JavaString and StringBuffer. You use the String class to create text
strings that cannot change, and you can use StringBuffer to create strings you can modify. As you can see in
the preceding code, you can use strings much as you would any simple data type in Java. Well take a look at
using strings in this chapter as well as in the next chapter (which is on using operators such as + and ). Well
also take a look at using operators on strings.
Thats enough overview for nowits now time to start creating and using variables, arrays, and strings.
36
Immediate Solutions
Immediate Solutions
What Data Types are Available?
Say, the Big Boss (BB) says, how about writing a Java program to manage the companys debt? We are in
debt? you ask. Just a little, the BB replies. How little? you ask. About $2,848,238,493, 902.77, says the BB.
Hmm! you say. Sounds like a job for floating-point numbers.
What simple data types can you use to create variables in Java? Youll find them in Table 2.1 below. The simple
data types can be broken up by category, as we did at the beginning of this chapter, like this:
IntegersRefer to the byte, short, int, and long types. They contain signed, whole-value numbers.
Floating point numbersRefer to the float and double types. They contain signed, floating-point
numbers.
CharacterRefers to the char type that holds characters such as letters and numbers.
BooleanRefers to the type that holds only two types of values: true and false.
Thats an overview of what simple data types are available; to put each of them to work, see the following
solutions.
Its worth realizing that you cant completely count on the numeric precision listed in Table 2.1 because Java implementations
do differ by machine. However, you can use the StrictMath class (you can find more about these classes at
http://docs.oracle.com/javase/8/docs/api/) to ensure that the same mathematical precision is used no matter what platform your
program is running on.
37
Chapter 2: Variables, Arrays, and Strings
Here, we are assigning an integer literal with a value of 365 to the variable days. By default, integer literals are
of the int type. However, if you assign them to other integer types, such as short, Java converts the literal type
automatically. On the other hand, long values can have more digits than int values, so Java provides an
explicit way of creating long literals: You append an L to the end of the literal. Heres an example:
public class App {
public static void main(String[] args) {
long value;
value = 1234567890123456789L;
System.out.println("The value = " + value); }
}
Heres the result of this code:
C:\>java App
The value = 1234567890123456789
You can also create literals in octal format by starting them with a leading zero and in hexadecimal format by
starting with 0x or 0X. Here are some examples:
public class App { public static void main(String[] args) {
int value; value = 16;
System.out.println("16 decimal = " + value);
value = 020;
System.out.println("20 octal = " + value + " in decimal");
value = 0x10;
System.out.println("10 hexadecimal = " + value + " in decimal"); }
}
Heres what this program displays:
C:\>java App
16 decimal = 16
20 octal = 16 in decimal
10 hexadecimal = 16 in decimal
38
Immediate Solutions
39
Chapter 2: Variables, Arrays, and Strings
40
Immediate Solutions
more detailed than the hexadecimal or octal literals. A good example of the relation between the array members
is rotation of 2 bits among the successive array members, as shown in the following example:
public class App {
public static void main(String[] args) {
int val = 0b00010000;
int myPhases[] = {
0b00110011,
0b11001100,
0b00110011,
0b11001100 };
System.out.println("The value in val is: " + val);
System.out.println("And following are the values stored in the array myPhases:");
System.out.println(myPhases[0]);
System.out.println(myPhases[1]);
System.out.println(myPhases[2]);
System.out.println(myPhases[3]); }
}
The output of the program is as follows:
C:\>java App
The value in val is: 16
And following are the values stored in the array myPhases:
51
204
51
204
41
Chapter 2: Variables, Arrays, and Strings
It is important to note that you can put underscores in a numeric literal only in between the digits of the numeric
literal. Or the underscore character should be accompanied by at least one digit on each side. You cannot place
an underscore in the numeric literals in the following places:
At the start or the end of the numeric literal
Next to the decimal point in the floating-point literal
In front of an F or L suffix in the floating-point or long literal
Places where a string of digits is expected in the numeric literal
42
Immediate Solutions
double double1;
float1 = 1.11111111111F;
double1 = 1.1111111111111E+9D;
System.out.println("float1 = " + float1);
System.out.println("double1 = " + double1); }
}
Heres the output of the code (note that we have exceeded the precision allowed for a float, so its value is
rounded):
C:\>java App
float1 = 1.1111112
double1 = 1.1111111111111E9
43
Chapter 2: Variables, Arrays, and Strings
44
Immediate Solutions
Automatic Conversions
When you are assigning one type of data to a variable of another type, Java will convert the data to the new
variable type automatically if both the following conditions are true:
The data type and the variable types are compatible.
The target type has a larger range than the source type.
For example, you can assign a byte value to an int variable because byte and int are compatible types, and
int variables have a larger range than byte values. Therefore, no data will be lost in the type conversion. Heres
an example:
public class App {
public static void main(String[] args) {
byte byte1 = 1;
int int1;
int1 = byte1;
System.out.println("int1 = " + int1); }
}
The Java compiler has no problem with this code, and it makes the type conversion automatically. Heres the
result of this program:
C:\>java App
int1 = 1
45
Chapter 2: Variables, Arrays, and Strings
Converting a data type to another with a larger range is called widening conversion. In widening conversions, the
numeric types, such as the integer and floating-point types, are compatible with each other. On the other hand,
char and boolean types are not compatible with each other or with the numeric types.
46
Immediate Solutions
In general, the Java compiler promotes byte and short types to int types in expressions. If one operand is a long, the entire
expression is made a long. Similarly, if one operand is a float, the whole expression is made a float; if one operand is a double,
the whole expression is made a double.
In fact, theres another way of doing this that follows the pointer-declaration syntax in C++. You can also declare arrays with the
brackets ([]) after the type, not the name of the variable, like this: double[ ] accounts.
Unlike declaring simple variables, declaring an array does not set aside memory for the array because Java isnt
sure how big you want it to be yet. This means theres another step to the processactually creating the array.
See the next topic for the details.
47
Chapter 2: Variables, Arrays, and Strings
In fact, theres another way of doing this that follows the pointer-declaration syntax in C++. You can also declare arrays with the
brackets ([ ]) after the type, not the name of the variable, like this: double[ ][ ] accounts.
Thats how it works with two-dimensional arraysthe left index specifies the row in the array and the right
index specifies the column. Of course, you dont have to limit yourself to two dimensions.
Heres how you can declare a four-dimensional array:
public class App {
public static void main(String[] args) {
double accounts[][][][] = new double[2][3][4][5];
. . . }
}
As you can see, its as easy to declare multi-dimensional arrays as it is to declare one-dimensional arrays. Now
what about actually creating the declared array? See the next topic for the details.
48
Immediate Solutions
49
Chapter 2: Variables, Arrays, and Strings
accounts[1][2]); }
}
Heres what running this code yields:
C:\>java App
Savings account 3 has $4343.91
Checking account 3 has $543.62
50
Immediate Solutions
The preceding program gets compiled but running the code yields, is the exceptional handling error as follows:
C:\>java App
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 500
at App.main(App.java:10)
51
Chapter 2: Variables, Arrays, and Strings
This shows the need for the static member of the Circumference class with the name PI and would provide a
much more accurate definition of . The Math prefix to the name PI doesnt really add clarity to the code, and it
would be better without it.
We can avoid the prefixing of PI to the Math class name by importing the PI member name from
the Math class:
import static java.lang.Math.PI;
class Circumference {
. . .
double circumference_circle() { return 2*PI*radius; }
}
All the static members can also be imported by using the * notation. This import applies only to the classes
defined in a named package for the static members of a class. If you require importing the name of static member
of a class that you define, the definition of the class should be included in a named package. Names of static
members with no names in the default package cannot be imported. The class name in the static import
statement must always be qualified with its package name.
52
Immediate Solutions
53
Chapter 2: Variables, Arrays, and Strings
54
Immediate Solutions
55
Chapter 2: Variables, Arrays, and Strings
static String valueOf(Object obj) It yields the string representation of an Object type argument
Creating Strings
So Java includes a String class to handle text strings, the Novice Programmer says. Thats great, because
Im writing this novel, see, and. Hold it, you say. I dont want to hear about it.
Lets take a look at some of the many ways of creating String objects. Heres a way youve already seen:
public class App { public static void main(String[] args) {
String s1 = "Hello from Java!";
. . . }
}
In fact, when you use a string literal such as Hello from Java! in your code, Java treats it as a String object So
whats really happening here is that one String object is assigned to another.
Of course, you can also declare a string first and then assign a value to it:
public class App { public static void main(String[] args) {
String s1 = "Hello from Java!";
String s2;
s2 = "Hello from Java!";
. . . }
}
Heres a case in which we use one of the String class constructors. In this case, we are just creating an empty
string and then assigning data to it:
public class App {
public static void main(String[] args) {
String s1 = "Hello from Java!";
String s2;
s2 = "Hello from Java!";
String s3 = new String();
s3 = "Hello from Java!";
. . .}
}
You can also pass a text string to the String class constructor directly to create a new string, like this:
public class App {
public static void main(String[] args) {
String s1 = "Hello from Java!";
String s2;
s2 = "Hello from Java!";
56
Immediate Solutions
To convert a string into a number, you can use the numeric wrapper classes, such as Integer, Long, Float, and so on, using
methods such as Integer.parseInt() and Long.parseLong().
At the end of this code, we print out all the strings we have created. Heres what appears when the program
is run:
C:\>java App
Hello from Java!
Hello from Java!
Hello from Java!
Hello from Java!
Hi there
Hi
Hi there
57
Chapter 2: Variables, Arrays, and Strings
Concatenating Strings
Concatenating strings means joining them together, and we have already used the + operator in this book to do
just that. However, theres another way to concatenate stringsyou can use the String class concat()
method to join two strings and create a new one.
How does that look in code? Heres an example where we use both the + operator and the concat() method to
create the same string:
public class App {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = s1 + " from";
String s3 = s2 + " Java!";
String s4 = s1.concat(" from");
String s5 = s4.concat(" Java!");
System.out.println(s3);
System.out.println(s5); }
}
Heres the result of the preceding code:
C:\>java App
Hello from Java!
Hello from Java!
As you have already seen when printing out numbers, when you concatenate a numeric value with a string, the
numeric value is concatenated as a string.
Note that concatenating numbers does indeed treat them as strings, so be carefulfor example, System.out.println (3 + 3 = +
3 + 3) displays 3 + 3 = 33, not 3 + 3 = 6.
58
Immediate Solutions
59
Chapter 2: Variables, Arrays, and Strings
60
Immediate Solutions
61
Chapter 2: Variables, Arrays, and Strings
62
Immediate Solutions
Creating StringBuffers
You can create StringBuffer objects using the StringBuffer class constructors. For example, heres how to
create an empty StringBuffer object (which is set up with space for 16 characters, by default) and then insert
some text into it:
public class App { public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
s1.insert(0, "Hello from Java!");
System.out.println(s1);
. . .
Heres how to initialize a new StringBuffer object with a string:
public class App {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
s1.insert(0, "Hello from Java!");
System.out.println(s1);
StringBuffer s2 = new StringBuffer("Hello from Java!");
63
Chapter 2: Variables, Arrays, and Strings
System.out.println(s2);
. . .
You can also create a StringBuffer object with a specific length, like this:
public class App {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
s1.insert(0, "Hello from Java!");
System.out.println(s1);
StringBuffer s2 = new StringBuffer("Hello from Java!");
System.out.println(s2);
StringBuffer s3 = new StringBuffer();
s3.insert(0, "Hello from Java!");
System.out.println(s3);
}
}
Heres the result of this code:
C:\>java App
Hello from Java!
Hello from Java!
Hello from Java!
64
Immediate Solutions
65
Chapter 2: Variables, Arrays, and Strings
In fact, youve already seen how to use replace() method; you just specify a character range and the new text
that should replace that range, like this:
public class App {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello from Java!");
s1.replace(6, 10, "to");
System.out.println(s1); }
}
Heres the result of the preceding code:
C:\>java App
Hello to Java!
short Short
long Long
byte Byte
float Float
double Double
char Character
boolean Boolean
There are different methods defined in order to return the value of an object. For example, byteValue()
method returns the value of an object as byte; similarly, doubleValue() method will return the values as
double. The following example is giving you the demonstration of using the wrapper class:
public class App {
public static void main (String args[]) {
Integer intwrap = new Integer(250);
Character chrwrap = new Character('H');
int int1 = intwrap.intValue();
char chr1= chrwrap.charValue();
System.out.println(int1 + " " + intwrap);
System.out.println(chr1+" "+ chrwrap); }
}
This program compiles and upon executing shows the result as:
C:\>java App
250 250
H H
66
Immediate Solutions
The following lines from the preceding program are encapsulating a value within an object. This feature is known
as boxing:
Integer intwrap = new Integer(250);
Character chrwrap = new Character('H');
The following lines of code are extracting the values from the type wrapper. This feature is known as unboxing:
int int1 = intwrap.intValue();
char chr1= chrwrap.charValue();
67
Chapter 2: Variables, Arrays, and Strings
Lets discuss what is happening in the preceding program, from the previous code we have:
public class App {
public static void main(String args[]) {
Integer intbox1,intbox2,intbox3;
intbox1 =250;
int a= intbox1;
System.out.println("The value of intbox1 is "+ intbox1);
System.out.println("The value of a is "+ a);
. . . }
}
The following code line in the preceding program is encapsulating a value within an object:
intbox1 =250;
This feature is known as autoboxing as we have not defined the object explicitly by using the new keyword.
Again, the following line is shown as extracting the values. This feature is known as unboxing:
int a= intbox1;
If well print the results of the two variables defined, it will yield the same result as assigned. If you need an int,
it is required that you unbox the Integer by using the intValue() method.
Lets take another section of the code from the program:
public class App {
public static void main(String args[]) {
Integer intbox1,intbox2,intbox3;
intbox1 =250;
int a= intbox1;
System.out.println("The value of intbox1 is "+ intbox1);
System.out.println("The value of a is "+ a);
intbox2=500;
System.out.println("value of intbox2 is "+ intbox2);
intbox2=intbox2+1;
System.out.println("value of intbox2 after increment is " + intbox2);
intbox3= intbox2+(intbox2/5);
System.out.println(" value of intbox 3 after evaluation is "+ intbox3);
. . . }
}
In these lines, the expression is being calculated and the result obtained will again be reboxed. In the line,
intbox2=500, autoboxing is taking place.
Note the expression intbox2=intbox2+1. It will automatically unbox the variable and then result back into
the variable by reboxing. Youll get the result of different variables used in the expression. It will display the
values before evaluating and after evaluating the expression. You can see this later in this section. Lets take
some more lines of the code:
public class App {
public static void main(String args[]) {
Integer intbox1,intbox2,intbox3;
intbox1 =250;
int a= intbox1;
System.out.println("The value of intbox1 is "+ intbox1);
System.out.println("The value of a is "+ a);
intbox2=500;
System.out.println("value of intbox2 is "+ intbox2);
intbox2=intbox2+1;
System.out.println("value of intbox2 after increment is " + intbox2);
intbox3= intbox2+(intbox2/5);
System.out.println("value of intbox 3 after evaluation is "+ intbox3);
Boolean bbox1= true;
if (bbox1)
System.out.println ("bbox1 contains the true value");
Character chbox1='H';
char chbox2= chbox1;
68
Immediate Solutions
69
Chapter 2: Variables, Arrays, and Strings
To understand this better, we can compare this with arrays. If you needed to create a method that could take
an arbitrary number of values, you could put the values into the array prior to invoking the method.
For example, shown here is the MessageFormat class that formats a message:
Object[] arguments = {
new Integer(7), new Date(), "a disturbance in the Force" };
String result = MessageFormat.format("Nature caused {2} , on {1,date}
{1,time}" + "{0,number,integer}., arguments);
Basically, instead of passing multiple arguments in an array, varargs automates and hides the process.
Additionally, it is upwardly well matched with the existing APIs. For example, the
MessageFormat.format() method now has this declaration:
public static String format(String pattern, Object... arguments);
The three periods after Object indicate that you can pass an array or a sequence of arguments as final argument.
However, it must be noted that varargs can be used only in the final argument position.
Varargs can be useful in core APIs including reflection, message formatting, and the new print facility. If you
are an API designer, you should use them in moderationonly when the benefit is truly undeniable. Care must
be taken so that the varargs method is not overloaded or it will be difficult for you to figure out which
overloaded method gets called; but you can take advantage of them whenever the API offers them. Lets now
understand the concept of varags through a small example given here:
public class App {
static void mthdvar(int ...int1) {
System.out.print("Total number of arguments passed are: "
+int1.length+ " Contents: ");
for (int int2:int1) System.out.print(int2 +" ");
System.out.println(); }
public static void main (String args[]) {
mthdvar();
mthdvar(100);
mthdvar(200,300,400); }
}
The result of the preceding code is as follows:
Total number of arguments passed are: 0 Contents:
Total number of arguments passed are: 1 Contents: 100
Total number of arguments passed are: 3 Contents: 200 300 400
So, in the preceding examples, we have defined a method mthdvar(), in which int1 is operated as an array.
The three dots used in the line will be known by the compiler as an array. As you can see in the main(),
method, mthdvar() has been called by using three different arguments; in the first case, we have not passed
any arguments.
The contents of this array arguments can be fetched by using the for-each statement. Lets briefly go through the
for-each loop. You will be explained about the for-each loop as well as other varieties of loops in Chapter 3.
The statement for (type any-var : collections) is in general form. The word type is for the data type which should be the same as
defined in the array or passed in the argument list. Collection is being considered as the type of objects whether array or some
list value specifies one at a time from first element to the last element. Lets take a small example to understand this concept.
Overloading requires methods with distinct signatures. The signature of a method includes its name and the ordered list of its
argument types. All other items appearing in a method header, such as exceptions, return type, final, and synchronized, do not
contribute to a method's signature.
71
Chapter 2: Variables, Arrays, and Strings
Similar type of elements must be passed to the varargs list, although that type can be of any type or a user-
defined type.
Trying to combine varargs with optional parameters is not a good ideathough it just doesnt work most of the
time (type mismatch errors are common). The resulting functionality generally isnt very useful even when the
code compiles without errors.
Also, once you are inside the function body, your varargs parameter is a list, completely impossible to tell apart
from a list passed as a parameter. This means that passing a variable number of arguments through one function
to another could be really tough.
Test( varargs List ) { Counter( List ); }
Counter ( varargs List ) { print( ListCount(List) ); }
main () { Test( 1, 2, 3) ; }
Heres an example to understand the concept:
public class App {
public static void Test(Integer... List) { counter(List); }
public static void counter(Integer... List) {
int ListCount=0;
for(Integer cnt:List) { ListCount++; }
System.out.println(ListCount); }
public static void main(String args[]) { Test(1,2,3); }
}
Heres the result:
C:\>java App
3
Fortunately, this issue doesnt come up too often.
72
Immediate Solutions
compile time by looking at the methods of the callee class; but if that class is extended later with more
specific methods, the old caller will start using them instead of using the vararg method. This is a case where the
type signature safety has not been taken care of. Many more examples are available that show the ambiguity in
varargs, but we need to find those by getting accustomed to the technology and to popularize the use of the
same.
73
Chapter 2: Variables, Arrays, and Strings
Summary
In this chapter, we have learned about the use of variables, literals, data types, arrays, strings, and Wrapper
classes. After getting the conceptual knowledge on the concepts, the Immediate Solutions section has helped you
to declare and initialize variables, create binary literals, and use underscores in numeric literals. You also came
to know how to perform operations on arrays and strings. You have learned the use of StringBuffer classes and
wrapper classes. The chapter ends with the discussion on autoboxing and unboxing of primitive types, and the
fundamentals of varargs methods.
In the next chapter, you will learn about the operators and control structures.
74
3
Operators, Conditionals,
and Loops
If you need an immediate solution to: See page:
Operator Precedence 81
Incrementing and Decrementing (++ and --) 82
Unary NOT (~ And !) 83
Multiplication and Division (* and /) 83
Modulus (%) 83
Addition and Subtraction (+ and -) 84
Shift Operators (>>, >>>, and <<) 84
Relational Operators (>, >=, <, <=, ==, and !=) 85
Bitwise and Bitwise Logical AND, XOR, and OR (&, ^, and /) 85
Logical (&& and ||) 87
The if-then-else Operator (?:) 87
Assignment Operators (= and [operator]=) 88
Using the Math Class 89
Changes in the Math Class 90
Class StrictMath 90
Comparing Strings 91
The if Statement 92
The else Statement 92
Nested if Statement 93
The if-else Ladders 93
The switch Statement 93
Using Strings in switch Statement 95
The while Loop 95
The do-while Loop 96
Chapter 3: Operators, Conditionals, and Loops
76
In Depth
In Depth
In the previous chapter, we took a look at how Java handles data in basic ways. In this chapter, well start doing
something with that data as we examine the Java operators, conditionals, and loops.
Storing a lot of data in your program is fine; but unless you do something with it, its not of much use. Using
operators, you can manipulate your dataadd, subtract, divide, multiply, and more. With conditionals, you can
alter a programs flow by testing the values of your data items. Using loops, you can iterate over all data items in
a set, such as an array, working with each data item in succession in an easy way. These represent the next step
up in programming power from the previous chapter, and well discuss all three of these programming topics
here.
Operators
Java provides a very easy way to work with data in a program. Like most languages, it provides a number of
built-in operators. For example, if one variable contains value 10 and another variable contains 20, the variables
can be added using the + operator, as shown in this code:
public class App {
public static void main(String[] args) {
int operand1 = 20, operand2 = 10, sum;
sum=operand1+operand2;
System.out.println(operand1 + " + " +operand2 + " = " + sum); }
}
Heres the result of this code:
C:\>java App
20 + 10 = 30
So, what operators does Java offer? Heres a list of all of them:
--(decrement)
- (subtraction)
! (logical unary NOT)
!= (not equal to)
% (modulus)
%= (modulus assignment)
& (logical AND)
&& (short-circuit AND)
&= (bitwise AND assignment)
* (multiplication)
*= (multiplication assignment)
/ (division)
/= (division assignment)
?: (ternary if-then-else)
^ (logical XOR)
^= (bitwise XOR assignment)
| (logical OR)
|| (short-circuit OR)
|= (bitwise OR assignment)
~ (bitwise unary NOT)
+ (addition)
77
Chapter 3: Operators, Conditionals, and Loops
++ (increment)
+= (addition assignment)
< (less than)
<< (shift left)
<<= (shift left assignment)
<= (less than or equal to)
= (assignment)
-= (subtraction assignment)
== (equal to)
> (greater than)
>= (greater than or equal to)
>> (shift right)
>>= (shift right assignment)
>>> (shift right with zero fill)
>>>= (shift right zero fill assignment)
Youll see these operators at work in this chapter. Operators that take one operand are called unary operators.
Those that take two operandsfor example, addition (a + b)are called binary operators. Theres even an
operator,?:, that takes three operandsthe ternary operator.
Besides the built-in operators, well also cover the Java Math class in this chapter, which allows you to add a lot more math
power to your programs, including exponentiation (unlike other languages, Java has no built-in exponentiation operator),
logarithms, trigonometric functions, and more. StrictMath classes (you can find more about these classes at
http://java.sun.com/javase/8/docs/api/) ensure that the same mathematical precision is used no matter what machine your
program is running on.
Conditionals
The next step up from using simple operators is to use conditional statements, also called branching statements, in
your code. You use conditional statements to make decisions based on the value of your data and make the flow
of the program go in different directions accordingly.
Say you wanted to report on the weather; and if its less than 80 degrees Fahrenheit, you want to print out a
message that reads Its not too hot. You can do this by checking the current temperature with a Java if
statement that compares the value in the variable temperature to 80; and if that value is under 80, it prints out
your message:
public class App {
public static void main(String[] args) {
int temperature = 73;
if (temperature < 80) { System.out.println("It's not too hot."); }
}
}
The if statement tests whether its condition (the part that appears in the parentheses) is true, which in this case
is temperature < 80. The Java < (less than) relational operator is used to test whether the value in
temperature is less than 80. Because we have set that value to 73, the if statements condition is true, which
means the code in the body of the if statement will be executed. Heres the result of this code:
C:\>java App
It's not too hot.
You can make if statements more complex by adding else clauses. These clauses must follow the if statement
and are executed when the if statement condition turns out to be false. Heres an example:
public class App {
public static void main(String[] args) {
78
In Depth
Loops
Loops enable you to execute a set of statements for a number of times. For example, you may want to print your
name five times on the console or calculate the sum of the first hundred natural numbers; in such cases, loops are
used. The loop execution depends upon a loop condition. The statements inside a loop are executed as long as
the loop condition remains true. Generally, the condition involves a loop index that gets incremented or
decremented every time the loop executes.
The general syntax of a for loop is as follows:
for (initialization_expression; test_conditon; iteration_expression) {
statement;
}
Note that the statement that makes up the body of the for loop can be a compound statement, which means it
can be made up of several single statements enclosed within curly braces.
You can initialize the loop index with initialization expression, provide a test condition for loop termination,
and modify loop index value in iteration expression. Note that we are declaring and initializing the loop index at
the same time. Isnt it similar to C++? Yes, C++ also allows you to simultaneously declare and initialize the loop
index. A simple example of a for loop which prints Kogent five times is as follows:
public class App {
public static void main(String[] args) {
for (int loop_index = 1; loop_index < 6; loop_index++){
System.out.println("Kogent"); }
}
}
This code prints Kogent, using loop_index, which starts at 1 and is steadily incremented each time through
the loop by 1 till the loop test condition evaluates true. The result of this code is:
C:\>java App
Kogent
Kogent
Kogent
Kogent
Kogent
There are statements that cause an unconditional jump to other statement in the code. Such statements are called
jump statements. These are mainly used to interrupt the control flow within the switch statements and loops.
There are three jump statements supported by Java: break, continue, and return. Generally, the break
statement allows exit from a loop or switch before the execution completes, and the continue statement takes
control to the beginning of a loop or switch. For the return statement, please see the topic Returning Values
from Methods in Chapter 4.
Heres a simple example of the break statement to make things clearer. In this case, the loop index is initialized
with value 1 and is incremented by 1 for every execution of the loop. In the code, the test condition states that the
loop should execute till the loop index is less than 7:
public class App {
public static void main(String[] args) {
for (int loop_index = 1; loop_index < 7; loop_index++){
if(loop_index==5) break;
System.out.println(loop_index); }
System.out.println("Kogent"); }
}
79
Chapter 3: Operators, Conditionals, and Loops
This code prints the value of loop index until it becomes 5. Then the break statement takes control out of the
loop and Kogent gets printed. The result of this code is:
C:\>java App
1
2
3
4
Kogent
As you can see, for loop is a powerful one; in fact, its just one of the many topics coming up in the Immediate
Solutions section. Its now time to start by using operators, conditional statements, and loops.
80
Immediate Solutions
Immediate Solutions
Operator Precedence
Hey, says the Novice Programmer, Javas gone all wacky again. I tried adding 6 and 24 and then dividing the
result by 6. The answer should have been 5, but Java said its 10. Probably an operator precedence problem,
you say. Let me check your code.
When a single Java statement contains a number of operators, you may also face problem similar to what the
Novice Programmer is facing here. An important concern is which operator does Java execute first? For example,
take a look at the Novice Programmers code in which he tries to add 6 and 24 and then divide the sum by 6:
public class App {
public static void main(String[] args) {
double value;
value = 6 + 24/6;
System.out.println("Value is " + value); }
}
The actual result of this code is:
C:\>java App
Value is 10.0
The Novice Programmer was right; its different from what he expected. Actually, its the operator precedence
that determines which operator is to be executed first, which second, and so on. Operator precedence rule states
that the operators are executed in the order of highest to lowest precedence. The Novice Programmer is getting
10 as output because the / operator has higher precedence than the + operator. Therefore, 24 is firstly divided by
6 and then the result is added to 6, which produces 10.
You can use parentheses to specify Java the way you want the operators to execute. Heres how the Novice
Programmers code would now look; see the parentheses around 6 + 24, which have been used to make sure
that this operation is performed first:
public class App {
public static void main(String[] args) {
double value;
value = (6 + 24)/6;
System.out.println("Value is " + value); }
}
The result of this code is:
C:\>java App
Value is 5.0
Table 3.1 spells out the Java operator precedence, from highest to lowest (operators on the same line have the
same precedence). Note that at the very highest level of precedence, youll find ( ), [ ] (the array operator,
which you use to get data items at a specific index in an array), and . (the dot operator, which you use to specify
methods and data members of objects). This means that, for example, you can always use parentheses to set the
execution order of operations in Java statements.
Well go over all these Java operators, in order of precedence, in this chapter, starting with the incrementing and
decrementing operators: ++ and --.
Table 3.1: Operator precedence
Operators
( ) [ ] .
++ -- ~ !
* / %
+ -
81
Chapter 3: Operators, Conditionals, and Loops
82
Immediate Solutions
value1 = 12
value2 = 12
So, why are 1111111111111111 binary equal to -1 in a short variable? If you add it to 1, you end up with 10000000000000000
binary, a number too large for a 16-bit short, so the leading 1 is lost and you end up with 0 (in other words, -1 + 1 = 0).
Modulus (%)
Modulus operator returns the remainder of a division operation. For example, 11%3 returns 2 and 7%2 returns 1
as output. Note that the modulus operator is especially useful when converting between bases because you can
use it to successively strip digits off a number by using the modulus operator with the base you are converting
into. To see how this works, take a look at the topic The while Loop, later in this chapter. It contains a full
example.
83
Chapter 3: Operators, Conditionals, and Loops
84
Immediate Solutions
Heres a Java pitfall to avoid: When you are creating a logical condition, bear in mind that you probably want to use == instead
of =. For example, the expression budget == 0 is true if the value in budget is 0, but the expression budget = 0 assigns a value
of 0 to budget. Be careful, because using = instead of == in logical conditions is a very common mistake.
85
Chapter 3: Operators, Conditionals, and Loops
You can find the bitwise operators in Table 3.2. In overview, heres how they work: The OR operator (|) returns 0
when both bits are 0 and returns 1 otherwise. The AND operator (&) returns 1 when both bits are 1 and returns 0
otherwise. Finally, the XOR operator (^, called the exclusive OR) returns 1 when one bit is 0 and the other is 1, and
it returns 0 otherwise.
When the &, ^, and | operators operate on Boolean (true/false) values, they are considered bitwise logical
operators. The bitwise logical operators work the same as the bitwise operators (substitute false for 0 and true for
1), as you can see in Table 3.3.
In overview, heres how the bitwise logical operators work: The OR operator (|) returns false when both
operands are false, and it returns true otherwise. The AND operator (&) returns true when both operands are true,
and it returns false otherwise. The XOR operator (^) returns true when one operand is false and one is true, and it
returns false otherwise.
Table 3.2: The OR, AND, and XOR bitwise operators
x y x | y (OR) x & y (AND) x ^ y (XOR)
0 0 0 0 0
1 0 1 0 1
0 1 1 0 1
1 1 1 1 0
Table 3.3: The OR, AND, and XOR bitwise logical operators
X y x | y (OR) x & y (AND) x ^ y (XOR)
False False False False False
Heres an example in which we tie two logical conditions together, displaying a message if either is true, using
the | operator:
public class App {
public static void main(String[] args) {
int budget = 1; boolean fired = false;
if (budget < 0 | fired == true) { System.out.println("Uh oh."); }
else { System.out.println("Still solvent."); }
}
}
Heres the result:
C:\>java App
Still solvent.
In this next example, we insist that the temperature be between 60 and 90 degrees, using the & bitwise logical
operator, before printing out a message:
public class App {
public static void main(String[] args) {
int temperature = 70;
if (temperature < 90 & temperature > 60) {
System.out.println("Time for a picnic."); }
}
}
Heres the result:
C:\>java App
Time for a picnic.
As you can see, the bitwise logical operators can be very useful. Java also includes two logical operators: && and
||. Well take a look at them next.
86
Immediate Solutions
The OR operator (||) returns true if any of its operands is true and false if all operands are false. The AND (&&)
operator returns false if any of its operands is false and true only when all operands result in true.
The && and || operators also have another interesting propertythey are short-circuit operators, which means
that if they can determine all they need to know by evaluating the left operand, they wont evaluate the right
operand. This is very useful in cases such as the following, where we are testing both whether a value holds 0
and whether its reciprocal is less than 1000. If the value is indeed 0, the second part of the expression, where its
reciprocal is calculated, is not executed. This way a divide-by-zero overflow error doesnt occur. Heres the code:
public class App {
public static void main(String[] args) { double value = 0;
if (value != 0 && 1 / value < 1000) {
System.out.println("The value is not too small."); }
else {
System.out.println("The value is too small."); }
}
}
Heres the result:
C:\>java App
The value is too small.
The logical operators differ from the bitwise logical operators because the logical operators are short-circuit
operators. To see this at work, take a look at the following code, where the assignment in the if statement is
performed when we use the & operator but not when we use the && short-circuit operator:
public class App {
public static void main(String[] args) {
double int1 = 0, int2 = 1, int3 = 1;
if (int1 != 0 & (int2 = 2) == 1) { }
System.out.println("int2 = " + int2);
if (int1 != 0 && (int3 = 2) == 1) { }
System.out.println("int3 = " + int3); }
}
Heres the result:
C:\>java App
int2 = 2.0
int3 = 1.0
87
Chapter 3: Operators, Conditionals, and Loops
In this way, the preceding statement works like the following if statement:
if (condition) { value = value1; }
else { value = value2; }
Heres an example where we convert an integer between 0 and 15 into a hexadecimal digit using the ?:
operator. This operator is perfect here, because we can use it to return a string made from the value itself if the
value is less than 10 or a letter digit if the value is 10 or greater, like this:
public class App {
public static void main(String[] args) {
int value = 15;
String digit, chars[] = {"a", "b", "c", "d", "e", "f"};
digit = value < 10 ? String.valueOf(value) : chars[value - 10];
System.out.println(value + " = 0x" + digit); }
}
Heres the result:
C:\>java App
15 = 0xf
88
Immediate Solutions
There are quite a few combination assignment operators. Heres a list of them:
%= (modulus assignment)
&= (bitwise And assignment)
*= (multiplication assignment)
/= (division assignment)
^= (bitwise Xor assignment)
|= (bitwise Or assignment)
+= (addition assignment)
<<= (shift left assignment)
<= (less than or equal to)
-= (subtraction assignment)
>>= (shift right assignment)
>>>= (shift right zero fill assignment)
That completes the list of Java operators, but theres one more popular way of handling math in Javathe Math
class. This class is part of the java.lang package (which the Java compiler imports by default). Well take a
look at this class in the next topic.
89
Chapter 3: Operators, Conditionals, and Loops
Class StrictMath
The StrictMath class consists of methods that let you perform basic numeric operations, such as elementary
exponential, logarithm, square root, and trigonometric functions. The java.lang.StrictMath class is defined with
respect to fdlibm version 5.3. For this class, use IEEE 754 core function version (residing in a file whose name
begins with letter e) where fdlibm provides more than one definition for a function (such as acos). The methods
that require fdlibm semantics are sin, cos, tan, asin, acos, atan, exp, log, log10, cbrt, atan2, pow, sinh, cosh, tanh,
hypot, expm1, and log1p. This ensures the portability of Java program as these methods produce same result
across different platforms. The description of the methods of the StrictMath class is as follows:
static double cbrt (double a)It returns the cube root of a double value.
90
Immediate Solutions
static double cosh(double x)It returns the hyperbolic cosine of a double value.
static double expm1(double x) It returns ex -1.
static double hypot(double x, double y)It returns sqrt(x2 +y2) without intermediate overflow
or underflow.
static double log(double a)It returns the natural logarithm (base e) of a double value.
static double log10(double a)It returns the base 10 logarithm of a double value.
static double log1p(double x)It returns the natural logarithm of the sum of the argument and 1.
static double rint(double a)It returns the double value that is closest in value to the argument
and is equal to a mathematical integer
static double signum(double d)It returns the signum function of the argument; zero if the
argument is zero; 1.0 if the argument is greater than zero; -1.0 if the argument is less than zero.
static float signum(float f) It returns the signum function of the argument; zero if the argument is zero,
1.0f if the argument is greater than zero, -1.0f if the argument is less than zero.
static double sinh(double x)It returns the hyperbolic sine of a double value.
static double tanh(double x)It returns the hyperbolic tangent of a double value
static double toDegrees(double angrad)It converts an angle measured in radians to an
approximately equivalent angle measured in degrees
static double toRadians(double angdeg)It converts an angle measured in degrees to an
approximately equivalent angle measured in radians.
static double ulp(double d)It returns the size of an ulp of the argument.
static float ulp(float f)It returns the size of an ulp of the argument
Comparing Strings
When you are working with the String class, there are some methods you can use much like operators. For
example, you can use the equals method, equalsIgnoreCase() method, and compareTo() method as
follows:
s1.equals(s2)It returns true if s1 equals s2.
s1.equalsIgnoreCase(s2)It returns true if s1 equals s2 (ignoring case).
s1.compareTo(s2)It returns a value less than zero if s1 is less than s2 lexically, returns zero if s1
equals s2, or returns a value greater than zero if s1 is greater than s2.
Heres an example putting these methods to work:
public class App {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = "ABC";
String s4 = "bcd";
if (s1.equals(s2)) { System.out.println("s1 == s2"); }
else { System.out.println("s1 != s2"); }
if (s1.equalsIgnoreCase(s3)) {
System.out.println("s1 == s3 when ignoring case"); }
else { System.out.println("s1 != s3 when ignoring case"); }
if (s1.compareTo(s4) < 0) { System.out.println("s1 < s2"); }
else if (s1.compareTo(s4) == 0){ System.out.println("s1 == s2"); }
else if (s1.compareTo(s4) > 0 ) { System.out.println("s1 > s2"); }
}
}
91
Chapter 3: Operators, Conditionals, and Loops
The if Statement
Hmm, says the Novice Programmer. Im stuck. I want to write an absolute value routine in Java, and I dont
know how to proceed. I dont suppose youve ever heard of the Math classs abs method? you reply. The
what? asks the NP.
The if statement lets you execute a statement or a set of statements depending upon the result of test condition.
However, if the test condition evaluates false, no statement is executed. In general, the if statement is used as
follows:
if (condition)
statement;
Note that statement can be a compound statement also, which means it can be made up of a number of
statements enclosed in curly braces. Heres an answer to what the Novice Programmer was trying to do. Start by
checking whether the value is greater than zero; and if so, just print out the value itself, as done in the following
code:
public class App {
public static void main(String[] args) {
int value = 10;
if(value > 0)
System.out.println("Abs(" + value + ") = " + value); }
}
Heres the result of this code:
C:\>java App
Abs(10) = 10
Another example for the Novice Programmer where an if statement is used to execute multiple statements is as
follows:
public class App {
public static void main(String[] args) {
int value = 10;
if(value > 0) {
System.out.println("The number was positive.");
System.out.println("Abs(" + value + ") = " + value); }
}
}
Heres the result of this code:
C:\>java App
The number was positive.
Abs(10) = 10
92
Immediate Solutions
Nested if Statement
The nested if statement allows that one if statement can be written inside another if statement. Heres an
example to show how a nested if statement works:
public class App {
public static void main(String[] args) {
double value = 2;
if (value != 0) {
if (value > 0)
System.out.println("The result = " + (1 / value));
else
System.out.println("The result = " + (-1 / value)); }
}
}
Heres the result of this code:
C:\>java App
The result = 0.5
93
Chapter 3: Operators, Conditionals, and Loops
case value2:
statement2;
[break;]
case value3:
statement3;
[break;]
. . .
default:
default_statement;
}
Here, the value of expression, which must be of type byte, char, short, or int, is compared against the
various test values in the case statements: value1, value2, and so on. If the expression matches one of the
case statements, the code associated with that case statementstatement1, statement2, and so onis
executed. If execution reaches a break statement, the switch statement ends. Heres an example in which we
display the day of the week based on a numeric value by using a switch statement:
public class App {
public static void main(String[] args) {
int day = 5;
switch(day) {
case 0:
System.out.println("Today is Sunday."); break;
case 1:
System.out.println("Today is Monday."); break;
case 2:
System.out.println("Today is Tuesday."); break;
case 3:
System.out.println("Today is Wednesday."); break;
case 4:
System.out.println("Today is Thursday."); break;
case 5:
System.out.println("Today is Friday."); break;
default:
System.out.println("Today is Saturday."); }
}
}
Heres the result of this code:
C:\>java App
Today is Friday.
Try to execute the preceding example without writing the break statements and see what it returns as the day
today. Youll find that it returns Today is Friday. and Today is Saturday. This signifies that if you
dont specify a break statement at the end of a case statement, the execution will continue with the code in the
next case statement. This may prove useful when you want to execute the same code for multiple case test
values, as shown in the following code:
public class App {
public static void main(String[] args) {
int temperature = 78;
switch(temperature) {
case 60:
case 61:
case 62:
case 63:
case 64:
System.out.println("Very cold"); break;
case 65:
case 66:
case 67:
case 68:
case 69:
System.out.println("It\'s cool"); break;
case 70:
case 71:
94
Immediate Solutions
case 72:
case 73:
case 74:
case 75:
System.out.println("It\'s warm"); break;
default:
System.out.println("Uff, very hot!! "); } }
}
Heres the result of this code:
C:\>java App
Uff, very hot!!
Note that a default case executes if none of the above cases match or when no break statements are specified.
95
Chapter 3: Operators, Conditionals, and Loops
Current value = 3
Current value = 2
Current value = 1
Heres an example where a while loop has been used to calculate the factorial of 6:
public class App {
public static void main(String[] args) {
int value = 6, factorial = 1, temp;
temp = value; //make a destructive copy.
while (temp > 0) { factorial *= temp--; }
System.out.println(value + "! = " + factorial); }
}
Heres how the program calculates the factorial of 6:
C:\>java App
6! = 720
A more advanced example is as follows:
import java.util.*;
public class App { public static void main(String[] args) {
int value = 32, temp = value;
StringBuffer sb = new StringBuffer();
Stack <String> st = new Stack <String>();
while (temp > 0) {
st.push(String.valueOf(temp % 16));
temp >>>= 4; }
while(!st.empty()) { sb.append(new String((String) st.pop())); }
System.out.println("Converting " + value + " to Hexadecimal yields 0x" + sb); }
}
In this case, we are converting a number into hexadecimal by successively stripping off hex digits with the
modulus operator. Because the digits come out in reverse order, we are using a while loop to push them onto a
Java stack, which youll see when we discuss the collection classes. After pushing the digits onto the stack, we
pop them in another while loop to reverse the order of the digits and create the StringBuffer object to
display.
Heres what this programs output looks like:
C:\>java App
Converting 32 to Hexadecimal yields 0x20
Heres a fact that can come in handy: Because null statements are valid in Java, a while loop doesnt have to
have a body at all. Heres an example showing a crude way of calculating an integer square root (note that all the
work here takes place in the condition part of the loop):
public class App { public static void main(String[] args) {
int target = 144, sqrt = 1;
while (++(sqrt) * (sqrt) != target) ;
System.out.println("sqrt(" + target + ") = " + sqrt); }
}
Heres the result:
C:\>java App
sqrt(144) = 12
Another type of while loopthe do-while loopis discussed in the next topic.
96
Immediate Solutions
It can be seen in the preceding lines that a do-while loop will always execute at least once even if the condition
evaluates to false. This is because the condition is tested after the loop body gets executed. Heres an example to
show how a do-while loop works:
public class App {
public static void main(String[] args) {
int values[] = {1, 2, 3, 0, 5}, test, index = 0;
do {
test = 5 * values[index++];
System.out.println(test);
} while (test < 15); }
}
The result is as follows:
C:\>java App
5
10
15
Question arises when to use a while loop and when to use a do-while loop? The answer is whenever the
situation demands that looping statements should execute only if the condition is true, you use a while loop.
The following code makes it clearer, where a do-while loop evaluates the reciprocal of a value but can only
test whether the value is a nonzero value at the end of the loop:
public class App {
public static void main(String[] args) {
double value = 0;
do {
System.out.println("The reciprocal = " + 1 / value);
} while (value > 0);
}
}
Its far better in this case to use a while loop to test for 0 first:
public class App {
public static void main(String[] args) {
double value = 0;
while (value > 0) {
System.out.println("The reciprocal = " + 1 / value); }
}
}
97
Chapter 3: Operators, Conditionals, and Loops
98
Immediate Solutions
99
Chapter 3: Operators, Conditionals, and Loops
Here, country is a variable of enumeration type Country. Each of the values in the enumeration is passed to
the variable and thus display on the screen:
C:\> java App
The country is India
The country is Japan
The country is China
The construct for (variable: collection) doesnt add any new keywords to the language.
Alternatively, it extends the meaning of the basic for loop. This for-each loop says, for each element in the
collection, assigns it to the variable element, and executes the statement.
The construct works for both arrays and implementations of the Collection interface, like ArrayList,
HashSet, and the keys from a Map like a Properties object. As you can infer from their names, the
collection classes let you group elements in various ways. The collection classes also define various methods that
make working with those items easier. Collection was finally added by J2SE 1.2. With the new versions of JDK,
the power of Collection Framework has significantly increased and its use has been streamlined.
In fact, it has simplified the way you track a group of objects. A few simple methods are needed to use collection
classes. Youll learn more about the collections in Chapter 21. Before moving onto the program, lets learn about
the most basic collection class, ArrayList. An ArrayList is similar to an array but avoids many of the most
common problems of arrays. For example, an array cant grow or shrink in size once created; therefore, you must
know in advance the size of an array, whereas an ArrayList supports dynamic arrays that can grow or shrink in
size as per the need.
The following program shows the case of using the for-each construct with a Collection:
import java.util.ArrayList;
public class ForLoopTest {
public static void main(String[] args)
//args the command line arguments
{
double[] array = {2.5, 5.2, 7.9, 4.3, 2.0, 4.1, 7.3, 0.1, 2.6};
//leave details of the loop such as indices out of the picture
for(double d: array) { System.out.println(d); }
System.out.println("---------------------");
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(7);
list.add(15);
list.add(-67);
for(Integer number: list) { System.out.println(number); }
System.out.println("---------------------");
//Works identically with autounboxing
for(int item: list) { System.out.println(item); }
System.out.println("---------------------"); }
}
Look at the line here as you can specify the type of elements the array list is allowed to contain. This statement
creates an array list that holds Integer objects:
ArrayList<Integer> list = new ArrayList<Integer>()
Heres the output of this code:
C:\>java ForLoopTest
2.5
5.2
7.9
4.3
2.0
4.1
7.3
0.1
2.6
---------------------
7
100
Immediate Solutions
15
-67
---------------------
7
15
-67
A (Poor) Solution
To allow the client code to work with all products, you could create a method in the Catalog that returned the
ArrayList of products:
List<Product> getProducts() { return products; }
For choosing an object in the list the client code would have to iterate through the list. However, returning a
collection to a client is not feasible. If this is done, the client can modify the list in your collection, as you have
given the control over the contents of that collection to the client. And hence, the client code could add or
remove elements to the collection without the knowledge of the Catalog object. Moreover, the client will have
to do more work than necessary.
Significance of for-each
The for-each loop provides a simple, consistent solution for iterating arrays, collection classes, and even your
own collections. It helps eliminate much of the repetitive code that you would otherwise require. They also
eliminate the need for casting as well as other potential problems related to iteration. This is one such addition to
Java that was long overdue.
The for-each loop can be used with both collections and arrays. The basic function is to simplify the most
common form of iteration, where the iterator or index is used solely for iteration, and not for any other kind of
operation, such as removing or editing an item in the collection or array. When there is a choice, the for-each
loop should be preferred over the for loop, since it increases legibility. Here is an example on for-each loop:
import java.util.*;
import java.math.BigDecimal;
public final class For_each_Examples {
101
Chapter 3: Operators, Conditionals, and Loops
Nested Loops
Im working with a two-dimensional array, the Novice Programmer says, and I almost wish I could have a
loop within a loop, so I could loop over both dimensions. Of course you can use loops within loops, you reply.
Java lets you nest loops, one within another. Heres an example showing how this works (in this case, we are
finding the average value of the elements in a two-dimensional array by looping over all the elements with two
for loops):
public class App {
public static void main(String[] args) {
double array[][] = {{1, 2, 3}, {3, 2, 1}, {1, 2, 3}};
int sum = 0, total = 0;
for(int outer_index = 0; outer_index < array.length;
outer_index++) {
for(int inner_index = 0; inner_index <
array[outer_index].length; inner_index++) {
sum += array[outer_index][inner_index];
total++; } }
System.out.println("Average array value = " + (sum / total)); }
}
Heres the result of this code:
C:\>java App
Average array value = 2
102
Immediate Solutions
103
Chapter 3: Operators, Conditionals, and Loops
To skip to the next iteration of a loop, you can use the continue statement. Heres an example in which we are
printing out reciprocals, and we want to avoid trying to print out the reciprocal of 0. If the current loop index
equals 0, we skip the current iteration and move on to the next one. Heres the code:
public class App {
public static void main(String[] args) {
for(double loop_index = 5; loop_index > -5; loop_index--) {
if (loop_index == 0) continue;
System.out.println("The reciprocal of " + loop_index +
" = " + (1 / loop_index)); }
}
}
Heres the result of this code (note that this output skips over the line where the code would try to calculate the
reciprocal of 0):
C:\>java App
The reciprocal of 5.0 = 0.2
The reciprocal of 4.0 = 0.25
The reciprocal of 3.0 = 0.3333333333333333
The reciprocal of 2.0 = 0.5
The reciprocal of 1.0 = 1.0
The reciprocal of -1.0 = -1.0
The reciprocal of -2.0 = -0.5
The reciprocal of -3.0 = -0.3333333333333333
The reciprocal of -4.0 = -0.25
Summary
In this chapter, we have discussed about the operators, conditionals, jump statements, and loops. You also
understood how to work with operators, use the Math Class, the StrictMath Class, compare strings, use
strings in switch statement, and use the conditional statements. You have also learned about the implementation
of iterative control structure. Towards the end, you have studied about the nested loops and the jump
statements.
The next chapter will discuss about object oriented programming.
104
4
Object-Oriented
Programming
If you need an immediate solution to: See page:
Declaring and Defining Classes 111
Declaring and Creating Objects 112
Creating Instance Variables 114
Setting Variable Access 114
Creating Class Variables 115
Creating Methods 116
Setting Method Access 116
Passing Parameters to Methods 117
Command-Line Arguments Passed to main() method 118
Returning Values from Methods 118
Creating Class Methods 119
Creating Data Access Methods 120
Creating Constructors 120
Passing Parameters to Constructors 121
A Full Class Example 121
Understanding Variable Scope 122
Using Recursion 123
Garbage Collection and Memory Management 123
Garbage Collection and the finalize() Method 125
Overloading Methods 125
Overloading Constructors 126
Passing Objects to Methods 126
Passing Arrays to Methods 127
Using the this Keyword 128
Chapter 4: Object-Oriented Programming
106
In Depth
In Depth
This chapter is all about a topic central to any Java programObject-Oriented Programming (OOP). We first
discussed Object-Oriented Programming in Chapter 1 because you cannot write Java code without it. Now that
you have come up through the basics of Java syntax, you are ready to work with Object-Oriented Programming
in a formal way.
Object-Oriented Programming is really just another technique to let you implement that famous programming
dictumdivide and conquer. The idea is that you encapsulate data and methods into objects, making each object
semi-autonomous, enclosing private (i.e., purely internal) data and methods in a way that stops them from
cluttering the general namespace. The object can then interact with the rest of the program through a well-
defined interface as implemented by its public (i.e., externally callable) methods.
Object-Oriented Programming was first created to handle larger programs by breaking them up into functional
units. It takes the idea of breaking a program into subroutines one step further, because objects can have both
multiple subroutines and data inside them. The result of encapsulating parts of your program into an object is
that it is easily conceptualized as a single item, instead of you having to deal with all that makes up that object
internally.
Imagine how your kitchen would look filled with pipes, pumps, a compressor, and all kinds of switches used to
keep food cold. Every time the temperature of the food got too high, you would have to turn on the compressor
and open valves and start cranking the pumps manually. Now wrap all that functionality into an objecta
refrigeratorin which all those operations are handled internally, with the appropriate feedback between the
parts of the object handled automatically inside the object. Thats the idea behind encapsulationtaking a
complex system that demands a lot of attention and turning it into an object that handles all its own work
internally and can be easily conceptualized, much like a refrigerator. If the first dictum of Object-Oriented
Programming is divide and conquer, the second is surely out of sight, out of mind.
In Java, Object-Oriented Programming revolves around a few key conceptsclasses, objects, data members,
methods, and inheritance. Heres what those terms mean in overview:
ClassThis is a template from which you can create objects. The definition of a class includes the formal
specifications for the class, and any data and methods in it.
ObjectThis is an instance of a class, much as a variable is an instance of a data type. You can think of a
class as the type of an object, and you can think of the object as an instance of a class. Objects encapsulate
methods and instance variables.
Data membersThese are variables that are part of a class. You use them to store the data the object uses.
Objects support both instance variables whose values are specific to the object, and class variables whose
values are shared among the objects of that class.
MethodThis is a function built into a class or an object. You can have instance methods and class
methods. You use instance methods with objects, but you can use a class method just by referring to the
class by nameno object is required.
InheritanceThis is the process of deriving one class, called the derived class, from another, called the base
class, and being able to make use of the members of the base class in the derived class.
All these constructs are important to Object-Oriented Programming, and well get into more details on each of
them now.
If you are used to working with Object-Oriented Programming in C++, it may surprise you to learn that although Java programs
are object-oriented, the object-oriented support in Java is less than whats available in languages, such as C++. For example,
the designers of Java decided to let programmers overload methods but not operators (although Java itself overloads operators,
such as + for the String class). Also, Java does not support destructors and multiple inheritances directlyinstead Java
interfaces are used.
107
Chapter 4: Object-Oriented Programming
Classes
In Object-Oriented Programming, classes provide a sort of template for objects. That is, if you think of a class as a
cookie cutter, the objects you create from it are the cookies. You can consider a class an objects typeyou use a
class to create an object and then you can call the objects methods from your code.
To create an object, you call a classs constructor, which is a method with the same name as the class itself. This
constructor creates a new object of the class. We have been creating classes throughout this book already; each
time you create a Java program, you need a class. For example, heres how to create a class named App, which is
stored in a file named App.java (this class creates a Java application):
public class App { //Object-Oriented Programming
public static void main(String[] args) {
System.out.println("Hello from Java!"); }
}
When you use the Java compiler, this file, App.java, is translated into the bytecode file App.class, which
holds the complete specification for the App class. So, how do you create objects from classes? Take a look at the
next section.
Objects
In Java, you call an instance of a class an object. To create an object, you call a classs constructor, which has the
same name as the class itself. Heres an example in which we create an object from the Java String class,
passing the string we want to enclose in that object to the String classs constructor:
String s = new String("Hello from Java!");
Youll see more about creating objects with constructors throughout this chapter. So, what do you do with an
object when you have one? You can interact with it using its data members and methods; take a look at the next
two sections.
Data Members
Data members of an object are called instance data members or instance variables. Data items shared by all objects of
a class are called class data members or class variables. Youll see how to create both instance variables and class
variables in this chapter. Data members can be accessible outside an object, or you can make them internal to the
object for the private use of the methods inside the object.
Heres an example showing how you might use an objects data member; say you have a class named
Data_class, and you create an object of this class named data1:
Data_class data1 = new Data_class("Hello from Java!");
. . .
If Data_class defines a publicly accessible data member named data, you can refer to the data member of
data1 by using the dot operator (.), like this:
data1.data
That means you can print out the data in data1, like this:
Data_class data1 = new Data_class("Hello from Java!");
System.out.println(data1.data);
In this way, you can refer to the data members of an object that the object makes publicly accessible. On the other
hand, recall that data hiding is one of the motivations behind Object-Oriented Programming, and giving code
outside an object access to the internal data of an object might not be a good idea. Instead, you often give code
outside an object access to the objects data only through the objects methods (which mean you can control the
objects interface to the rest of the program, checking data values before those values are stored in the objects
data members).
Methods
Methods are the functions built into a class and therefore built into the objects you create from that class. You
usually divide methods into those intended for use inside the class, called private methods, those intended for use
outside the class, called public methods, and those intended for use by the class and those classes you derive from
108
In Depth
it, called protected methods. Private methods are usually only called inside the object itself by other parts of the
object. In the Previously-mentioned refrigerator example, for instance, the thermostat may call an entirely
internal method named start_compressor when its time to get cold. Once you have an object that supports
methods, you can use that objects methods. In the following example, we use the calculate() method to
work with the two values in operand1 and operand2 and store the result of the calculation in result:
Calculator calc = new Calculator();
result = calc.calculate(operand1, operand2);
Java supports two types of methods: class methods and instance methods. Instance methods, like the
calculate() example here, are invoked on objects (i.e., objects are instances of a class). Class methods, on the
other hand, are invoked on a class. For example, the java.lang.Math class has a class method named sqrt()
that calculates a square root, and you can use it like this (no object is needed):
public class App {
public static void main(String[] args) {
double value = 4, sqrt;
sqrt = Math.sqrt(value);
System.out.println("The square root of " + value + " = " + sqrt); }
}
Heres what you see when you run this code:
C:\>java App
The square root of 4.0 = 2.0
Youll learn how to create both instance and class methods in this chapter. Theres one more object-oriented
concept to master before we get to the codeinheritance.
Inheritance
Inheritance is one of the formally defining aspects of Object-Oriented Programming. Using inheritance, you can
derive a new class from an old class, and the new class will inherit all the methods and member data of the old
class. The new class is called the derived class, and the original class is called the base class. The idea here is that
you add what you want to the new class to give it more customized functionality than the base class.
For example, if you have a class named Vehicle, you might derive a new class named Car from Vehicle and
add a new method called horn() that prints beep when called. In that way, you have created a new class from
a base class and have augmented that class with an additional method. Inheritance is an important topic in Java
because you can use the huge class libraries available in Java by deriving your own classes from them. Youll see
how to use object-oriented inheritance in the next chapter.
Exception Handling
An exception refers to an event that occurs when a program is not being executed in the normal flow, i.e., not
according to the instructions. Each type of exception is represented by a different exception class:
IllegalArgumentExceptionIt occurs when passing an incorrect argument to a method.
InputMismatchExceptionIt occurs when the console input doesnt match the data type expected by a
method of the Scanner class.
ArithmeticExceptionIt occurs when an illegal type of arithmetic operation is performed.
IOExceptionIt occurs when the I/O encountered an unrecoverable I/O error.
ClassNotFoundExceptionIt occurs when a necessary class couldnt be found.
They are just some exceptions that youll find as you read on. Each of these topics is important, and well take a
look at them in overview now.
Exception handling is the way that Java handles runtime errors. The basis of exception handling is the try block,
in which you place code that can cause exceptions. In fact, youll see this throughout the book, such as in this
example, where an operation using an InputStreamReader can generate an exception (called throwing an
exception), which is then caught and handled in a catch block:
import java.io.*;
class App {
public static void main(String args[]) {
109
Chapter 4: Object-Oriented Programming
try {
int character;
InputStreamReader reader = new
InputStreamReader(System.in);
while ((character = reader.read()) != -1) {
System.out.print((char) character); } }
catch (IOException e) { System.out.println("Error occurred!"); }
}
}
Youll know more on InputStreamReader in later chapters. But for now, it is important for you to know that it
reads bytes and translates them into characters according to a specified character encoding.
Using Javas built- in I/O classes, you can open a file for reading, outputting each line to the screen until the end
of the file is reached. Such I/O operations do generate errors, so these I/O operations are typically placed in try
blocks, because theyre error-proneJava will usually insist that you use a try/catch block (and if you dont,
itll ask you to do so when you try to compile your code).
Here, the sensitive operation is enclosed in a try block; and if an exception occurs, its caught in the catch
block. You can do various things in the catch block, such as attempt to recover from the exception, ignore it,
inform the user, and so on. Youll see the options in this chapter.
Its a good idea to handle exceptions yourself in any program you release for general use because if you dont, Java passes the
exception on to the default exception handler, which prints out its internal stack and terminates your program.
Debugging
Exception handling lets you work with runtime errors, but theres another kind of error: logic errors in your
code (also known as bugs). Java provides a debugging tool the jdb toolthat lets you single-step through
your code, set breakpoints in your code that halt execution when you reach them, examine the variables of a
program while its executing, and more. Well take a look at the jdb tool in this chapter.
Thats it for the overview of whats in this chapter. Theres a great deal of material here, and its time to turn to
the Immediate Solutions section and master OOP in detail. All this material is essential for Java programming,
so keep digging into it until youve made it your own.
110
Immediate Solutions
Immediate Solutions
Declaring and Defining Classes
A Novice Programmer is excited and says, I have done it! I have created an objectit worked! Fine, you say
approvingly, now how about creating a class? The NP says, How does that work?
There are two parts for setting up a class in Java: the class declaration and the class definition. The declaration
tells Java what it needs to know about the new class. The general form of a class declaration is as follows:
[access] class classname [extends ...] [implements ...] {
//class definition goes here.
}
The actual implementation of the class is called the class definition, and it makes up the body of the class
declaration, which you can see in the preceding sample code. The general form of a class declaration and
definition is as follows:
access class classname [extends ...] [implements ...] {
[access] [static] type variable1;
. . .
[access] [static] type variableN;
[access] [static] returntype method1 (parameter_list) { . . . }
. . .
[access] [static] returntype methodN (parameter_list) { . . . }
}
The static keyword in the general form turns variables into class variables and methods into class methods (as
opposed to instance variables and methods), as youll see later. The access term specifies the accessibility of the
class or class member to the rest of the program, and it can be public, private, or protected. Theres also
a default access if you dont specify an access type; youll learn about this in the next few pages. You use the
extends and implements keywords with inheritance, which youll see in the next chapter.
An example will make this all clear. To start, well just create a very simple class named Printer that defines
one method print(). When we call the print() method, it displays the message Hello from Java! on the
console. The Printer class appears as follows:
class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
Now we can make use of the print() method in other classes, as in this example, where were creating a new
object of the Printer class by using the new operator and that objects print() method in an application
named App:
class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
public class App {
public static void main(String[] args) {
Printer printer1 = new Printer();
printer1.print(); }
}
Now we put this code in a file (App.java), compile it, and then run it as follows:
C:\>java App
Hello from Java!
Note that were declaring and defining two classes, Printer and App, in the same file. Only one class can be
declared public in one file, and thats App in this case. The file itself must be named after that class, which
means the containing file must be App.java. However, you can have as many private or protected classes as
you like in the file (and Java will create separate .class files for them when you compile the file).
111
Chapter 4: Object-Oriented Programming
You can also divide this example into two files, one for each class. Heres Printer.java that displays a
message:
package printer;
class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
The new App.java is as follows:
import printer.Printer;
public class App {
public static void main(String[] args) {
Printer printer1 = new Printer();
printer1.print(); }
}
Note that we had to import the Printer class to be able to use it; see Chapter 1 for more on importing classes.
Actually, you dont need to declare an object in all cases before using it. In some cases, Java creates an object for you
automatically, as is the case with string literals, which Java treats like String objects. This means that expressions such as
Hello from Java!.length() are valid.
112
Immediate Solutions
Classes often have several different constructors, each of which can take a different data specification (i.e.,
different parameter types and number of parameters; the Java compiler knows which constructor you want to
use by noting how the types of the parameters are used and how many parameters are there). In object-oriented
terms, these constructors are overloaded, and well cover overloading in this chapter. For example, the String
classs constructor is overloaded to take character arrays as well as text strings, so we can create a new object, s3,
using a character array, like this:
public class App {
public static void main(String[] args) {
String s1;
s1 = new String("Hello from Java!");
String s2 = new String("Hello from Java!");
char c1[] = {'H', 'i', ' ', 't', 'h', 'e', 'r', 'e'};
String s3 = new String(c1);
. . . }
}
Sometimes classes will have methods that return objects, which means theyll use the new operator internally
(and you dont have to). Heres an example, using the valueOf() method of the String class, in which we
convert a double into a String object:
public class App {
public static void main(String[] args) {
String s1; s1 = new String("Hello from Java!");
String s2 = new String("Hello from Java!");
char c1[] = {'H', 'i', ' ', 't', 'h', 'e', 'r', 'e'};
String s3 = new String(c1);
double double1 = 1.23456789;
String s4 = String.valueOf(double1);
. . . }
}
In addition, you can assign one object to another, as we have done here:
public class App {
public static void main(String[] args) {
String s1;
s1 = new String("Hello from Java!");
String s2 = new String("Hello from Java!");
char c1[] = {'H', 'i', ' ', 't', 'h', 'e', 'r', 'e'};
String s3 = new String(c1);
double double1 = 1.23456789;
String s4 = String.valueOf(double1);
String s5;
s5 = s1;
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
System.out.println(s5); }
}
Internally, whats really happening is that the object reference in s1 is copied to s5. What this means in practice
is that s1 and s5 refer to the same object. Thats important to know, because if you change the instance data in
s1, youre also changing the instance data in s5, and vice versa. If two variables refer to the same object, be
carefulmultiple references to the same object can create some extremely hard-to-find bugs. This usually
happens when you think youre really dealing with different objects.
At the end of the preceding code, we print out all the strings weve created. Heres what appears when the
program is run:
C:\>java App
Hello from Java!
Hello from Java!
Hi there
1.23456789
Hello from Java!
113
Chapter 4: Object-Oriented Programming
Thats how to declare and create objectsmuch the same way you declare and create simple variables, with the
added power of configuring objects by passing data to a classs constructor. Its time to start creating your own
classes, and well start that process in the next solution.
114
Immediate Solutions
115
Chapter 4: Object-Oriented Programming
Creating Methods
OK, says the Novice Programmer, I have got instance variables down now. Is there anything more to learn
about classes? Plenty, you say. Pull up a chair and well talk about creating methods.
Till now, we have used a lot of methods; the most commonly used is the method println() in the statement
System.out.println() to display the output at the console.
A method is a code block that you can transfer control to so as to execute that code. Heres how you create
methods in a class:
access class classname [extends ...] [implements ...] {
[access] [static] returntype method1 (parameter_list) { . . . }
. . .
[access] [static] returntype methodN (parameter_list) { . . . }
}
To declare and define a method, you use an access specifier (see the next topic), specify the return type of the
method if you want it to return a value (such as int, float, an object type, or void if the method doesnt
return any value), give the methods name and place the list of the parameters you intend to pass to the method
after that name. The actual method body is written after the methods declaration and contains the instructions
that are executed when the method is called. Lets get to an example. In fact, youve already seen one earlier in
this chapterthe Printer class. In that example, we added a public method named print() to the Printer
class, created an object of the Printer class, and called the print() method, like this:
class Printer {
public void print() { System.out.println("Hello from Java!"); }
}
public class App {
public static void main(String[] args) {
Printer printer1 = new Printer();
printer1.print(); }
}
In this case, the print() method takes no parameters and returns no value, but we still use parentheses after
the methods namethis is mandatory when you are defining or calling a method in Java (its mandatory
because thats how the Java compiler knows print() is a method and not a data member). Heres the output of
this code:
C:\>java App
Hello from Java!
Theres a lot to know about creating methods in Java, so were going to elaborate on the process over the next
few topics. One of the most important aspects of methods is that you can make them purely internal to an object,
in keeping with the object-oriented concept of encapsulationand thats where well start.
116
Immediate Solutions
{ . . . }
. . .
[access] [static] returntype methodN (parameter_list)
{ . . . }
}
The access specifier access can contain three possible values: public, private, and protected. You can
find the details of them in Table 4.1.
Heres an example in which we add a private method to the Printer class developed over the last few
topics. This method may only be called from other methods in the Printer class, like this:
class Printer {
public void print() { internal_use_only(); }
private void internal_use_only () {
System.out.println("Hello from Java!"); }
}
public class App {
public static void main(String[] args) {
Printer printer1 = new Printer(); printer1.print(); }
}
When you call the Printer classs print() method, it makes use of the internal_use_only() method,
which is inaccessible outside the object, to do the actual printing.
Heres the result of this code:
C:\>java App
Hello from Java!
Making methods private or protected is often a good idea because it reduces or controls the methods
accessibility from the rest of the code.
}
}
Heres the result of this code:
C:\>java App
Hello again from Java!
117
Chapter 4: Object-Oriented Programming
If you have more than one parameter to pass, you can specify multiple parameters in the parameter list,
separated by commas:
class Calculator {
int additems(int op1, int op2) {
int result = op1 + op2;
. . . }
}
You can call methods using literals, variables, arrays, or objects, like this:
calc.additems(1, int1, array1, obj1)
You should note that when you pass a simple variable or literal to a method, the value of the variable or literal is
passed to the methodthis process is called passing by value. On the other hand, when you pass an object or
array, you are really passing a reference to that object or array (in fact, when you store an array or object in a
variable, what youre really storing is a reference to the array or object). For that reason, the code in the called
method has direct access to the original array or object, not a copy of it. Therefore, if that code changes some
aspect of the array or object, such as an element in the array or a data member of the object, the original array or
original object is changed. Well take another look at this in detail in the topics, Passing Objects to Methods
and Passing Arrays to Methods, later in this chapter.
118
Immediate Solutions
The return type can be any type that Java recognizesfor example, int, float, double, the name of a class
youve defined, int[] to return an integer array, or float[] to return a float array. Heres an example in
which the class Calculator has a method named additems() that takes two integer parameters, adds them,
and returns the result. Heres how we declare additems():
class Calculator {
int additems(int op1, int op2) { return result; }
}
Heres how we return the sum of the values passed to additems(), using the return statement:
class Calculator { int additems(int op1, int op2) { return op1 + op2; } }
Heres how we put the Calculator class to work in a program:
class Calculator { int additems(int op1, int op2) { return op1 + op2; } }
public class App {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("additems(2,2) = " + calc.additems(2,2)); }
}
Heres the result of this application:
C:\>java App
additems(2,2) = 4
So how do you call non-static methods from main? You do this as we have been doing it throughout the bookyou create an
object of some other class in main and call the methods of that object.
119
Chapter 4: Object-Oriented Programming
Creating Constructors
Hmm, says the Novice Programmer, I know I can use constructors to initialize the data in an object, such as
the String classs constructors that I use to set the text in a string, but Yes? you ask. But how can I create
constructors for my own classes? the NP asks.
Creating a constructor for a class is easy; you just add a method to a class with the same name as the class, with
or without any access specifier and having no return type. Heres an example in which we add a constructor that
takes no parameters to the Printer class weve developed in this chapter. This constructor is called when an
object is created of the Printer class; and in this case, it initializes the internal data data_string to Hello
from Java! (Note that we still need the parentheses after the constructor name when declaring it, even though it
doesnt take any parameters):
class Data {
private String data_string;
Data() { data_string = "Hello from Java!"; }
public String getData() { return data_string; }
}
120
Immediate Solutions
121
Chapter 4: Object-Oriented Programming
122
Immediate Solutions
Using Recursion
The Novice Programmer comes in still shaking with laughter and says, Youll never believe what the
Programming Correctness Czar just told mein C++, methods can call themselves! Its the same in Java, you
reply. Huh? the NP says.
Each time you call a method in Java, Java allocates new space on its internal stack for all the variables in the
method, which means theres no reason you cant call the same method againa new set of variables will be
allocated on the stack automatically. Whats more, a method can call itself in Javathis is a technique called
recursion.
The classic recursion example is to calculate a factorial, so well implement it here. To calculate the factorial of
positive integer n, you calculate the following:
n! = n * (n - 1) * (n - 2) ... * 2 * 1
This process lends itself to recursion easily because each stage of the recursion can calculate one multiplication in
which it multiplies the number it has been passed by the factorial of the number minus 1. When the number has
finally been reduced to 1 through successive calls, the method simply returns, and control comes back through
the successive stages, performing one multiplication at each stage until all nested calls have returned and you
have the factorial.
Heres what this looks like in code:
class Calculator {
public int factorial(int n) {
if (n == 1) { return n; }
else { return n * factorial(n - 1); }
}
}
public class App {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("6! = " + calc.factorial(6)); }
}
Heres what this program looks like at work:
C:\>java App
6! = 720
In practice, you probably wont use recursion too often, but its good to know its available.
123
Chapter 4: Object-Oriented Programming
in which were just creating a new object and then setting its variable to null. Because there are no remaining
references to the object, the garbage collection process will deallocate it sooner or later. Heres the code:
class Data {
public int intdata = 0;
Data() { intdata = 1; }
}
public class App {
public static void main(String[] args) {
Data d = new Data(); //some code...
d = null; } //some additional code...
}
Heres the thing to remember from this example: When you are done with a data itemincluding objects and
arraysthat youve allocated with the new operator, you can set its references to null, and if Java needs more
memory, itll start the garbage collection process. However, you have to be careful to avoid circular references.
If you are familiar with C++, you may be wondering where pointers are in Java, and the answer is that it doesnt have them. The
designers of Java omitted pointers for security reasons to make sure programmers couldnt access memory beyond legal
limits. Instead of pointers, Java uses references, which act very much like pointers behind the scenes. When you create a new
object, you get a reference to that object, and when you use that reference, Java de-references it for you automatically. Thats
how it works in JavaJava handles references (pointers) for you automatically.
124
Immediate Solutions
Overloading Methods
Im still working on my new program, SuperDuperMathPro, says the Novice Programmer, and I have a
great class named Calculator with a method named additems() that adds two numbers. Id also like to add
three numbers together, though, I guess Ill have to write a new method. Not at all, you say. You can
overload the additems() method to handle either two or three operands. Hows that? the NP asks.
Method overloading is an object-oriented technique that lets you define several different versions of a method, all
with the same name, but each with a different parameter list. When you use an overloaded method, the Java
compiler will know which one you mean by the number and/or types of the parameters you pass to the method,
finding the version of the method with the right parameter list.
Lets take a look at an example. To overload a method, you just define it more than once, specifying a new
parameter list each time. Each parameter list must be different from every other one in some way, such as the
number of parameters or the type of one or more parameters. Well create an example the Novice Programmer
was worried about here. First, we add a version of the additems() method to the Calculator class that will
handle two operands:
class Calculator {
int additems(int op1, int op2) {return op1 + op2; }
. . .
}
Then we add another version of the same method that will take three operands:
class Calculator {
int additems(int op1, int op2) { return op1 + op2; }
int additems(int op1, int op2, int op3) { return op1 + op2 + op3; }
}
Now we can use both methods in code, like this:
public class App {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("additems(2,2) = " + calc.additems(2,2));
System.out.println("additems(2,2,2) = " + calc.additems(2,2,2)); }
}
125
Chapter 4: Object-Oriented Programming
Overloading Constructors
Alright, says the Novice Programmer, so I can overload methods in Java to let them handle different parameter
lists! Can I also overload constructors? Of course, you say. Consider the Java String class, which has a
constructor to which you can pass strings, character arrays, and all other kinds of data. Oh yeah, says the NP.
Overloading constructors work like overloading other methods (see the previous topic for details): You just
define the constructor a number of times, each time with a parameter list with parameters that differ from the
other lists in some way.
Heres an example that mimics the Java String classs constructors in this new class, the Data class, will have a
constructor to which you can pass either a character array or a string. This class will simply store the text data
you pass to it and make that data available with a getData() method.
Heres how we declare and define the constructor that takes a character array:
class Data {
private String data_string;
Data(char[] c) { data_string = new String(c); }
}
Heres how we declare the constructor that takes a text string:
class Data {
private String data_string;
Data(char[] c) { data_string = new String(c); }
Data(String s) { data_string = s; }
}
All thats left is to add the getData() method:
class Data {
private String data_string;
Data(char[] c) { data_string = new String(c); }
Data(String s) { data_string = s; }
public String getData() { return data_string; }
}
Now we can use both constructors in code, creating objects and printing out the stored text, like this:
public class App {
public static void main(String[] args) {
char chararray[] = {'H', 'e', 'l', 'l', 'o'};
System.out.println((new Data(chararray)).getData());
System.out.println((new Data("Hello from Java!")).getData()); }
}
Heres the result of this code:
C:\>java App
Hello
Hello from Java!
However, when you pass an object to a method, Java actually passes a reference to the object, which is called
passing by reference. Passing by reference means that the code in the method can reach the original object. In fact,
any changes made to the passed object affect the original object.
Heres an example in which we pass an object of class Data to the print() method of the Printer class in
order to print out the data in the object:
class Data {
public String data_string;
Data(String data) { data_string = data; }
}
class Printer {
public void print (Data d) { System.out.println(d.data_string); }
}
public class App {
public static void main(String[] args) {
Data data = new Data("Hello from Java!");
Printer p = new Printer();
p.print(data); }
}
Heres the result of this code:
C:\>java App
Hello from Java!
As mentioned previously, because objects are passed by reference, changing a passed object changes the original
object. Heres an example in which we pass an object of the Data class to a method named rewrite() that
changes the data_string instance variable in the object. This variable starts out with the string Hello from
Java! in it, but the rewrite() method is able to change the string to Hello to Java! in this code:
class Data {
public String data_string;
Data(String s) { data_string = new String(s); }
}
class Data2 {
public void rewrite(Data d) { d.data_string = "Hello to Java!"; } }
public class App {
public static void main(String[] args) {
Data d = new Data("Hello from Java!");
Data2 d2 = new Data2();
d2.rewrite(d);
System.out.println(d.data_string); }
}
Heres the result of this code:
C:\>java App
Hello to Java!
127
Chapter 4: Object-Oriented Programming
}
public class App {
public static void main(String[] args) {
int array[] = {5,3,6,1,7};
Calculate c = new Calculate();
System.out.println("Before calling the doubleValue()...");
for (int loop_index = 0; loop_index < array.length; loop_index++) {
System.out.println("array[" + loop_index + "] = " +
array[loop_index]); }
c.doubleValue(array);
System.out.println("After calling the doubleValue()...");
for (int loop_index = 0; loop_index < array.length; loop_index++) {
System.out.println("array[" + loop_index + "] = " +
array[loop_index]); }
}
}
Heres the result of this code:
C:\>java App
Before calling the doubleValue()...
array[0] = 5
array[1] = 3
array[2] = 6
array[3] = 1
array[4] = 7
After calling the doubleValue()...
array[0] = 10
array[1] = 6
array[2] = 12
array[3] = 2
array[4] = 14
128
Immediate Solutions
129
Chapter 4: Object-Oriented Programming
Java was enriched the lang package by two new classes: the ProcessBuilder class and the
StringBuilder class.
This class is not at all synchronized. If an instance of the ProcessBuilder class is retrieved concurrently by multiple threads and
at least one of the attributes is modified structurally by one of the threads, it must be externally synchronized.
It is very easy to start a new process, which make use of both the default working directory and environment.
For example:
import java.io.*;
public class App {
public static void main(String args[])
throws IOException {
ProcessBuilder pb=new ProcessBuilder("notepad.exe", "nfile.java");
pb.start(); }
}
In the previous program, we have used an exception statement which youll study later in detail, but for
information were giving you a brief idea. An exception refers to an object that is created whenever an error
occurs in a Java program and cannot be fixed automatically. An exception object contains the information about
the error. Exceptions that occur belong to different classes according to the occurrence of errors. A throws
keyword used here simply lists the exceptions that the method might throw. The throws statement has the
following basic format:
throw new exception-class();
130
Immediate Solutions
When the program is executed, it will create a new file or open that if it already exists within the same directory.
Youll get a dialogue box as shown in Figure 4.1.
You can create new objects of this class from any of the four classes that implements the interface, as the StringBuilder class
has constructors with a parameter of type CharSequence.
Heres an example showing the concatenation of a list of strings into a single string, when string is declared by
using StringBuilder. The following code demonstrates this use, to give you more exposure to
StringBuilder:
class App {
public static void main (String [] args) {
System.out.println ("Concatenation: " +
concat ("Hello", " ", "Java")); }
static String concat (String ... strings) {
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < strings.length; i++)
sb.append (strings [i]);
return sb.toString (); }
}
131
Chapter 4: Object-Oriented Programming
Catching an Exception
No!, says the Novice Programmer. My program just crashes when I divide by zero. Well, you say, its
pretty hard for Java to know what to do when you do that. Why not catch ArithmeticException exceptions
and handle divisions by zero yourself? The NP says, Tell me more!
You can use try/catch blocks to handle runtime errors, called exceptions. Exceptions are encapsulated into
objects that extend the Throwable class. In fact, theres another kind of runtime error in Java thats built on the
Throwable classits called Error. However, this type of error is serious and cannot be caught in code. Heres
the inheritance diagram for the Throwable class:
java.lang.Object
|____java.lang.Throwable
Youll find the constructors of the Throwable class in Table 4.2 and its methods in Table 4.3. Note, in particular,
the getMessage() method, which returns an error message you can display to the user, and the toString()
method, which lets you print out an exception object as part of a string, like this:
System.out.println("Exception: " + e)
132
Immediate Solutions
133
Chapter 4: Object-Oriented Programming
When some sensitive code inside a try block throws an exception, you can catch it with a catch block. You can
also use a finally block to execute code after the try/ catch block is complete, and the code in the finally
block will be executed whether or not an exception occurred. You can use a finally block to handle exceptions
not explicitly caught in a catch block. There are many, many different types of exceptions in Java, and youll
find some of the exception classes in Table 4.5.
Table 4.5: Some Java exception classes
AclNotFoundException ActivationException AlreadyBoundException
ApplicationException AWTException BackingStoreException
BadLocationException CertificateException ClassNotFoundException
CloneNotSupportedException DataFormatException DestroyFailedException
ExpandVetoException FontFormatException GeneralSecurityException
GSSException IllegalAccessException InstantiationException
InterruptedException IntrospectionException InvalidMidiDataException
InvalidPreferencesFormatExcepti InvocationTargetException IOException
on
LastOwnerException LineUnavailableException MidiUnavailableException
MimeTypeParseException NamingException NoninvertibleTransformExcep
tion
NoSuchFieldException NoSuchMethodException NotBoundException
NotOwnerException ParseException ParserConfigurationExcepti
on
PrinterException PrintException PrivilegedActionException
PropertyVetoException RefreshFailedException RemarshalException
RuntimeException SAXException ServerNotActiveException
SQLException TooManyListenersException TransformerException
UnsupportedAudioFileException UnsupportedCallbackExcepti UnsupportedFlavorException
on
UnsupportedLookAndFeelException URISyntaxException UserException
XAException
Take a look at this simple example that divides two numbers and uses try/catch statement to catch an
exception, if the second number turns out to be zero:
public class Divide {
public static void main(String[] args) {
int d = 5;
int z = 0;
134
Immediate Solutions
135
Chapter 4: Object-Oriented Programming
in Java), by specifying the throws keyword in the methods definition (note that if you use the throws
keyword like this, you dont need a try/catch block in the methods body):
public class Excep2 {
public static void main(String args[]) {
try { doSomeWork(); }
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Exception: " + e.getMessage());
e.printStackTrace(); } }
static void doSomeWork() throws ArithmeticException {
int array[] = new int[100];
array[100] = 100; }
}
Heres the result of this code. Note that the stack trace indicates that the exception occurred in the
doSomeWork() method:
C:\>java Excep2
Exception: 100
java.lang.ArrayIndexOutOfBoundsException: 100
at Excep2.doSomeWork(Excep2.java:9)
at Excep2.main(Excep2.java:3)
Here is another example by using the FileNotFoundException. A string is passed to the constructor that
contains the path and name of a file that exists on your computer. In case the file is not found, a
FileNotFoundException is thrown. Youll get acquainted with file operations later:
import java.io.*;
public class FileExcep {
public static void main(String[] args) { openFile("test.bmp"); }
public static void openFile(String name) {
FileInputStream f = new FileInputStream(name); }
}
Youll notice that you cannot compile this example successfully, as the compiler displays the following error:
C:\> javac FileExcep.java
FileExcep.java:5: error: unreported exception FileNotFoundException; must be caught or
declared to be thrown
FileInputStream f = new FileInputStream(name); }
^
1 error
This message means that you need to take care of the FileNotFoundException. To do so, you need to catch
this exception by using the try statement:
import java.io.*;
public class FileExcep {
public static void main(String[] args) { openFile("test1.bmp"); }
public static void openFile(String name) {
try { FileInputStream f = new FileInputStream(name); }
catch (FileNotFoundException e) {
System.out.println("File not found."); }
}
}
On executing this example, the following result gets displayed:
C:\>java FileExcep
File not found.
136
Immediate Solutions
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out of bounds: "
+ e); } }
catch(ArithmeticException e) {
System.out.println("Divide by zero: " + e); }
}
}
Heres the result of this code:
C:\>java NestedExcep
Array index out of bounds: java.lang.ArrayIndexOutOfBoundsException: 4
...It worked!!
137
Chapter 4: Object-Oriented Programming
Throwing Exceptions
Argh! That Johnson is at it again, says the Novice Programmer, abusing my code. Well, you say, you can
throw exceptions yourself in the code if you want to. Yes? asks the NP, Tell me more!
You can throw your own exceptions with the throw statement. Here is an example in which we throw an
exception that will be caught in a catch block that, in turn, throws the exception again to be caught in the
calling method:
public class ThrowExcep {
public static void main(String args[]) {
try { doSomeWork(); }
catch(ArithmeticException e) {
System.out.println("Exception caught in main" + e); } }
static void doSomeWork() {
try { throw new ArithmeticException("Arithmetic Exception!"); }
catch(ArithmeticException e) {
System.out.println("Caught inside doSomeWork " + e);
throw e; } }
}
Heres the output of this code:
C:\>java ThrowExcep
Caught inside doSomeWork java.lang.ArithmeticException: Arithmetic Exception!
Exception caught in mainjava.lang.ArithmeticException: Arithmetic Exception!
Lets now throw the FileNotFoundException that we dealt with earlier in this chapter. If we pass this
exception to the main() method instead of the openFile() method, the example would be as follows:
import java.io.*;
public class FileExcep1 {
public static void main(String[] args) {
try { openFile("test1.bmp"); }
catch (FileNotFoundException e) {
System.out.println("File not found."); } }
public static void openFile(String name) throws FileNotFoundException {
FileInputStream f = new FileInputStream(name); }
}
Adding a throws clause to the openFile() method means that when the FileNotFoundException occurs, it
is simply passed to the method that called the openFile() method. That means the calling method must
either catch or throw the exception. In case the file does not exist, the catch block catches the exception and
displays the error message, as shown in the result:
C:\> java FileExcep1
File not found.
In fact, the throws clause lists all the exception(s) that the method might throw. In case more than one exception
is on the list, it can be separated by commas like this:
public static void readFile(String name) throws
FileNotFoundException, IOException
You can throw a FileNotFoundException from the main method also, by using a throws clause like this:
public static void main (String[] args) throws FileNotFoundException {
openFile(test1.bmp);
}
Can we ignore an exception? asks NP. Of course you can! you say. NP looks satisfied.
138
Immediate Solutions
You can ignore an exception by catching the exception in the catch block of a try statement and then leaving
the catch block empty:
public static void ope1(String name) {
try { FileInputStream f = new FileInputStream(name); }
catch (FileNotFoundException e) { }
}
Note that you dont have to throw any of the predefined Java exceptionsyou can define your own exceptions.
See the next solution for the details.
139
Chapter 4: Object-Oriented Programming
Heres how you can catch multiple exceptions in a single catch block:
catch(SQLException|IOException e) { . . . }
You can see that in Java SE 7, a single catch block allows you to specify different types of exceptions separated
by a vertical bar (|) symbol. Also, note that the catch parameter e is implicitly final. Therefore, you cant assign
or modify value contained in it inside the catch block. The bytecode generated on compilation of the catch
block handling multiple exception types is smaller in size in comparison to the bytecode generated on
compilation of various catch blocks that are handling the single exception type. The bytecode generated in case
of Java SE 7 catch block handling multiple exceptions contains no duplication or replication of exception
handlers.
140
Immediate Solutions
141
Chapter 4: Object-Oriented Programming
142
Immediate Solutions
main[1]
Now we can use the next command to single-step through the code like this:
main[1] next
>
Step completed: "thread=main", App.main(), line=4 bci=13
4 System.out.println("a = " + a);
main[1] next
> a = 51
main[1] next
> c = 34
main[1]
As you can see, there are all kinds of debugging options. Try it yourself. The best way to learn how to use jdb is
to put it to work.
143
Chapter 4: Object-Oriented Programming
Summary
In this chapter, you have been introduced to objects, data members, methods, inheritance, exception handling,
and debugging. You have learned how to declare and define a class, create instance variables, implement
variable scope, create class variable, and perform basic operations on methods. We have also discussed about the
this keyword and operating methods using objects and arrays. You have learned how to perform basic
operations on constructors and use garbage collection, finalize() method and memory management.
Towards the end, the new classes in the java.lang package and exception handling in Java has been explored.
The next chapter will discuss about the inheritance, inner classes, and interfaces.
144
5
Inheritance, Inner Classes,
and Interfaces
If you need an immediate solution to: See page:
Creating a Subclass 150
Access Specifiers and Inheritance 150
Calling Superclass Constructors 151
Creating Multilevel Inheritance 153
Handling Multilevel Constructors 154
Overriding Methods 155
Accessing Overridden Members 155
Using Superclass Variables with Subclassed Objects 156
Dynamic Method Dispatch (Runtime Polymorphism) 157
Creating Abstract Classes 158
Stopping Overriding with final 159
Stopping Inheritance with final 159
Creating Constants with final 160
Is-a vs. Has-a Relationships 160
The Java Object Class 161
Using Interfaces for Multiple Inheritance 162
Creating Iterable Objects 166
Creating Inner Classes 168
Creating Anonymous Inner Classes 168
Chapter 5: Inheritance, Inner Classes, and Interfaces
In Depth
This chapter is all about inheritance, a very important topic in Java programming. Inheritance is used to derive
one class from another class. The class from which another class is being derived is called the base class or
superclass, and the class that is derived is called the derived class or subclass. The idea here is that you add what
you want to the new class to give it more customized functionality in addition to the original class.
The previous chapter began our discussion of Object-Oriented Programming (OOP) and as we mentioned there,
if you have a class named, say, Vehicle, that contains the basic functionality of some means of transport, you
can use that class as the base class of classes you derive from that class, such as Car and Truck. The Car class
might, for instance, have a data member named wheels, set to 4, whereas the same data member in the Truck
class might be set to 18. You can also use the same Vehicle class as the base class for other classes, such as
Helicopter class. All the subclasses will have access to the non-private members of the superclass, and they
can add their own. In fact, they can override the non-private methods of the superclass, replacing them with their
own code. For example, the Vehicle class may have a method named go that prints out Driving and the
Helicopter class may override that method, redefining it so it prints out Flying.
Using inheritance, then, you can base your classes on other classes, reusing code and adding to it. You can use or
redefine the members of the superclass, as you like, customizing that class for your own use. In fact, you can
create classes that must be treated as superclasses. These classes are called abstract classes. You cant instantiate
an abstract class directly into an object; you must instead derive a new class from it first, overriding those
members that are specifically declared abstract. You use abstract classes to force developers to customize some
or all of the members of a class; for example, you may have an abstract method named printError() because
you want developers to supply their own code for this method as appropriate for the subclasses they create.
Thats an overview of what inheritance does. The next question arises, why is inheritance so important in Java?
Why Inheritance?
Java, being an OOP language, relies heavily on inheritance. It contains a large number of packages which contain
classes that you can use as superclasses.
This is important if, for example, you want to create an applet in Java, because in that case, you can derive your
applet from the java.applet packages Applet class. Heres an applet that creates a superclass on the basis of
the Applet class by using the extends keyword (more on applets in the next chapter):
import java.applet.Applet;
import java.awt.*;
public class App extends Applet {
public void paint(Graphics g) {
g.drawString("Hello Java Reader!", 40, 100); }
}
Heres another example; in this case, we are creating a windowed application and basing the window itself on
the Java java.awt.Frame class:
import java.awt.*;
import java.awt.event.*;
class AppFrame extends Frame {
public void paint(Graphics g) {
g.drawString("Hello Java Reader!", 40, 100); }
}
public class App {
public static void main(String [] args) {
AppFrame f = new AppFrame();
f.setSize(200, 200);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0); }});
f. setVisible(true); }
}
146
In Depth
As you can see, when it comes to visual elements in your programs, youll rely on the Java packages a great deal.
Buttons, for example, have their own classes and to customize them, you can derive your own classes from them.
In fact, if you even want to handle mouse actions or button clicks, you have to use inheritance this time, not
using superclasses but rather interfaces.
Why Interfaces?
Suppose you want to create an applet that handles button clicks. For this, you can create a standard applet by
deriving a class from the java.applet.Applet class. You can use ActionListener class for handling the
button clicks. Therefore, both the Applet and ActionListener classes act as base for your applet.
However, basing a subclass on two or more superclasses is called multiple inheritance, and it turns out that Java
doesnt support multiple inheritance (although languages, such as C++ do). In practice, this means you can only
use the extends keyword with one class. To solve this problem, Java implements classes such as
ActionListener as interfaces. In this case, you can extend your applet from the Applet class and use the
implements keyword to add the button-click handling. Heres what this looks like in an applet:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class Clicker extends Applet implements ActionListener {
TextField text1; Button button1;
public void init() {
text1 = new TextField(20); add(text1);
button1 = new Button("Click Here!"); add(button1);
button1.addActionListener(this); }
public void actionPerformed(ActionEvent event) {
String msg = new String ("Welcome to Java");
if(event.getSource() == button1) { text1.setText(msg); }
}
}
You can implement as many interfaces as you like; for example, heres part of a program that implements three
listeners to enable the program to handle button clicks and mouse actions:
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.applet.Applet;
public class dauber extends Applet implements ActionListener,
MouseListener, MouseMotionListener {
. . .
Youll see how to create interfaces later in the book. However, youll get an introduction to them in this chapter
so that we can use them in the chapters to come. Theres one more topic well cover in this chapterInner
Classes.
147
Chapter 5: Inheritance, Inner Classes, and Interfaces
f.setSize(200, 200);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0); }});
f.setVisible(true); }
}
Well unravel this code in detail when working with events, and well get started on that process by introducing
inner classes so that this code will make much more sense to you later.
Lambda Expressions
A lambda expression refers to a method that has no name; no access specifier private, public, or protected; and
no return value declaration. This type of method is also known as anonymous method or closure. Like
anonymous class, a lambda expression can be used for performing a task without a name. It is a new and
significant feature that is included in Java SE 8. Through lambda expressions, functionality can be passed as
method arguments and code as data.
An anonymous class does not have a name, but an object of this class can be created.
Consider the following code snippet for understanding the concept of lambda expression, in which a simple
method is created for showing a message. Lets first declare a simple message as:
public void showMgs()
{
System.out.println(Dreamtech Press);
}
Now, convert the preceding method into a lambda expression by removing the public access specifier, return
type declaration, such as void, and the name of method showMsg. The lambda expression is shown as follows:
() -> {System.out.println(Dreamtech Press); }
The basic structure of a lambda expression comprises:
formal parameters separated by commas and enclosed in parentheses.
arrow token, ->
a single expression or a statement block
If a single expression is specified, the Java runtime environment automatically evaluates the expression and then
returns its value. You can also use a return statement, but it should be enclosed in braces as it is not an
expression.
You know that everything is treated as object in Java; therefore, objects are in large numbers therein. Performing
operations on such large number of objects is very difficult, to handle which Java provides java.util package in
which various objects are stored as a single object, known as collection object. You can perform operations on
various objects by using the loops such as for-each loop. However, this loop will allow you to handle the object
separately and not collectively. Therefore, you need to improve the functional aspect, which can be easily done
by using lambda expressions as these are treated as objects by the JVM.
Method References
As discussed earlier, you can use lambda expressions for creating anonymous methods. Sometimes, a lambda
expression is used only for calling an existing method by using its name but not for performing operations.
Lambda expressions use method references that are compact and easy-to-read for calling existing methods by
their names. There are mainly four different types of method references, as shown in Table 5.1:
148
In Depth
Now that youve the concepts behind inheritance, interfaces, inner classes, and lambda expressions, its time to
turn to the Immediate Solutions section.
149
Chapter 5: Inheritance, Inner Classes, and Interfaces
Immediate Solutions
Creating a Subclass
OK, the NP says, I want to learn what inheritance is all about. Can you explain it in two words or less?
Counting on your fingers you say, No way. Heres an example showing how to create a subclass by using
inheritance.
Suppose you have a class Airplane that has one method fly(), which signifies that the object can fly and
prints Flying:
class Airplane { public void fly() { System.out.println("Flying"); } }
Different kinds of airplanes fly in the sky, so if you want to specialize the Airplane class into a
Passengerplane class, you can use inheritance. Java provides the extends keyword to use inheritance.
Heres how you declare Passengerplane as a subclass of the Airplane class:
class Passengerplane extends Airplane { . . . }
This code line signifies that the class Passengerplane is derived from the superclass Airplane, which
means that the Passengerplane class will inherit the fly() method from the Airplane superclass.
Subclasses can also contain your own methods and data members.
Heres an example in which we add a method named land() to the Passengerplane class that prints
Landing:
class Passengerplane extends Airplane {
public void land() { System.out.println("Landing"); }
}
Now, we can access both the fly() method and the land() method in objects of the Passengerplane class,
as shown in this example:
public class App {
public static void main(String[] args) {
Passengerplane p = new Passengerplane(); p.fly(); p.land(); }
}
Heres the output of the preceding code:
C:\>java App
Flying
Landing
This is a basic subclassing example. However, there is a lot more to the process. For example, what if you define
a method in a subclass with the same name as a method in the superclass? How do you pass data to a
superclasss constructor? All this is coming up in this chapter.
150
Immediate Solutions
For example, take a look at the NPs code, where the fly() method is not only declared private but also
accessed in main():
class Airplane {
private void fly() { System.out.println("Flying"); }
}
class Passengerplane extends Airplane {
public void land() { System.out.println("Landing"); }
}
public class App {
public static void main(String[] args) {
Passengerplane p = new Passengerplane();
p.fly(); p.land(); }
}
Because declaring a member by using private restricts that member to its class, Java says it cant find the fly
method as used in main:
App.java:10: cannot find symbol
p.fly(); p.land(); }
^
symbol : method fly()
location: variable p of type Passengerplane
1 error
On the other hand, declaring a member protected restricts its scope to code in the same package and
subclasses of the class its declared in. Therefore, the following code works:
class Airplane {
protected void fly() { System.out.println("Flying"); } }
151
Chapter 5: Inheritance, Inner Classes, and Interfaces
152
Immediate Solutions
Xyz(String s) {
super(s);
System.out.println("In Xyz\'s String constructor");
System.out.println(s); }
}
public class App {
public static void main(String[] args) {
Xyz obj = new Xyz("Hello Java!"); }
}
In this case, when you instantiate class Xyz, the constructor that takes a String parameter in class Abc is called
instead of the default constructor:
C:\>java App
In Abc's String constructor
Hello Java!
In Xyz's String constructor
Hello Java!
Why is the constructor that takes a String parameter in class Abc called and not the default constructor in class
Abc? The reason is simpleJava sees you are using the super() method to call the superclasss constructor:
class Xyz extends Abc {
Xyz(String s) {
super(s);
System.out.println("In Xyz\'s String constructor");
System.out.println(s); }
}
If you use super() method to call a superclasss constructor, the line in which you do so must be the very first
one in a constructor, which is where Java will look for it (if its in any line but the first, Java will object).
153
Chapter 5: Inheritance, Inner Classes, and Interfaces
Now, we can instantiate objects of these classes, as in this example, we are creating objects of the classes
Passengerplane and Jet:
public class App {
public static void main(String[] args) {
System.out.println("Creating a passenger plane...");
Passengerplane p = new Passengerplane(); p.fly(); p.land();
System.out.println("Creating a jet...");
Jet j = new Jet();
j.fly(); j.fight(); j.target();
}
}
Heres what the output of this code looks like:
C:\>java App
Creating a passenger plane...
Flying
Landing
Creating a jet...
Flying
Fighting
Targeting
154
Immediate Solutions
Its also worth noting that you can pass parameters back multiple levels in the ways we outlined in the topic
Calling Superclass Constructors, earlier in this chapter. However, all constructors in the subclassing chain
must still be called in an ascending order.
Overriding Methods
Oh well, the NP says, I thought I could use the Java Button class in my new program, but I wanted to create
a method named getLabel(), and the Button class already has a method named that. Thats no problem,
you say, you can just override the Button classs getLabel() method with a new implementation of that
method. I can do that? the NP asks.
In the last chapter, you saw that you can overload methods with different implementations that have different
parameter lists. You can also override methods that you inherit from a superclass, which means that you replace
them with a new version.
Heres an example. In this case, well start with a general base class named Animal that has one method
breathe(). When breathe() is called, it prints out Breathing. Heres the code:
class Animal {
public void breathe() { System.out.println("Breathing"); }
}
Now, suppose you want to derive a new class from Animal named Fish. When you test the breathe()
method in the Fish class, you see that it prints out Breathing. You decide it would be better if it prints out
Bubbling instead. To do this, you can override the breathe() method in the Fish class simply by defining a
new version with the same parameter list:
class Animal {
public void breathe() { System.out.println("Breathing"); }
}
class Fish extends Animal {
public void breathe() { System.out.println("Bubbling"); }
}
Now, you can instantiate new objects of the Animal and Fish classes and call their breathe methods as
follows:
public class App {
public static void main(String[] args) {
System.out.println("Creating an animal...");
Animal a = new Animal(); a.breathe();
System.out.println("Creating a lungfish...");
Fish f = new Fish(); f.breathe(); }
}
Heres the output of this code, showing that the breathe() method is indeed overloaded:
C:\>java App
Creating an animal...
Breathing
Creating a lungfish...
Bubbling
You can find the process of creating methods in detail in Chapter 4.
155
Chapter 5: Inheritance, Inner Classes, and Interfaces
System.out.println("Creating a lungfish...");
Fish lf = new Fish(); lf.newbreathe(); }
}
Heres the result of this code:
C:\>java App
Creating an animal...
Breathing
Creating a lungfish...
Breathing
156
Immediate Solutions
157
Chapter 5: Inheritance, Inner Classes, and Interfaces
158
Immediate Solutions
This is an important technique to understand because many methods in the Java packages themselves are abstract and
therefore must be overridden.
159
Chapter 5: Inheritance, Inner Classes, and Interfaces
160
Immediate Solutions
}
class B {
void print() { System.out.println("This comes from class B..."); }
}
public class App {
public static void main(String[] args) { A obj = new A(); }
}
Now, class Bs print() method is accessible from the object named b1 in the object of class A:
C:\>java App
This comes from class B...
Heres an example in which we use the getClass() method to determine the class of an object reference in a
superclass variable. This is useful because a superclass variable can hold references to objects of any of its
subclasses. We start with a superclass named A and three subclasses B, C, and D. The print()method in each of
these classes prints out the name of the class. Heres the code:
class A {
public void print() { System.out.println("Here's A..."); }
}
class B extends A {
public void print() { System.out.println("Here's B..."); }
}
class C extends A {
public void print() { System.out.println("Here's C..."); }
}
class D extends A {
161
Chapter 5: Inheritance, Inner Classes, and Interfaces
162
Immediate Solutions
Now, you can use these two interfaces with the implements keyword:
class A implements B, C { . . . }
As the interfaces declare and not define methods, its up to you to implement the interfaces methods. For
example, in the applet shown at the beginning of this chapter, we implemented the Java ActionListener
interface to handle button clicks (youll see all the details of applets like this in the next chapter). That interface
declares one method actionPerformed(), which we defined as follows:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class Clicker extends Applet implements ActionListener {
TextField text1;
Button button1;
public void init() {
text1 = new TextField(20); add(text1);
button1 = new Button("Click Here!"); add(button1);
button1.addActionListener(this); }
public void actionPerformed(ActionEvent event) {
String msg = new String ("Welcome to Java");
if(event.getSource() == button1) { text1.setText(msg); } }
}
If you dont define the actionPerformed() method, the Java compiler will give you a message like this one:
C:\>javac Clicker.java
Clicker.java:4: error: Clicker is not abstract and does not override abstract method
actionPerformed(ActionEvent) in ActionListener
public class Clicker extends Applet implements ActionListener {
^
1 error
You can implement as many interfaces as you want, as in this example, which implements the
ActionListener interface for button clicks and the MouseListener and MouseMotionListener interfaces
to work with the mouse:
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class Dauber extends Applet implements ActionListener, MouseListener,
MouseMotionListener {
Button buttonDraw, buttonLine, buttonOval, buttonRect,
button3DRect; Button buttonRounded; Point pts[] = new Point[1000];
Point ptAnchor, ptDrawTo, ptOldAnchor, ptOldDrawTo; int ptindex = 0;
. . .
The Readable interface is a source of characters and the CharBuffer class ensures the availability of
characters to the callers from the Readable interface. So, the class CharBuffer should be inherited by the
Readable interface as follows:
public abstract class CharBuffer extends Buffer
implements Comparable<CharBuffer>, Appendable, CharSequence, Readable
163
Chapter 5: Inheritance, Inner Classes, and Interfaces
Besides PrintStream, the interface is also implemented by CharBuffer and all Writer classes, i.e., among
other things by BufferedWriter, CharArrayWriter, FileWriter, FilterWriter,
OutputStreamWriter, and StringWriter.
From PrintStream and Appendable, the covariant return can be read-off. Before Java 5, the subclasses
and/or the implementing classes had to adhere accurate with the type of return to the upper class or interface.
That makes the PrintStream in such a way that it will not append in the class, the return Appendable, but
with the return PrintStream, it will be Appendable.
public PrintStream append( char C ) { print(C); return this; }
Special care must be taken to note that Iterable is in java.lang, not in java.util. No explicit documentation about this is available,
probably to avoid importing the interface (java.lang is in the set of namespaces automatically imported for all Java code).
interface java.long. Iterable<T>
164
Immediate Solutions
Many classes have already implemented this interface so that the result quantities can be iterated with this
extended interface. Primarily, it concerns with the data structures. In addition, it comes with the field, which is
not directly visible as class, but can be Iterable suitably and be implemented.
Heres an example to implement a practical Iterable in order to go over characters in forward and backward
directions. This example uses an ArrayList object.
import java.util.*;
class Iter {
public static void main(String args[]) {
ArrayList<String> al = new ArrayList<String>();
al.add("A");
al.add("B");
al.add("C");
al.add("D");
al.add("E");
al.add("F");
System.out.print("Contents of it are: ");
Iterator<String> Str = al.iterator();
while(Str.hasNext()) {
String element = Str.next();
System.out.print(element + " "); }
System.out.println();
ListIterator<String> list_itr = al.listIterator();
while(list_itr.hasNext()) {
String element = list_itr.next();
list_itr.set(element + "+"); }
System.out.print("Contents of it after modification: ");
Str = al.iterator();
while(Str.hasNext()) {
String element = Str.next();
System.out.print(element + " "); }
System.out.println();
System.out.print("Contents of it in backward direction: ");
while(list_itr.hasPrevious()) {
String element = list_itr.previous();
System.out.print(element + " "); }
System.out.println(); }
}
Heres the result of the code:
C:\>java Iter
Contents of it are: A B C D E F
Contents of it after modification: A+ B+ C+ D+ E+ F+
Contents of it in backward direction: F+ E+ D+ C+ B+ A+
Heres another example to implement a practical Iterable in order to go over words of a sentence.
Fundamental implementation of the Iterable interface on array of characters serves the purpose of the for-
each loop and decides about whether characters of string can be selected or not.
We begin with the first part to be create the class App, which must implement Iterable, as shown in the code
below:
import java.util.*;
import java.util.Iterator;
public class App implements Iterable<String> {
static ArrayList<String> astr = new ArrayList<String>();
public static void main( String args[] ) {
astr.add("At the beginning was the word - At the end the cliche");
Iterator<String> it = astr.iterator();
while(it.hasNext()) {
String element = it.next();
165
Chapter 5: Inheritance, Inner Classes, and Interfaces
System.out.println(element); }
}
public Iterator<String> iterator() { return astr.iterator(); }
}
Heres the result of the code:
C:\> Java App
At the beginning was the word - At the end the cliche
Lets see one more example related to the Iterable interface:
package java.lang;
import java.util.Iterator;
public interface Iterable<T> { Iterator<T> iterator(); }
To implement this interface in the Catalog class, you must write an Iterator method. This method must
return an Iterator object that is bound to the product type.
The Catalog class stores all of its Product objects in an ArrayList. An Iterator object is provided to a
client for returning the Iterator object from the products ArrayList itself. Here is the modified Catalog
class:
class Catalog implements Iterable<Product> {
private List<Product> products = new ArrayList<Product>();
void add(Product product) { products.add(product); }
public Iterator<Product> iterator() { return products.iterator(); }
}
You can see that the Iterator, the List reference, and the ArrayList are all bound to the Product type.
After the implementation of the java.lang.Iterable interface, the for-each loop can be used by the client
code.
Here is an example:
Catalog cat = new Catalog();
cat.add(new Product("1", "pinto", new BigDecimal("7.99")));
cat.add(new Product("2", "flounder", new BigDecimal("34.88")));
cat.add(new Product("2", "cucumber", new BigDecimal("9.01")));
for (Product product: cat)
product.discount(new BigDecimal("0.1"));
for (Product product: cat)
System.out.println(product);
166
Immediate Solutions
Anything (including your own classes) that implements the Iterable interface can be used in a for-each
loop. The for-each takes anything that has an iterator() method and iterates through the available
elements. But, how do you find out that an iterator() method is present? The answer is that the new
Iterable interface indicates the presence of the iterator() method. Lets have a look at the following
example:
import java.util.ArrayList;
import java.util.Iterator;
public class App {
public static void main(String[] args) {
double[] arr = {1.5, 4.2, 4.7, 9.4, 4.8, 7.6};
for(double d: arr) { System.out.println(d); }
System.out.println("---------------------");
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(17); list.add(10); list.add(-61);
for(Integer number: list) { System.out.println(number); }
System.out.println("---------------------");
for(int item: list) { System.out.println(item); }
System.out.println("---------------------");
MyIterable iter = new MyIterable();
for(double d: iter) { System.out.println(d); }
}
}
class MyIterable implements Iterable<Double>,
Iterator<Double> {
static final double CLOSE_TO_ZERO = 0.0001;
double value; double factor = -0.5;
public MyIterable() { value = 1.0; }
public Iterator<Double> iterator() { return this; }
public boolean hasNext() {
return !(value > -CLOSE_TO_ZERO && value
< CLOSE_TO_ZERO); }
public Double next() {
double res = value; value = value*factor; return res; }
public void remove() {
throw new UnsupportedOperationException("There is
nothing to remove"); }
}
Heres the result of this code:
C:\>java App
1.5
4.2
4.7
9.4
4.8
7.6
---------------------
17
10
-61
---------------------
17
10
-61
---------------------
1.0
-0.5
0.25
-0.125
0.0625
-0.03125
0.015625
-0.0078125
0.00390625
167
Chapter 5: Inheritance, Inner Classes, and Interfaces
-0.001953125
9.765625E-4
-4.8828125E-4
2.44140625E-4
-1.220703125E-4
168
Immediate Solutions
Fi.showMsg();
}
}
Here is the result of the preceding code:
C:\>java LambdaExpression
Hello Dreamtech Press
Default Methods
A method that is declared by using the default keyword is known as default method. It is accessible by all
implementation classes of that interface. These classes can override the implementation of the default method
and provide a different implementation. The concept of default method is new, and it is an important feature
included in Java SE 8.0. The default method also allows adding new functionality to interfaces present in
libraries and makes sure that new code written for these interfaces should be compatible with their older
versions. Consider the following example in which a default method is created with the name div and is called
using the object of the interface:
//Functional interface with a default and an abstract methods
interface FuncInterface
{
//abstract method
void mul(int num1, int num2);
//default method
default void div(int num1, int num2)
{
int division=num1/num2;
System.out.println("Result of Division: "+division);
}
}
class ImplClass implements FuncInterface
{
public void mul(int num1, int num2)
{
int sum=num1+num2;
System.out.println("Result of Addition: "+sum);
}
}
class LambdaExpression1
{
public static void main(String args[])
169
Chapter 5: Inheritance, Inner Classes, and Interfaces
{
FuncInterface Fi = new ImplClass();
Fi.mul(2,3);
Fi.div(15,3);
}
}
Here is the result of the preceding code:
C:\>java LambdaExpression1
Result of Addition: 5
Result of Division: 5
Summary
In this chapter, you learned about the concept of inheritance, interfaces, and inner classes. You also learned how
to create a subclass and use the correct access specifiers while implementing inheritance. You came to know
about calling superclass constructors and handling multilevel inheritance. You also explored in the chapter
about handling overriding methods inherited from superclass and accessing overridden methods with the use of
super keyword. Then, you studied about superclass variables with subclass objects, implementation of runtime
polymorphism, how to create abstract classes, the use of final keyword and the lambda expression.
In the next chapter, youll come across AWT package used for creating an applet.
170
6
AWTApplets, Applications,
and Event Handling
If you need an immediate solution to: See page:
Using the Abstract Window Toolkit 175
Creating Applets 186
Using the <APPLET> HTML Tag 188
Handling Non-Java Browsers 189
Embedding <APPLET> Tags in Code 189
Using the init, start, stop, destroy, paint, and update Methods 190
Drawing Graphics in Applets 191
Reading Parameters in Applets 191
Using Java Consoles in Browsers 191
Adding Controls to Applets: Text Fields 192
Adding Controls to Applets: Buttons 193
Handling Events 194
Using Adapter Classes 200
Using Anonymous Inner Adapter Classes 202
Creating Windowed Applications 202
Exiting an Application When Its Window Is Closed 206
Applications You Can Run as Applets 206
Setting Applet Security Policies 207
Other Facilities in the java.awt Package 209
171
Chapter 6: AWTApplets, Applications, and Event Handling
In Depth
We have worked through a lot of Java syntax to get to this point, and this is one of the payoff chapters. Here,
well start working with graphical programsboth applets and applications. This chapter introduces the Java
Abstract Windowing Toolkit (AWT), Javas original way of working with graphics. AWT is now supplemented
with the Swing package, which youll see in a few chapters. AWT provides the foundation of graphics work in
Java, and even the Swing package is based on AWT.
In this chapter, well put AWT to work, creating applets and windowed applications. Before we begin, its worth
putting AWT in some historical perspective. AWT was developed very quickly for the first release of Javain
fact, in only six weeks. The original AWT developers used one window for each component of AWT, so each
button, text field, checkbox, and so on has its own window as far as the underlying operating system is
concerned. That turned out to be a considerable use of system resources as programs became larger. Sun has
introduced the Swing package in which components are displayed using graphical methods of their containing
applet or application windowsthey dont have their own operating system windows. AWT components are
called heavyweight components because of their significant use of system resources, and the Swing components are
called lightweight components because they are just drawn and dont need their own windows. What does this
mean for you? Its clear that, to Sun, Swing is the future. There are far more Swing components than AWT ones,
and in fact, theres a Swing replacement component for each AWT component. Sun probably wont be
expanding the AWT component set much in the future, whereas Swing is expected to grow. On the other hand,
Swing itself is based on AWTthe windows that Swing uses to display Swing components (that is, windows,
frame windows, applets, and dialog boxes) are all based on AWT containers. AWT isnt going away; and in
order to work with Swing, you need a thorough background in AWT. For that reason and because so much
development is still done with AWTand more will be done in the futurewell spend this and the next few
chapters on AWT. Well start with an overview of AWT itself.
172
In Depth
Applets
So, just what is an AWT applet? An applet is simply a Java class file that is embedded in a webpage, using
HTML <APPLET> tag, to display graphics in a web brower. The browser automatically downloads the applet file
and displays it in the appropriate space when the webpage gets loaded. In addition to displaying graphics,
applets can display animation and handle various controls, such as text fields and buttons. Using applets makes
your webpages active, not passivethats their main attraction.
The process goes like this when working with AWT: You create a new applet, basing it on the
java.applet.Applet class, which in turn is based on the AWT Component class. Heres an example which
you have seen before, and well go through it again in this chapter. This example just displays the text Kogent
Learning Solutions! in a web page:
import java.applet.Applet;
import java.awt.*;
public class AppletDemo extends Applet {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 100, 100); }
}
You compile the applet into a bytecode .class file. When you have your .class file, you upload it to an
Internet Service Provider (ISP). You can give the applet the same protection you would give a web page, making
sure anyone can read the AppletDemo.class file (for example, in Unix, you might give the applet the
permission setting 644, which lets anyone read the file).
Unix file permissions make up three octal digits corresponding to the file owners permission, the permission of others in the
same user group, and the permission of all others. In each octal digit, a value of 4 indicates read permission, a value of 2
indicates write permission, and a value of 1 indicates execute permission. You add these values together to set the individual
digits in a permission settingfor example, a permission of 0600 means that the files owner, and only the files owner, can both
read and write to the file.
You can embed the new applet in a web page with the <APPLET> tag, indicating the name of the .class file for
the applet as well as telling the web browser how much space (in pixels) to leave for the applet. Heres an
example:
<HTML>
<BODY>
<CENTER>
<APPLET
CODE = "AppletDemo.class"
WIDTH = 300
HEIGHT = 200>
</APPLET>
</CENTER>
</BODY>
</HTML>
In this case, we have set up a centered 300-by-200-pixel space in a web page in which is to display the applet,
and we told the web browser to download the AppletDemo.class file and run it. Well cover the details,
including the details on the <APPLET> tag, in this chapter. When the browser loads this page, itll display the
applet.
Theres one important thing to know that we are working with appletsthe Java web browser plug-in. Web
browser manufacturers have been notoriously slow to implement the latest Java versions. This means that some
of the Java applets we develop with Java 8 may not work in the latest browsers, even Microsoft Internet Explorer
and Netscape Navigator (you can always use the Sun appletviewer, of course). We get dozens of letters asking
why the examples in this book wont workhadnt they tested? The fault, of course, is with the browsers, which
173
Chapter 6: AWTApplets, Applications, and Event Handling
dont implement the latest Java version. Frustrated with this situation, Sun took the matter into its own hands by
creating the Java Plug-In, which is a plug-in for Netscape Navigator and an ActiveX control for Microsoft
Internet Explorer. The plug-in is a complete implementation of the Java Runtime Environment and lets you run
applets using the latest Java version. Note that you must take some special steps to configure your web pages to
use the plug-in, but Sun also creates and distributes a utility that well use here, the HTML Converter, to
automatically convert any web page to use the plug-in.
Applications
AWT-windowed applications are based on the AWT Frame class, which creates a window with a frame that
displays buttons and a title. Heres an example that youll see more of in this chapter. Like the previous applet,
this application displays Kogent Learning Solutions! in a frame window:
import java.awt.*;
import java.awt.event.*;
public class ApplicationDemo extends Frame {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 50, 100); }
public ApplicationDemo() { addWindowListener(new MyWindowAdapter()); }
public static void main(String [] args) {
ApplicationDemo demo = new ApplicationDemo();
demo.setSize(250,250);
demo.setVisible(true); }
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) { System.exit(0); }
}
After compiling and executing the above program ApplicationDemo.java file, well get the output written
Kogent Learning Solutions! in a frame window having width and height both 250. Well go through the
process of creating windowed applications in detail in this chapter.
Handling Events
One of the biggest aspects of creating applets and applications is letting the user interact with the program, and
you do that with events. When the user performs some actionclicking a button, closing a window, selecting an
item in a list, or using the mouse, for exampleJava considers that as an event. Well handle events throughout
the rest of this book, and well take a look at how event handling works in this chapter.
To start working with events, well also introduce two basic controls in this chapterbuttons and text fields. The
user can use mouse to click buttons that initiate some action in your program, such as placing some text in a text
field. In fact, the button click is perhaps the most basic event Java supports. To illustrate how event handling
works in Java, well create programs in this chapter which support buttons and text fields. The full details on
these controls appear in the next chapter.
Now that you have an overview of applets, applications, and event handling, its time to get to the details in the
Immediate Solutions section.
174
Immediate Solutions
Immediate Solutions
Using the Abstract Window Toolkit
OK, says the Novice Programmer. Im ready to start working with the AWT. Where does it start? With the
Component class, you say. Get some coffee and well take a look at it.
The most basic AWT class is the java.awt.Component class, which all AWT visual components are based on.
For example, the AWT Button class, java.awt.Button, is derived directly from java.awt.Component. The
java.awt.Component class itself is derived directly from the java.lang.Object class, which you saw in
the previous chapter.
The Component class includes a large number of methods, many of which youll see in this and the upcoming
chapter. We have listed them all in Table 6.1 for reference. This is a long table, but its worth glancing it through
and coming back later for reference.
Table 6.1: Methods of the AWT Component class
Method Does this
boolean action It is deprecated. You should register the component as an
(Event evt, Object what) ActionListener on component which fires action events
void add(PopupMenu popup) It adds the pop-up menu to the component with an
ActionListener
void addComponentListener It adds the component listener to receive component events
(ComponentListener l)
void addFocusListener(FocusListener l) It adds the focus listener to receive focus events
void addHierarchyBoundsListener It adds the hierarchy bounds listener to receive hierarchy
(HierarchyBoundsListener l) bounds events from this component when the hierarchy to
which this container belongs changes
void addHierarchyListener It adds the hierarchy listener to receive hierarchy changed
(HierarchyListener l) events from this component when the hierarchy to which this
container belongs changes
void addInputMethodListener It adds the input method listener to receive input method
(InputMethodListener l) events
void addKeyListener (KeyListener l) It adds the key listener to receive key events
void addMouseListener (MouseListener l) It adds the mouse listener to receive mouse events
void addMouseMotionListener It adds the mouse motion listener to receive mouse motion
(MouseMotionListener l) events
void addMouseWheelListener It adds the mouse wheel listener to receive mouse wheel events
(MouseWheelListener I)
void addNotify() It makes a component displayable by connecting it to a native
screen resource
void addPropertyChangeListener It adds a PropertyChangeListener
(PropertyChangeListener listener)
void addPropertyChangeListener It adds a PropertyChangeListener for specified property
(String propertyName,
PropertyChangeListener listener)
void applyComponentOrientation It sets the ComponentOrientation property of this
(ComponentOrientation orientation) component and all components contained within it
boolean areFocusTraversalKeysSet It returns whether the focus traversal keys are explicitly defined
(int id)
Rectangle bounds() It is deprecated and replaced by getBounds()
175
Chapter 6: AWTApplets, Applications, and Event Handling
176
Immediate Solutions
177
Chapter 6: AWTApplets, Applications, and Event Handling
178
Immediate Solutions
179
Chapter 6: AWTApplets, Applications, and Event Handling
180
Immediate Solutions
181
Chapter 6: AWTApplets, Applications, and Event Handling
182
Immediate Solutions
Another important AWT class is the Container class. This class is derived from AWT Component class, and
its the basis of AWT containers, which can hold other components. Applets and windowed applications, which
can display AWT components, are based on the Container class. Because you run across the Container class
often in AWT programmingas in the next topic coming upwe have listed its methods in Table 6.2:
Table 6.2: Methods of the Container class
Method Does this
Component add(Component comp) It adds the indicated component to this container
Component add(Component It adds the indicated component to this container at a specific
comp, int index) position
void add(Component comp, It adds the indicated component to this container
Object constraints)
void add(Component comp, It adds the indicated component to this container with the
Object constraints, int indicated constraints at the indicated index
index)
Component add(String name, Component It adds the indicated component to this container
comp)
183
Chapter 6: AWTApplets, Applications, and Event Handling
184
Immediate Solutions
185
Chapter 6: AWTApplets, Applications, and Event Handling
Creating Applets
Finally! says the Novice Programmer. At last, Im ready to create an applet. Thats right, you say. Now
which one would you like to create? Hmm, says the NP.
You base your applets on the java.applet.Applet class, which is a subclass of the java.awt.Panel class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|_____java.awt.Panel
|____java.applet.Applet
For the sake of reference, youll find the methods of the Applet class in Table 6.3.
Table 6.3: Methods of the Applet class
Method Does this
void destroy() It is called when the applet is about to be disposed of
AccessibleContext getAccessibleContext() It gets the AccessibleContext associated with this applet
AppletContext getAppletContext() It determines this applets context to allow the applet query
and affect the environment in which it runs
String getAppletInfo() It gets information about this applet
AudioClip getAudioClip It gets the AudioClip object specified by the URL argument
(URL url)
AudioClip getAudioClip It gets the AudioClip object specified by the URL and name
(URL url, String name) arguments
URL getCodeBase() It gets the base URL
URL getDocumentBase() It gets the document URL
Image getImage(URL url) It gets an image that can then be painted on the screen
Image getImage It gets an image that can then be painted on the screen
(URL url, String name)
186
Immediate Solutions
Lets look at an example. Here, well create an applet that displays the text Kogent Learning Solutions! in the
file CreateApplet.java. We start by deriving a new class CreateApplet from the java.applet.Applet
class, like this:
import java.applet.Applet;
public class CreateApplet extends Applet { . . . }
To display the message in the applet, well use the paint() method, which the applet inherits from the
Component class. When an applet is displayed, its paint() method is called, and you can place the code for
drawing the applet in that method. The paint() method is passed an object of the Graphics class, which
youll study in a few chapters. Its the basis of graphical work in applets. This object supports a method named
drawString(), which well use to draw a string of text in the applet. The Graphics class is an AWT class, so
well import AWT classes when we override the default paint() method of the Applet class like this:
import java.applet.Applet;
import java.awt.*;
public class CreateApplet extends Applet {
public void paint(Graphics g) { . . . }
}
Now well customize the overridden paint() method to draw the text Kogent Learning Solutions! at location
(80, 100) in the applet. Applet coordinates are in pixels; therefore, (80, 100) is at 80 pixels from the left edge of the
applet and 100 pixels here the bottom of the title bar. Heres the code:
import java.applet.Applet;
import java.awt.*;
/*<APPLET
CODE= CreateApplet.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class CreateApplet extends Applet {
public void paint(Graphics g) {
187
Chapter 6: AWTApplets, Applications, and Event Handling
188
Immediate Solutions
In this case, we are not specifying a code base, so we place CreateApplet.class in the same directory as
Applet.html. This web page, as opened in Internet Explorer, appears in Figure 6.1. Note that if an applet
doesnt work in your browser, it could be well because the browser doesnt support the current Java version.
You can also use the Sun appletviewer, which comes with Java, to view the applet. You open the web page like
this (this example assumes that Applet.html is in the current directoryyou can always give the path of the
.html file like this: appletviewer C:\BB_Chapters\Chapter-6\Applet.html):
C:\>appletviewer Applet.html
The result appears in Figure 6.2. The appletviewer always supports the latest version of Java, so if your web
browser doesnt, and you dont want to install the Java plug-in, you can always use the appletviewer to test your
applets.
Figure 6.1: An applet at work in the Internet Explorer Figure 6.2: An applet at work in the
AppletViewer
189
Chapter 6: AWTApplets, Applications, and Event Handling
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=EmbedAppletTag.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class EmbedAppletTag extends Applet {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 80, 100); }
}
After creating the .class file, you can now start the appletviewer with the .java file directly:
C:\>appletviewer EmbedAppletTag.java
Using the init, start, stop, destroy, paint, and update Methods
The Novice Programmer is back and says, My browser has gone all wackyit draws my applets in gray!
Thats the default for many web browsers, you say. However, you can change that by adding some
initialization code to your applet in the init() method.
Here are a number of important applet methods you should know about:
init()This is the first method to be called, and it is called only once. You initialize the applet here.
start()This method is called after init, and it is called each time an applet appears again on the
screen. That is, if the user moves to another page and then comes back, the start method is called again.
stop()This method is called when the browser moves to another page. You can use this method to stop
additional execution threads your applet may have started.
destroy()This method is called when the applet is about to be removed from memory. You can
perform cleanup here.
paint()This method is called when the applet is to be redrawn. It is passed an object of the Graphics
class, and you can use that objects methods to draw in the applet.
update()This method is called when a portion of the applet is to be redrawn. The default version fills
the applet with the background color before redrawing the applet, which can lead to flickering when you
are performing animation, in which case you would override this method.
You can override these methods to customize them as you like. We have already overridden the paint method
to draw a string of text; here, we override the init() method to change the background color of the applet to
orange, using the applet setBackground() method and passing it the orange field of the Java Color class.
This applet also implements other methods listed previously. Heres the code:
import java.applet.Applet;
import java.awt.*;
/* <APPLET
CODE=AppletMethods.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class AppletMethods extends Applet {
public void init() { setBackground(Color.orange); }
public void start() { }
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 80, 100); }
public void stop() { }
public void destroy() { }
}
The init() method is a very useful one, and its commonly overridden because it lets you initialize your
applet. In this case, we have changed the background color from gray (the default in many browsers) to orange.
Applets excel at graphics; the next topic provides an overview of handling graphics in applets.
190
Immediate Solutions
Heres an applet that displays a message and uses System.out.println() to print to the console:
import java.applet.Applet;
import java.awt.*;
/* <APPLET
CODE=AppletAndConsole.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class AppletAndConsole extends Applet {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 80, 100);
System.out.println("Kogent Learning Solutions!"); }
}
If you run this applet with the Sun appletviewer, the applet will open in a separate window, and youll see
Kogent Learning Solutions! in the console window. Web browsers often have a Java Console as well, although
you often have to enable them before using. The way to enable the Java Console differs, unfortunately, from
browser to browser as well as from version to version. Currently, you enable the Java Console in Internet
Explorer by selecting Tools | Internet Options, clicking the Advanced tab, and selecting the Java Console
Enabled checkbox. And you can open the Java Console by selecting the View | Java Console
Figure 6.3 shows the result of the preceding applet as it appears in the Internet Explorer Java Console, which
pops up when you print to the applet. In Netscape Navigator, you can open the Java Console with the
Communicator | Java Console menu item.
192
Immediate Solutions
. . . }
}
After creating a new control, you must add it to the applet so that its displayed. Heres an example:
public void init() {
text1 = new TextField(20); add(text1);
. . .
}
The add method adds the control to the current layout manager, which decides where the control should be
placed (youll see the details on layout managers in the next chapter). Now that the text field has been added to
the applet, we can place the text Kogent Learning Solutions! in the text field with the setText() method,
like this:
public void init() {
text1 = new TextField(20);
add(text1);
text1.setText("Kogent Learning Solutions!");
}
The result of this code appears in Figure 6.4, where you can see the text field with the message we have put into
it. The user can also edit this text. Well take a closer look at text fields in the next chapter. Another basic control
is the AWT Button control; well use buttons and text fields to discuss event handling, so well introduce the
Button control in the next topic. Youll learn about buttons and text fields in detail in the next chapter.
Handling Events
Hey, says the NP, I have put a Button in my applet; but when I click it, nothing happens. What gives? What
gives, you say, is that you have to implement event handling.
Event handlingthe process of responding to button clicks, mouse movements, and so onhas become a
complex topic in Java. Starting with Java 1.1, event handling changed significantly in Java; the current model is
called delegated event handling. In this event handling model, you must specifically register with Java if you want
to handle a specific event such as a button click (the idea is that performance is improved if only code that needs
to handle specific events is informed of those events, and not the rest of your code).You register for events by
implementing an event listener interface. Here are the available event listeners and the kinds of events they
handle:
ActionListenerIt listens for action events, such as button clicks
AdjustmentListenerIt listens for adjustment events, such as scrollbar movements
ComponentListenerIt listens for cases in which a component is hidden, moved, resized, or shown
ContainerListenerIt listens for cases in which a component is added or removed from a container
FocusListenerIt listens for cases in which a component gains or loses the focus
ItemListenerIt listens for cases in which the state of an item changes
KeyListenerIt listens for keyboard events
MouseListenerIt listens for cases in which the mouse is clicked, enters a component, exits a component,
or is pressed
MouseMotionListenerIt listens for cases in which the mouse is dragged or moved
MouseWheelListenerIt listens for cases in which the mouse wheel event is rotated in a component
TextListenerIt listens for text value changes
WindowListenerIt listens for cases in which a window is activated, deactivated, iconified, deiconified,
opened, closed, or quit
Each listener is an interface, and its up to you to implement the methods of the interface (for more on interfaces,
see the previous chapter). Each of these methods is passed a type of event object that corresponds to the kind of
event:
ActionEventIt handles buttons, list double-clicks, and menu item clicks
AdjustmentEventIt handles scrollbar movements
ComponentEventIt handles cases in which a component is hidden, moved, resized, or becomes visible
ContainerEventIt handles cases in which a component is added or removed from a container
FocusEventIt handles cases in which a component gains or loses the focus
194
Immediate Solutions
InputEventIt handles checkbox and list item clicks, choice control selections, and checkable menu item
selections
ItemEventIt handles cases when an item is selected, de-selected, expanded, or contracted
KeyEventIt handles input from the keyboard
MouseEventIt handles cases in which the mouse is dragged, moved, clicked, pressed, released, or entered
or exits a component
MouseWheelEventIt handles the cases when the mouse wheel is rotated in a component
TextEventIt handles the value of a text field or text area being changed
WindowEventIt handles cases in which a window is activated, deactivated, iconified, deiconified, opened,
closed, or quit
Heres how we add an action listener to a button, sending event notifications to the current applet object (note
that we indicate that the AppletEvent1 class now implements the ActionListener interface):
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=AppletEvent1.class
WIDTH=300
HEIGHT=200>
</APPLET> */
public class AppletEvent1 extends Applet implements ActionListener {
TextField text1;
Button button1;
public void init() {
text1 = new TextField(20);
add(text1);
button1 = new Button("Display Text");
add(button1);
button1.addActionListener(this);
.... }
}
Now we have to implement the methods of the ActionListener interface. It turns out that this interface has
only one method actionPerformed(), which is passed an object of the ActionEvent class when the button
is clicked:
void actionPerformed(ActionEvent e)
ActionEvent objects (which well discuss in the next chapter) inherit a method named getSource() from the
EventObject class, and this method returns the object that caused the event. That means we can check whether
this event was caused by the button, button1, and if so, place the text Kogent Learning Solutions! into the text
field text1, like this:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
195
Chapter 6: AWTApplets, Applications, and Event Handling
CODE=AppletEvent1.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class AppletEvent1 extends Applet implements ActionListener {
TextField text1; Button button1;
public void init() {
text1 = new TextField(20);
add(text1);
button1 = new Button("Display Text");
add(button1);
button1.addActionListener(this); }
public void actionPerformed(ActionEvent event) {
String text = new String ("Kogent Learning Solutions!");
if(event.getSource() == button1) { text1.setText(text); }
}
}
This applet appears in Figure 6.6. When you click the button, the text Kogent Learning Solutions! appears in
the text field.
197
Chapter 6: AWTApplets, Applications, and Event Handling
198
Immediate Solutions
199
Chapter 6: AWTApplets, Applications, and Event Handling
Extending Components
If you like being sneaky, you can handle events by deriving new classes from components and overriding the
methods in the components that handle events. In fact, this way of doing things ends up much like the Java 1.0
technique of event handling because all event handling takes place in one method; therefore, its discouraged.
However, well cover it here to be complete.
Heres how we implement the applet by extending the Button class in a derived class named NewButton. In this
new class, we override the Button classs processActionEvent() method, displaying the text Kogent
Learning Solutions! in the applets text field after calling the Button classs processActionEvent() method:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=AppletEvent7.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
class NewButton extends Button {
AppletEvent7 ae;
NewButton(AppletEvent7 ref, String s) {
super(s); ae = ref;
enableEvents(AWTEvent.ACTION_EVENT_MASK); }
protected void processActionEvent (ActionEvent e) {
super.processActionEvent(e);
ae.text1.setText("Kogent Learning Solutions!"); }
}
Now all we have to do is to create a new button of this class and add it to the applet:
public class AppletEvent7 extends Applet {
TextField text1;
Button button1;
public void init() {
text1 = new TextField(20);
add(text1);
button1 = new NewButton(this, "Display Text");
add(button1); }
}
Thats all it takes; now this applet works like the others.
200
Immediate Solutions
Adapter classes are classes that have already implemented the various event interfaces available. Each method of
an interface is implemented as an empty method without any code in an adapter class, and all you need to do is
override the method or methods you want to provide code for.
Lets look at an example. In this case, well start with an applet that stores a string to print, which is Kogent
Learning Solutions! by default, and displays that string in the paint() method. Then we are going to add a
mouse listener (which youll learn more about in the next chapter) to the applet; so when the user clicks the
applet, the message Hello from Java! appears. Unlike the ActionListener interface, the MouseListener
interface has five methods that must be implemented. However, we just want to use the mouseClicked()
method to handle mouse clicks, so well use the MouseAdapter class instead.
We start by adding a class that implements a mouse listener to the program. This class will subclass the
MouseAdapter class, and well call it MyAdapter:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=AppletAdapter.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class AppletAdapter extends Applet {
public String text = "Kogent Learning Solutions!";
public void init() { addMouseListener(new MyAdapter(this)); }
public void paint(Graphics g) { g.drawString(text, 80, 100); }
}
We pass an object of the main applet class to the MyAdapter classs constructor, so it can reach the fields in the
applet. When the mouse is clicked, the text string in the applet is replaced with the text Hello from Java! and
then the applet is repainted, causing the new string to appear on the screen:
class MyAdapter extends MouseAdapter {
AppletAdapter aa;
MyAdapter(AppletAdapter appletobject) { aa = appletobject; }
public void mouseClicked(MouseEvent e) {
aa.text = "Hello from Java!";
aa.repaint(); }
public void mouseReleased(MouseEvent e) { }
}
The result of this code appears in Figure 6.9 and Figure 6.10.
Note that this was a little awkward because we had to pass the applet object to the MyAdapter classs
constructor so that the class could reach the fields in the AppletAdapter class. On the other hand, inner classes
have access to the fields of their enclosing classes, so adapters are often implemented as inner classes. Well take
a look at that next.
Figure 6.9: Supporting button clicks Figure 6.10: Supporting button release
with adapter classes with adapter classes
201
Chapter 6: AWTApplets, Applications, and Event Handling
Although the Applet classs default layout manager is the flow layout manager, the default layout manager in the Frame class is
the border layout manager. If you want to use another layout when adding components to a Frame window, youll have to
change the layout manager yourself.
202
Immediate Solutions
Heres an example in which we derive a new class, AppFrame, from the Frame class and customize this new
class to display the string Kogent Learning Solutions! to make it look like the applet developed earlier.
As with the java.applet.Applet class, the java.awt.Frame class is derived from the java.awt.Window
class, so we can use the paint() method to display graphics in the Frame class. In fact, the paint() method
will look just as it did in the applet created earlier in the applications code file Application1.java. Heres
the code:
import java.awt.*;
class AppletFrame extends Frame {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 80, 100); }
}
203
Chapter 6: AWTApplets, Applications, and Event Handling
A main() method is needed to start the application itself, so we create that method in a new class named
Application1:
public class Application1 {
public static void main(String [] args) { . . . }
}
To display the applications frame window, we create an object of the AppletFrame class, like this:
public class Application1 { public static void main(String [] args) {
AppletFrame f = new AppletFrame();
. . . }
}
Now we give the frame window object a size of 300 by 200 pixels and display it on the screen with the
setVisible(true) method:
public class Application1 {
public static void main(String [] args) {
AppletFrame f = new AppletFrame();
f.setSize(300,200);
f.setVisible(true); }
}
If you dont give a frame window a size before displaying it, all youll see is a title bar. In Graphical User Interface (GUI) terms,
there will be no client area, which is the area under the title bar in which the application displays itself.
The result of this code appears in Figure 6.11. As you can see, the message Kogent Learning Solutions! appears
in the application, as intended. You can also add controls to this application, just as we did with the button
applet earlier in this chapter.
There are a few things to mention here: First, if you launch the application with the java tool (that is, as java
Application), that tool will wait until the application ends before returning control to the console. From the
users point of view, the console appears to hang until the application is exited. If you want control to return
immediately to the console after the application is launched and displays its own window, use the javaw tool
instead.
Another important point is that if you want to distribute your applications to users who dont have the SDK
installed, you can use the Java Runtime Environment (JRE).
Finally, its important to point out that theres no easy way to exit the application in Figure 6.11clicking the
close button has no effect at all. You can press Ctrl+C to end execution of the java tool in the console window,
but thats pretty awkward. Instead, you have to handle window-closing events to end the application when its
window is closed. Well take a look at this in the next topic related to exiting an application when window is
closed.
204
Immediate Solutions
import java.awt.Graphics;
import java.awt.image.VolatileImage;
public class Application2 extends Component {
public VolatileImage buffer = null;
void createBackBuffer() {
if (buffer != null) {
buffer.flush();
buffer = null; }
buffer = createVolatileImage(getWidth(), getHeight()); }
public void paint(Graphics g) {
if (buffer == null) { createBackBuffer(); }
do {
int code = buffer.validate(getGraphicsConfiguration());
if (code == VolatileImage.IMAGE_RESTORED) {}
else if (code == VolatileImage.IMAGE_INCOMPATIBLE) {
createBackBuffer(); }
Graphics graph = buffer.getGraphics(); graph.setColor(Color.white);
graph.fillRect(0, 0, getWidth(), getHeight());
graph.setColor(Color.red);
graph.drawLine(0, 0, getWidth(), getHeight());
g.drawImage(buffer, 0, 0, this); }
while (buffer.contentsLost());
}
public static void main(String args[]) {
Frame frame = new Frame();
frame.setSize(300, 200);
frame.add(new Application2());
frame.setVisible(true); }
}
The result of the code appears in Figure 6.12.
205
Chapter 6: AWTApplets, Applications, and Event Handling
if(ie.getStateChange() == ItemEvent.SELECTED)
state = "Selected";
label.setText(ie.getItem() + " " + state ); }
public static void main(String args[]) {
new Application3(); }
}
The result of the code appears in Figure 6.13.
206
Immediate Solutions
CODE=AppletApp.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
public class AppletApp extends Applet {
public static void main(String [] args) {
AppletFrame f = new AppletFrame();
f.setPreferredSize(new Dimension(WIDTH-0, HEIGHT-0));
f.addWindowListener(new WindowAdapter() {public void
windowClosing(WindowEvent e) {System.exit(0);}});
f.setVisible(true);
f.setIgnoreRepaint(false); }
public void paint(Graphics g) {
g.drawString("Hello from Java!", 60, 100); }
}
class AppletFrame extends Frame {
public void paint(Graphics g) {
g.drawString("Kogent Learning Solutions!", 80, 100); }
}
You can run this code as either an applet or application (the Big Boss would be proud).
You must be very careful when adjusting Javas security settingsdont leave yourself open to security problems.
Start the Policy Tool now by typing policytool in the console window. The Policy Tool appears in Figure 6.14.
To add a new policy entry for WriterApplet.class, click the Add Policy Entry button in the Policy Tool,
which opens the Policy Entry dialog box, shown in Figure 6.15.
207
Chapter 6: AWTApplets, Applications, and Event Handling
Figure 6.14: The Policy Tool Figure 6.15: The Policy Entry dialog box
Enter the URL of the applet or application you want to set the security settings for (well use a file:\\ URL
here, but of course you can specify HTTP:// URLs as well) and click the Add Permission button, which opens
the Permissions dialog box, shown in Figure 6.16:
208
Immediate Solutions
System Tray
It is a specific area that can be accessed during running programs. It appears at the bottom of the desktop. Any
user can access it continually. All running application on the desktop can share this tray area. It is referred to as
the Taskbar Status Area on the Microsoft Windows, the system tray on KDE, and the Notification Area on the
Gnome Desktop. You can access the system tray in Java with two separate classes defined in java.awt package,
i.e., SystemTray and TrayIcon.
These classes add some more functionality, such as graphics, pop-up menus, and floating tip functions to the
system tray. The system tray contains method getSystemTray(). The system tray in Java can be accessed by
calling the following method:
static SystemTray.getSystemTray()
Before accessing the system tray, the application always check the availability of system tray by using the
static SystemTray.isSupported() method. This method returns false if it is found that the system tray is
not present. In this case, if the getSystemTray() method is invoked by the application, it will throw a
java.lang.UnsupportedOperationException.
A TrayIcon can be added to the SystemTray. It can have an image, a tooltip(text), and it is also
associated with a set of listeners. Various MouseEvents, like MousePressed, MouseReleased,
MouseClicked are generated by a TrayIcon and provide the facility for notification of the events. Some of the
events are processed by TrayIcon itself. Suppose, a user performs right-click on the TrayIcon, then the
TrayIcon displays the pop-up menu. An ActionEvent is also generated by TrayIcon.
209
Chapter 6: AWTApplets, Applications, and Event Handling
Lets look at an example of SystemTray. Here, the SysTrayDemo class has used SystemTray and TrayIcon.
You can get the instance of SystemTray by calling the method getSystemTray(). The SystemTray class
represents the tray bar, and each icon on it is represented by the TrayIcon class. A TrayIcon can be added to
the SystemTray by invoking SystemTray.add() method. The SysTrayDemo class adds a TrayIcon with an
image, a tooltip and a pop-up menu.
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class SysTrayDemo {
private static void createGUI() {
if(!SystemTray.isSupported()) {
System.out.println("SystemTray is not supported");
return; }
SystemTray systray=SystemTray.getSystemTray();
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("image.jpg");
PopupMenu popmenu = new PopupMenu();//Menu item to show the message
MenuItem msgItem= new MenuItem("Show Message");
msgItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"System Tray
Demo"); } });
popmenu.add(msgItem); //create menu item to close application
MenuItem closeitem = new MenuItem("close");
closeitem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0); }});
popmenu.add(closeitem);
TrayIcon icon = new TrayIcon(image,"SystemTray Demo",popmenu);
icon.setImageAutoSize(true);
210
Immediate Solutions
try { systray.add(icon); }
catch (AWTException e) {
System.out.println("Tray icon cannot be added to system
tray"); }
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run(){ createGUI(); }
});
}
}
When you run the SysTrayDemo class, youll find the icon of the SystemTray in the Taskbar Status Area. If
you right-click on the icon, youll get the menu. The output of the code is as shown in Figure 6.18:
Splash Screen
Splash screen informs user that the application is starting up. It is a standard part of any GUI application. A
polished Splash screen of the application can be used for presenting marketing information and legal
information, such as copyright information, third party logo, and so on. To see the Splash screen, a user can be
sure that the application is starting.
For creating the Splash screen in Java application, you can use AWT or Java Foundation Classes/Swing
(JFC/Swing). There should be a minimum delay between the applications startup and the pop up of the Splash
screen. The application is permitted to display the Splash screen much before the starting of Java Virtual
Machine. It is possible to decode the image and then display it in a simple window by an application launcher.
The Splash screen is also capable of displaying any image format like jpeg, gif, png with transparency and
animation. You can use one of the two ways to show the native Splash screen:
If you are using the command-line for running the application, then to show the native Splash screen, use the
splash: Java application launcher option. Heres an example:
Java splash:filename.png HelloSplash
If application is packaged in a .jar file, a Splash screen can be displayed by using the SplashScreen-Image
option in a manifest file. You need to save the image in a jar archive and mention the path in the option.
Suppose, there is a manifest, file manif.mf Now use this code in the manifest file:
Manifest-Version: 1.0
Main-class: HelloSplash
SplashScreen-Image: filename.png
Among these two ways, the command-line interface has precedence over the manifest setting.
Heres the inheritance diagram for the SplashScreen class:
java.lang.Object
|____ java.awt.SplashScreen
211
Chapter 6: AWTApplets, Applications, and Event Handling
You can find the methods of the SplashScreen class in Table 6.7.
Table 6.7: Methods of the SplashScreen class
Method Does this
void close() It is used for hiding the Splash screen, closing the window, and releasing all
associated resources
Graphics2D createGraphics() It creates a graphics context for the Splash screen overlay image, which
allows you to draw over the Splash screen
Rectangle getBounds() It returns the bounds of the Splash screen window as a Rectangle
URL getImageURL() It returns the current Splash screen image
Dimension getSize() It returns the size of the Splash screen window as a Dimension
static SplashScreen It returns the SplashScreen object used for Java startup Splash screen
getSplashScreen() control on systems supporting dislpay
boolean isVisible() It determines whether the Splash screen is visible or not
void setImageURL (URL imageURL) It changes the Splash screen image
void update() It updates the Splash window with current contents of the overlay image
Lets look at an example. Here, the SplashScreenDemo class is used to display a Splash screen before the JVM
starts. The instance of the SplashScreen class is obtained by calling the static getSplashScreen() method,
and the createGraphics() method returns a Graphics 2D object that allows you to draw over the Splash
screen:
import java.awt.*;
import java.awt.SplashScreen;
import javax.swing.*;
public class SplashScreenDemo {
private static void createImage() {
SplashScreen splashscreen = SplashScreen.getSplashScreen();
if(splashscreen!=null){
Graphics2D g = (Graphics2D) splashscreen.createGraphics();
for(int i=0;i<10;i++){
String message = "Processing"+ i+ "of 10....";
g.setComposite(AlphaComposite.Clear);
g.fillRect(130,350,280,40);
g.setPaintMode();
g.setColor(Color.RED);
g.drawString(message,130,360);
g.fillRect(130,370,i*30,20);
splashscreen.update();
try {
Thread.sleep(500);
}catch(InterruptedException e) { e.printStackTrace(); }
}
}
JFrame frame = new JFrame("Splash Screen demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,200);
frame.setLocationRelativeTo(null);
frame.setVisible(true); }
public static void main (String args[]) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){ createImage(); }
});
}
}
Before running the SplashScreenDemo class, you have to make sure that the Java8.jpg file is in the same
directory. Run the class as follows:
java splash:Java8.jpg SplashScreenDemo
212
Immediate Solutions
When you run the SplashScreenDemo class, youll find that there is nothing more than a blank frame.
However, before it is uploaded, youll see a Splash screen like that in Figure 6.20:
Dialog Modality
A dialog box comprises a title and a border. It is used to take input from user and represented as a top-level pop-
up window. An application uses a modal dialog box for blocking the input to some other top-level windows.
The modal dialog box captures the window focus until it gets closed.
In JDK 5.0 and earlier, there was a problem with the modality model. When an application shows any modal
dialog box, the dialog box blocks the user from interacting with the JavaHelp tool windows (an API to display
help information). This problem has been resolved in Java SE 7 using a new AWT modality model. This new
modality model is helpful for the developer. It provides the developer to scope or limit the dialog modality,
blocking according to the selection of the modality type by the developer.
There are four modality types:
Modeless
Document modal
Application modal
Toolkit modal
Modeless
It does not block any other window until it is visible.
Document Modal
In this modal, all windows are blocked from the same document, except those from its child hierarchy.
Application Modal
In this modal, all windows are blocked from the same application, except those from its child hierarchy.
Toolkit Modal
All windows are blocked that run in the same toolkit, except from its child hierarchy. A dialog box will use the
application modal by default, whereas with JDKs, prior to Java SE 6, it is modeless by default.
Gif Writer
Sometimes, Graphics Interchange Format (GIF) is also referred to as Graphics Interchange File Format (GIFF). It
is well known that there are three graphic file formats:
Joint Photographic Experts Group (JPEG)
GIF
PNG (Portable Network Graphics)
JPEG supports a compression technique that can be lost, i.e., the images cannot be restored to their original form
if any images are compressed in the JPEG format, while GIF supports lossless compression but can only render
256 colors. These images are basically for simple images, such as buttons, labels, and logos. JPEG is used for
complex graphics, like photos. PNG is also superior to GIF, but it is not as widespread as GIF. Therefore, GIF is
used everywhere on the World Wide Web.
213
Chapter 6: AWTApplets, Applications, and Event Handling
Text Antialiasing
Text antialiasing is used for reducing the jaggedness of text or images onto screens with discrete pixel values.
When we draw a diagonal line on the monitor, we turn pixels on and off. After looking it closely, youll find that
stair-step effect. Mustang has provided the facility for supporting the LCD displays by using the subpixel text to
increase the text resolutions. Each color element of a pixel is called subpixel. These subpixels rendering is based
on the phenomenon that modifying the intensities of subpixels can cause the location of pixels to shift, without
changing the color.
The following five fields exist in the java.awt.RenderingHints class:
VALUE_TEXT_ANTIALIAS_LCD_HRGB
VALUE_TEXT_ANTIALIAS_LCD_HBGR
VALUE_TEXT_ANTIALIAS_LCD_VRGB
VALUE_TEXT_ANTIALIAS_LCD_VBGR
VALUE_TEXT_ANTIALIAS_GASP
You can use each of these values when using the setRenderingHint() method of the Graphics 2D object to
set the key text antialiasing value.
Summary
In this chapter, we have discussed about Abstract Window Toolkit, its applications, and event handling. You
have learned how to use the Abstract Window Toolkit and creation of applets. You have also read about
handling non- Java browsers and the use of init(), start(), stop(), destroy(), paint(), and update() methods. The
chapter has also helped you to draw the graphics and paramters in applets and add controls to them. Moreover,
the adapter classes and the anonymous inner adapter classes have been discussed in the chapter. Toward the
end, you learn to run the applications in applets and set applets security policies.
In the next chapter, well learn about text fields, buttons, checkboxes, radio buttons, and various layouts of the
AWT component class.
214
7
AWTText Fields,
Buttons, Checkboxes,
Radio Buttons, and Layouts
If you need an immediate solution to: See page:
Using Text Fields 218
Using Labels 220
Using Buttons 221
Using Checkboxes 224
Using Radio Buttons 227
Layout Managers 228
Flow Layouts 228
Grid Layouts 231
Using Panels 232
Border Layouts 234
Card Layouts 236
Grid Bag Layouts 238
Using Insets and Padding 243
Creating Your Own Layout Manager 244
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
In Depth
This chapter is all about a number of important AWT componentstext fields, buttons, checkboxes, and radio
buttons. Now that we are dealing with visible components, well also take a look at Java layout managers, which
let you arrange the components in an applet or application, as you like. Well also take a look at Java panels,
which let you assemble components together on one surface and submit the resulting surface to a layout
manager. Well start by taking a look at text fields.
Text Fields
Text fields are the basic text-handling components of the AWT. These components handle a one-dimensional
string of text; they let you display text, write passwords by masking typed text, enter and read the text the user
has entered, and more. In addition to buttons, these components are the most fundamental AWT components.
Buttons
Buttons provide users with a quick way to start some actionall they have to do is click them. Every user is
familiar with buttons, and we have already taken a look behind the scenes on how buttons work in code when
discussing event handling in the previous chapter. You can give buttons a caption, such as Display Text. When
the user does click the button, your code is notified if you have registered to handle events from the button.
Checkboxes
Checkboxes are much like buttons, except that they are dual state, which means they can appear as selected or
unselected. When selected, they display a visual indication of some kind, such as a checkmark or an X (it varies
by operating system in AWT programming, which is one of the reasons Sun introduced Swing, which can
display components with the same look across many operating systems). The user can click a checkbox to select
an option of some kind (such as the items on a sandwich), to enable automatic spell checking, or to enable
printing while he or she is doing something else. You use checkboxes to let the user select non-exclusive options;
for example, both automatic spell checking and background printing may be enabled at the same time. Radio
buttons, however, are a different story.
Radio Buttons
You let the user select one of a set of mutually exclusive options by using radio buttons. Only one of a set of
option buttons can be selected at one time; for example, using radio buttons, you can let the user select a printing
color or the day of the week. In AWT, radio buttons are actually a type of checkbox; and when selected, they
display a round dot or a clicked square or some other indication (again, the visual indication depends on the
operating system). You use radio buttons in groups, and youll see how that works in this chapter.
Layouts
So far, we have just added components to applets and applications by using the add method. This method is
actually a method of the default layout managerthe flow layout manager. This layout manager is responsible for
arranging components in AWT applets, by default. The flow layout manager arranges components much like a
word processor might arrange wordsacross the page and then wrapped to the next line as needed, creating
what Oracle calls a flow of components. Youll see that you can customize flow layouts to some extent, such as left-
, center-, or right-aligning components. However, the limitations of the flow layout are clear, especially if you are
counting on components maintaining some position with respect to the others, because if the user resizes your
applet or application, the components will all move around. On the other hand, there are other AWT layout
managers (and quite a few new ones in Swing), and well cover the AWT grid, border, card, and grid bag layout
managers in this chapter.
Why cant you just set where a component goes and forget it? Novice Java programmers are often frustrated by
having to deal with AWT layout managers and want to know why they cant just give the coordinates for the
components they want to use and be done with it. In fact, you can, although you are responsible for handling the
216
In Depth
case where windows are resized and components should be moved. To position components where you want
them, you can indicate that you want no layout manager at all. Then you can size and locate the components, as
you want them, using add() method to display them, like this:
setLayout(null);
text1 = new TextField(20);
text1.setSize(200,50);
text1.setLocation(20,20);
add(text1);
This adds a text field of size (200,50) at location (20,20) in a container, such as an applet window. Therefore, as
you can see, you can add components to containers without any layout manager at all, something thats useful to
bear in mind if the AWT layouts frustrate you too much. One very useful AWT container to use with layouts is
the Panel component. You can arrange components in a panel and then add the panel, itself, to the layout of an
applet or application. Youll see how to do that in this chapter. Thats it. Now that we have reviewed whats in
this chapter, its time to turn to the Immediate Solutions section.
217
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Immediate Solutions
Using Text Fields
Hey, says the Novice Programmer, I want to let users type in a password, but that silly Johnson keeps
standing over peoples shoulders and watching as they type their passwords. Thats easily fixed, you say.
Just set the echo character of the text field to an asterisk or some similar character. Problem solved!
You first saw and used text fields in the previous chapter; these components can display a single line of text, and
the user can edit that text. Heres the inheritance diagram for the text field class, TextField:
java.lang.Object
|____java.awt.Component
|____java.awt.TextComponent
|____java.awt.TextField
You can find the constructors of the TextField class in Table 7.1 and its methods in Table 7.2.
Table 7.1: Constructors of the TextField class
Constructor Does this
TextField() It constructs a new text field
TextField(int columns) It constructs a new, empty text field with the indicated number of columns
TextField(String text) It constructs a new text field with the indicated text
TextField(String text, int It constructs a new text field initialized with the indicated text and with
columns) the indicated number of columns
ActionListener[] It returns an array of all the action listeners registered on this TextField
getActionListeners()
int getColumns() It gets the number of columns in the text field
char getEchoChar() It gets the character to be used for echoing
<T extends It returns an array of all the listeners currently registered as
EventListener>T[]getListeners(Clas FooListeners on this TextField
s<T> listenerType)
Dimension getMinimumSize() It gets the minimum dimensions for the text field
Dimension getMinimumSize It gets the minimum dimensions for a text field with the indicated number
(int columns) of columns
Dimension getPreferredSize() It gets the preferred size of the text field
Dimension getPreferredSize It gets the preferred size of the text field with the indicated number of
(int columns) columns
Dimension minimumSize() It is deprecated and replaced by getMinimumSize()
Dimension minimumSize It is deprecated and replaced by getMinimumSize(int)
(int columns)
protected String paramString() It gets the parameter string representing the state of the text field
218
Immediate Solutions
Lets look at an example. In this case, well create a password text field that will display an asterisk (*) each time
the user types a character. You may be wondering how you can read the typed password in the text field. The
answer is by using the text fields getText() method, which the text field inherits from the Component class.
The typed password is displayed in the applets status bar when the user presses the Enter key. Heres the code:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=PasswordDemo.class
WIDTH=250
HEIGHT=200 >
</APPLET> */
public class PasswordDemo extends Applet implements ActionListener {
public TextField text1;
public void init() {
text1 = new TextField(30);
add(text1);
. . .
Next, we set the echo character in text1 (the password text field) to * and add an action listener to that text
field:
public void init()
{
text1 = new TextField(30);
add(text1);
text1.setEchoChar('*');
text1.addActionListener(this);
}
When the user presses Enter, the actionPerformed() method is called, so we override that method to set the
text in the status bar of the applet using the showStatus() method:
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == text1) { showStatus(text1.getText()); }
}
}
The result of this code appears in Figure 7.1. When the user types a password in the top text field and presses
Enter, that password appears in the applets status bar (not exactly what youd call high security).
219
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Another useful text field method is getSelectedText(), which lets you get the selected text in a text field.
You can find the process of Using Text Areas in detail in Chapter 8.
Using Labels
AWT labels are much like AWT text fields, except that the user cant edit the text in them. You can use labels to
present no editable text, or as the name implies, to label other components. Heres the inheritance diagram for the
Label class:
java.lang.Object
|____java.awt.Component
|____java.awt.Label
You can find the Label classs constructors in Table 7.3 and its methods in Table 7.4.
Table 7.3: Constructors of the Label class
Constructor Does this
Label() It constructs an empty label
Label(String text) It constructs a new label with the specified string of text, left justified
Label(String text, int alignment) It constructs a new label that presents the specified string of text with the
specified alignment
220
Immediate Solutions
You can justify the text in a label by passing the fields Label.LEFT, Label.CENTER, and Label.RIGHT to the
labels constructor. Heres an example that creates three labels with the various possible text justifications:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=LabelDemo.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
public class LabelDemo extends Applet {
Label label1;
Label label2;
Label label3;
public void init() {
label1 = new Label("Kogent Learning Solutions", Label.LEFT);
add(label1);
label2 = new Label("Kogent Learning Solutions", Label.CENTER);
add(label2);
label3 = new Label("Kogent Learning Solutions", Label.RIGHT);
add(label3); }
}
Figure 7.2 shows the result of this applet.
Using Buttons
I want to let users interact with my program, says the Novice Programmer. I want to let them indicate what
they want to do with just a click of the mouse, I want them to be able to select an action quickly and easily, and I
want.... Buttons, you say. What you want are buttons. Right, replies the NP.
Every GUI user is familiar with buttonsthose elementary controls you click to signal to a program to start
some action. For example, you might let the user click a button to change the background color of an application.
Buttons are supported in the java.awt.Button class. Heres the lineage of that class:
java.lang.Object
|____java.awt.Component
|____java.awt.Button
221
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Youll find the constructors for the Button class in Table 7.5 and the methods of this class in Table 7.6.
Table 7.5: Constructors of the Button class
Constructor Does this
Button() It constructs a button without any label
Button(String label) It constructs a button with the indicated label
To handle button events, you use the ActionListener interface, as you saw in the previous chapter. This
interface has only one method, actionPerformed(), which is passed an object of the ActionEvent class
when the button is clicked:
void actionPerformed(ActionEvent e) { . . . }
Heres the inheritance diagram of the ActionEvent class:
java.lang.Object
|____java.util.EventObject
|____java.awt.AWTEvent
|____java.awt.event.ActionEvent
Youll find the methods of the ActionEvent class in Table 7.7.
Table 7.7: Methods of the ActionEvent class
Method Does this
String getActionCommand() It gets the command string associated with this action
int getModifiers() It gets the modifier keys held down during the event
long getWhen() It gets the timestamp of when this event occurred
String paramString() It gets a parameter string identifying the event
As you saw in the previous chapter, there are two main ways to determine which button was selectedusing
the getSource() method and using commands. Well take a look at the getSource() way of doing things
222
Immediate Solutions
first. Heres an example with a button that, when clicked, displays the message Kogent Learning Solutions in a
text field (note that we register an action listener with the button and find out which button was clicked with the
getSource() method before setting the appropriate text in the text field):
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class ButtonDemo1 extends Applet implements ActionListener {
/* <APPLET
CODE=ButtonDemo1.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
TextField text1;
Button button1;
public void init() {
text1 = new TextField(20);
add(text1);
button1 = new Button("Click Me!");
add(button1);
button1.addActionListener(this); }
public void actionPerformed(ActionEvent e) {
String text = new String ("Kogent Learning Solutions");
if(e.getSource() == button1) { text1.setText(text); }
}
}
The result of this code appears in Figure 7.3.
Now in the actionPerformed() method, you can get the command for the button that was clicked with the
getActionCommand() method. If the button that was clicked is the right one, you can place the message in the
text field, like this:
public void actionPerformed(ActionEvent e) {
String text= new String ("Kogent Learning Solutions");
String cmd = e.getActionCommand();
if(cmd.equals("button1")) { text1.setText(text); }
}
}
Using Checkboxes
Now I have another problem, the Novice Programmer says. I want to let users select what they want on a
pizza, so Id like a button that, when clicked, stays clicked so that the users know what they have already
selected. No problem at all, you say. Dont use buttons. No? the NP asks. No, you say. Use checkboxes
instead.
A checkbox allows the user to select options; when the user clicks a checkbox, a visual indication of some kind,
such as a checkmark (the indicator varies by operating system when using the AWT), is used to specify that the
option is selected. Clicking the checkbox again deselects the checkbox. In AWT, checkboxes are supported with
the java.awt.Checkbox class, which has the following inheritance diagram:
java.lang.Object
|____java.awt.Component
|____java.awt.Checkbox
You can find the constructors for the Checkbox class in Table 7.8 and the methods of this class in Table 7.9. You
can use the setState() and getState() methods to set and get the state of a checkbox, respectively.
Table 7.8: Constructors of the Checkbox class
Constructor Does this
Checkbox() It creates a checkbox without a label
Checkbox(String label) It creates a checkbox with the indicated label
Checkbox(String label, boolean state) It creates a checkbox with the indicated label and sets the
indicated state
Checkbox(String label, boolean state It creates a checkbox with the indicated label and sets it in the
CheckboxGroup group) indicated state and checkbox group
Checkbox(String label, It constructs a checkbox with the indicated label in the
CheckboxGroup group, boolean state) indicated checkbox group and sets it to the indicated state
224
Immediate Solutions
Heres an example in which we add four checkboxes to an applet; and when the user clicks a checkbox, we
indicate which checkbox was clicked in a text field. Note that checkboxes do not use the ActionListener
interface as buttons do; instead, they use the ItemListener interface, which is set up to handle components
that can be selected or deselected. The ItemListener interface has only one method, itemStateChanged(),
which is passed as a parameter of the class ItemEvent:
void itemStateChanged(ItemEvent e)
You can find the methods of the ItemEvent class in Table 7.10.
Table 7.10: Methods of the ItemEvent class
Method Does this
Object getItem() It gets the item affected by the event
ItemSelectable getItemSelectable() It gets the originator of the event
int getStateChange() It gets the type of state change (selected or deselected)
String paramString() It gets a parameter string matching this event
Heres how we add the checkboxes to an applet and add an ItemListener interface to each one:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=CheckboxDemo1.class
WIDTH=200
HEIGHT=200>
</APPLET> */
public class CheckboxDemo1 extends Applet implements ItemListener {
Checkbox check1, check2;
TextField text1;
public void init() {
check1 = new Checkbox("Pizza");
add(check1);
check1.addItemListener(this);
check2 = new Checkbox("Burger");
add(check2);
check2.addItemListener(this);
text1 = new TextField(20);
add(text1);
}
Now we override the itemStateChanged() method, determining which checkbox was clicked by using the
ItemEvent objects getItemSelectable() method:
public void itemStateChanged(ItemEvent e) {
if(e.getItemSelectable() == check1) {
text1.setText("You clicked Pizza"); }
225
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
226
Immediate Solutions
Note, for example, that you can determine which radio button is selected in a group with the CheckboxGroup
classs getSelectedCheckbox() method, and you can set which one is selected with the
setSelectedCheckbox() method. Heres an example in which we create a checkbox group named group,
and we add two radio buttons to that group. You add a radio button to a checkbox group by adding the group
as a parameter in a checkboxs constructor, which turns the checkbox into a radio button. Heres what this looks
like:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=RadioButtonDemo.class
WIDTH=200
HEIGHT=200>
</APPLET> */
public class RadioButtonDemo extends Applet implements ItemListener {
CheckboxGroup group; Checkbox check1, check2;
TextField text1;
public void init() {
group = new CheckboxGroup();
check1 = new Checkbox("Male", false, group);
add(check1);
check1.addItemListener(this);
check2 = new Checkbox("Female", false,group);
add(check2);
check2.addItemListener(this);
text1 = new TextField(20);
add(text1);
}
Note that we have added an ItemListener interface to each radio button, so we can implement the
ItemListener interface and the itemStateChanged() method to indicate which radio button was clicked,
like this:
public void itemStateChanged(ItemEvent e) {
227
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Layout Managers
A layout manager organizes the controls automatically in a window with the help of certain algorithms. It is an
object which implements the LayoutManager interface. It also finds the size and position of the components in
a container. Each object of the container is associated with a layout manager.
The setLayout() method is used for setting the layout manager. If there is no setLayout() defined, then the
default layout manager is used. This method can be defined as follows:
void setLayout(LayoutManager layoutManager)
where layoutManager is referred to the desired layout manager.
If you pass null for layoutManager, then it disables the layout manager. Youll need to determine the size and
the position of the component manually. For this, you have to use the method setBounds(), which is defined
by the component.
Flow Layouts
Uh-oh, says the Novice Programmer, Javas gone all wacky again! Whats it done this time? you ask. The
NP says, Well, Im creating a multiplying calculator, and I want all the text fields to be stacked vertically, but
they keep rearranging themselves into rows. Thats because you are using a flow layout, you say.
Java has a number of AWT layout managers that handle how components are displayed in containers, and you
can install those layout managers into those containers. By default, applets use the flow layout manager, which
arranges components like text in a word processor, including wrapping them to the next line. The constructors of
the FlowLayout class appear in Table 7.12 and its methods in Table 7.13.
Table 7.12: Constructors of the FlowLayout class
Constructor Does this
FlowLayout() It constructs a new FlowLayout with centered alignment and a default 5
pixels horizontal and vertical gaps
FlowLayout(int align) It constructs a new FlowLayout with the given alignment and a default 5
pixels horizontal and vertical gaps
FlowLayout(int align, int hgap, It creates a new flow layout manager with the given alignment and the
int vgap) given horizontal and vertical gaps.
228
Immediate Solutions
You do have some control over how the components in a flow layout are arranged; you can specify their
alignment by using these FlowLayout fields:
CENTERIt specifies that each row of components must be centered.
LEADINGIt specifies that each row of components must be justified to the leading edge of the container.
LEFTIt specifies that each row of components must be left-justified.
RIGHTIt specifies that each row of components must be right-justified.
TRAILINGIt specifies that each row of components must be justified to the trailing edge of the container.
The default flow layout is to center each component in a row, but heres how we create a new flow layout
manager that right-justifies components by using the setLayout() method:
import java.applet.Applet;
import java.awt.*;
/* <APPLET
CODE=FlowLayoutDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class FlowLayoutDemo extends Applet {
Button button1, button2, button3;
public void init() {
setLayout(new FlowLayout(FlowLayout.RIGHT));
button1 = new Button("Kogent");
add(button1);
button2 = new Button("Learning");
add(button2);
button3 = new Button("Solutions");
add(button3);
}
}
229
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
After a few buttons are added to this new flow manager, you can see that they are indeed right-justified, as
shown in Figure 7.6.
230
Immediate Solutions
As you can see in the figure, the text fields are arranged to suit the flow layout manager, and the result is hardly
what the NP intended. To fix this situation, well take a look at another layout managerthe grid layout
managernext.
Grid Layouts
So how do I fix my multiplying calculator? The text fields are all over the place, the NP asks. You have to use
a different layout manager, you say, such as the grid layout manager.
The grid layout manager lets you add components to a container, positioning them in a grid. You tell the grid
layout manager what the dimensions of your grid will besuch as five rows and four columnsand when you
add components to the layout, theyll be added starting left of the first row. After the first row is filled,
components are placed into the first column of the second row, and that row is then filled, and so on. Note that
each component is given the same size and dimensions.
Heres the inheritance diagram for the grid layout manager:
java.lang.Object
|____java.awt.GridLayout
Youll find the constructors for the GridLayout class in Table 7.14 and the methods of this class in Table 7.15.
Table 7.14: Constructors of the GridLayout class
Constructor Does this
GridLayout() It creates a grid layout with one column per component in one row
GridLayout(int rows, int cols) It creates a grid layout with the given number of rows and columns
GridLayout(int rows, int cols, int It creates a grid layout with the given number of rows and columns as well
hgap, int vgap) as the given amount of spacing
Heres an example in which we create a grid of five rows and one column by passing those dimensions to the
grid layout managers constructor as GridLayout(5,1). When we start adding components to this layout,
theyll be stacked one on top of the other. Heres how that looks:
import java.applet.Applet;
import java.awt.*;
231
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
import java.awt.event.*;
/* <APPLET
CODE=GridLayoutDemo.class
WIDTH=250
HEIGHT=200>
</APPLET> */
public class GridLayoutDemo extends Applet implements ActionListener {
TextField num1, num2, result;
Label multiply; Button button1;
public void init() {
setLayout(new GridLayout(5,1));
num1 = new TextField(); add(num1);
multiply = new Label("*"); add(multiply);
num2 = new TextField(); add(num2);
button1 = new Button("="); add(button1);
button1.addActionListener(this);
result = new TextField();
add(result); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
int product = Integer.parseInt(num1.getText())
*Integer.parseInt(num2.getText());
result.setText(String.valueOf(product)); }
}
}
The result of this code appears in Figure 7.8:
Using Panels
The NP is still dissatisfied with layout issues and says, I need finer control in my layoutI have got a lot of
components to display. OK, you say. You can use Java panels to get that kind of control. Great! Tell me all
about it, replies the NP.
The Java Panel class is a container you can use in your layouts. You add components to a panel and then add
the panel to a layout. Because panels are containers, you can set their layout managers by using the
setLayout() methods. Panels, themselves, are not visual containersthey dont have borders, for example
and exist only to contain components. Heres the inheritance diagram for the Panel class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____java.awt.Panel
232
Immediate Solutions
The constructor for the Panel class appears in Table 7.16 and the method of this class appears in Table 7.17.
Table 7.16: The constructor of the Panel class
Constructor Does this
Panel() It creates a new panel with the default layout manager
Panel(LayoutManager layout) It creates a new panel with the specified layout manager
Heres an example in which we derive a new class ButtonPanel from the Panel class and add a few buttons
to the panel in the ButtonPanel constructor:
import java.applet.Applet;
import java.awt.*;
/* <APPLET
CODE=PanelDemo.class
WIDTH=150
HEIGHT=150 >
</APPLET> */
class ButtonPanel extends Panel {
Button button1, button2, button3, button4;
ButtonPanel() {
button1 = new Button("A");
add(button1);
button2 = new Button("B");
add(button2);
button3 = new Button("C");
add(button3);
button4 = new Button("D");
add(button4); }
}
Now we can arrange panels of this new class in a grid layout as follows:
public class PanelDemo extends Applet {
ButtonPanel panel1, panel2, panel3, panel4;
public void init() {
setLayout(new GridLayout(2,2));
panel1 = new ButtonPanel();
add(panel1);
panel2 = new ButtonPanel();
add(panel2);
panel3 = new ButtonPanel();
add(panel3);
panel4 = new ButtonPanel();
add(panel4);
}
}
The result of this code appears in Figure 7.9:
233
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
As you can see in this figure, each panel has been added to the grid layout; in this way, using panels gives you
finer layout control.
Border Layouts
The NP is back and asks, Are there any more layouts I should know about? Of course, you say. You should
know the border layout, for example. The NP asks, Does that arrange borders? Sort of, you say.
The border layout lets you arrange components around the border of a container, which is useful if you want to
support, say, scrollbars and scroll a central component. Border layouts are the default in AWT windows, frame
windows, and dialog boxes. You indicate where you want a component to go by passing text strings, such as
North, East, and so on, to the BorderLayout constructor. Heres the inheritance diagram for
BorderLayout:
java.lang.Object
|____java.awt.BorderLayout
You can find the constructors of the BorderLayout class in Table 7.18 and its methods in Table 7.19.
Table 7.18: Constructors of the BorderLayout class
Constructor Does this
BorderLayout() It constructs a new border layout without any gap between components
BorderLayout(int hgap, int vgap) It constructs a border layout with the indicated gaps between components
234
Immediate Solutions
Heres an example in which we create a panel containing a text field and add four buttons around the border of
the panel. When the user clicks a button, the applet will indicate which button was clicked in the text field.
Heres how we create the panel that displays a text field:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=BorderLayoutDemo.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
class TextPanel extends Panel {
TextField text1;
TextPanel() { text1 = new TextField(20);
add(text1); }
}
Now we create a border layout, placing the text field panel in the center and adding four buttons around the
border. You can specify where you want to place a component with strings, such as North, West, Center
and so on. Therefore, creating the layout looks like this:
public class BorderLayoutDemo extends Applet implements ActionListener {
Button button1, button2, button3, button4;
TextPanel panel1;
public void init() {
setLayout(new BorderLayout());
button1 = new Button("1");
add("North", button1);
button1.addActionListener(this);
button2 = new Button("2");
add("West", button2);
button2.addActionListener(this);
button3 = new Button("3");
add("South", button3);
button3.addActionListener(this);
button4 = new Button("4");
add("East", button4);
button4.addActionListener(this);
panel1 = new TextPanel();
add("Center", panel1);
panel1.text1.setLocation(0, 0); }
public void actionPerformed(ActionEvent e) {
panel1.text1.setText("Button " +
((Button) e.getSource()).getLabel() + " clicked"); }
}
The result of this code appears in Figure 7.10:
235
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Card Layouts
So, the NP says, are there any other AWT layouts? There are, you say, such as the card layout. You are
making that up, says the NP.
The card layout manager displays the containers you pass to it as cards. You assign each card a name, and then
you move from one card to another using the show() method of CardLayout class. Heres the inheritance
diagram for the CardLayout class:
java.lang.Object
|____java.awt.CardLayout
Besides the show() method, you can also use the first(), last(), next(), and previous() methods of the
CardLayout class to display specific cards. Youll find the CardLayout classs constructors in Table 7.20 and
the methods of this class in Table 7.21:
Table 7.20: Constructors of the CardLayout class
Constructor Does this
CardLayout() It creates a new card layout
CardLayout(int hgap, int vgap) It creates a new card layout with the given horizontal and vertical gaps
236
Immediate Solutions
Heres an example in which we create a class CardLayoutDemo that displays an applet containing a label. The
user can click the applet to move to the next card and a label to indicate what text the present card label contains:
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/*
<APPLET
CODE = CardLayoutDemo.class
HEIGHT=150
WIDTH=200>
</APPLET>*/
public class CardLayoutDemo extends Applet implements MouseListener
{
Panel panel1, panel2, panel3, panel4;
Label label1, label2, label3;
CardLayout cardLayout;
public void init()
{
label1 = new Label("Kogent");
label2 = new Label("Learning");
label3 = new Label("Solutions");
panel2 = new Panel();
panel3 = new Panel();
panel4 = new Panel();
panel2.add(label1);
panel3.add(label2);
panel4.add(label3);
237
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
addMouseListener(this);
. . .
}
}
In the main applet class, we create four panels and three labels. The layout of the panel panel1 is set to card
layout. The other three panels are added to the panel panel1, giving them the names First, Second, and
Third. We add mouse listener to the applet using the addMouseListener() method so that the user can
move to the next card on clicking the applet. Next, we give body of the mouseClicked() method and call the
next() method of the CardLayout class to move to the next card as follows:
public void mouseClicked(MouseEvent e) {
cardLayout.next(panel1); }
The other methods of the MouseListener interface are written without any code statements in the method
body:
public void mousePressed(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
The result appears in Figure 7.11:
238
Immediate Solutions
239
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Adding components to a container using a grid bag layout is something like using a grid layout, except you have
more options, such as setting the relative widths and heights of the components. Setting up a grid bag layout is a
two-step process: You first configure how you want a component to appear relative to the other components and
then you add the component to the layout. You configure components using the GridBagConstraints class;
the fields of that class appear in Table 7.24, its constructors in Table 7.25, and its method in Table 7.26.
Table 7.24: Fields of the GridBagConstraints class
Field Does this
static int ABOVE_BASELINE It indicates the possible value for the anchor field
static int ABOVE_BASELINE_LEADING It indicates the possible value for the anchor field
static int It indicates the possible value for the anchor field
ABOVE_BASELINE_TRAILING
int anchor It is used when the component is smaller than its display area
static int BASELINE It indicates the possible value for the anchor field
static int BASELINE_LEADING It indicates the possible value for the anchor field
static int BASELINE_TRAILING It indicates the possible value for the anchor field
static int BELOW_BASELINE It indicates the possible value for the anchor field
static int BELOW_BASELINE_LEADING It indicates the possible value for the anchor field
static int It indicates the possible value for the anchor field
BELOW_BASELINE_TRAILING
static int BOTH It resizes the component both horizontally and vertically
static int CENTER It puts the component in the center of its display area
static int EAST It puts the component on the right side of its display area, centered vertically
int fill It is used when the components display area is larger than the components
requested size
static int FIRST_LINE_END It places the component in the corner of its display area, where the first line
would normally end for current ComponentOrienation
static int FIRST_LINE_START It places the component in the corner of its display area, where the first line
would normally start for current ComponentOrienation
int gridheight It indicates the number of cells in a column for the components display area
int gridwidth It indicates the number of cells in a row for the components display area
int gridx It indicates the cell at the leading edge of the components display area,
where the first cell in the row has gridx=0
int gridy It indicates the cell at the top of the components display area, where the first
cell in the row has gridy=0
static int HORIZONTAL It resizes the component horizontally
240
Immediate Solutions
241
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Lets look at an example of putting a grid bag layout to work. In this example, well create the applet you see in
Figure 7.12; here, we have put three buttons into the top row of the layout, making the middle button twice as
wide as the others, and we have added a text field underneath. When the user clicks a button, the color of the
text field changes according to the name of color mentioned on the button, as you see in Figure 7.12:
242
Immediate Solutions
cons.weightx = 1;
button1 = new Button("Red");
gbl.setConstraints(button1, cons);
add(button1);
button1.addActionListener(this);
cons.weightx = 2;
button2 = new Button("Green");
gbl.setConstraints(button2, cons);
add(button2);
button2.addActionListener(this);
cons.weightx = 1;
button3 = new Button("Orange");
cons.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(button3, cons);
add(button3);
button3.addActionListener(this);
text1 = new TextField();
cons.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(text1, cons);
add(text1);
}
All thats left is to handle button clicks, and we do that by displaying the number of the button that was clicked:
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button1)
text1.setBackground(Color.red);
if(e.getSource()==button2)
text1.setBackground(Color.green);
if(e.getSource()==button3)
text1.setBackground(Color.orange);
}
}
And thats all it takes. Now this code will create the applet you see in Figure 7.12.
243
Chapter 7: AWTText Fields, Buttons, Checkboxes, Radio Buttons, and Layouts
Summary
In this chapter, the AWT controls such as text fields, buttons, checkboxes, radio buttons, and layouts have been
explained briefly. Then, you came to know how to implement a layout manager by understanding different
types of layout. Further, we have explained the concept of inserts and padding, and finally the creation of
custom layout manager.
The next chapter discusses about AWT- lists, choices, text areas, scrollbars, and scroll panes.
244
8
AWTLists, Choices,
Text Areas, Scroll bars,
and Scroll Panes
If you need an immediate solution to: See page:
Using Text Areas 248
Replacing Text in Text Areas 251
Searching and Selecting Text in Text Areas 252
Using Lists 253
Using Multiple-Selection Lists 257
Using Choice Controls 260
Using Scroll bars 265
Scroll bars and Border Layouts 269
Using Scroll Panes 272
245
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
In Depth
This chapter is all about a number of important AWT componentslists, choices, text areas, scroll bars, and
scroll panes. These components are all fundamental to AWT programmingthey are familiar to nearly all GUI
usersand well take a look at them in overview in this section. Note that one of the major themes of this
chapter is scrolling; all the controls in this chapter support scrolling in one way or another, letting the user move
around large documents with ease.
Lists
As the name suggests, a list control presents the user with a list of itemstext stringsfrom which one can
select. In windowing environments, space is often at a premium, so it is a good idea to place items in lists,
because using scroll bars, you can hide long lists in short list components. The user can select the item in the list
he or she wants, double-click it, and initiate some action. Lists can also support multiple selections at the same
time, using the Shift and Ctrl keys. However, if you support multiple selections, you have to think about how to
use the mouse in a list control. Clicking an item selects it, so the user cant just make multiple selections and then
double-click one to initiate some action because when one item is double-clicked, all the others are deselected. To
solve this problem, Sun suggests you to use some other event, such as a button click, to initiate an action when
dealing with multiple selections.
Choices
Choice controls also present the user with a list of items to select from, but theres a differencechoice controls
are even more compact than lists. They look much like text fieldsalthough you cant edit the text in them
with a small button on the right that has a downward-pointing arrow. When the user clicks the arrow, a list
opens displaying all the available choices, and the user can select from one of them. After the selection is made,
the choice control closes the list and displays the current selection. If the user opens the list again, the current
selection is highlighted. Note that choice controls are only designed to display one choice at a time, which means
you cant select more than one item in the list at a time. Using Shift+click and Ctrl+click is the same as clicking
an item. Like the other components in this chapter, choice controls support scrollingif the list of items is long,
scroll bars will appear on the side of the list automatically.
Text Areas
Text areas are much like text fields, except they support text in two-dimensions, with both rows and columns, so
you can display considerably more text in them. You indicate the size in rows and columns (as measured in
characters) that you want the text area to have when you create it. The result is just like a text field that has the
specified number of rows and columns. You use text areas when you want to work with entire documents, not
just single lines of text. As with the other components in this chapter, text areas support scrolling. You can
specify whether you want a horizontal scroll bar, a vertical scroll bar, both, or none. If you dont have a
horizontal scroll bar (and only if you dont have a horizontal scroll bar), the word-wrapping feature is
automatically enabled.
Scroll bars
Scroll bars are, of course, the zenith of scrolling controls, and every GUI user knows about them. The user uses
the mouse to manipulate the thumbalso called the scroll box, elevator, or bubblein a scroll bar to select a value
from a continuous range. You set that range when you create the scroll bar, and after the user selects a new
value, you can catch scroll bar events to read that new value. The user can also click the arrow buttons at the
ends of a scroll bar to increment or decrement the scroll bars setting by an amount you specify. The user can
also click the scroll bars track (that is, the part thats not the thumb or the arrow buttons) to increment or
decrement the scroll bars setting by an amount you specify.
246
In Depth
Scroll Panes
You might want to use scroll bars to scroll other components, such as a long text field, but Java controls either
support scroll bars themselves or dont support scrolling at all. To make scrolling of other components easier,
Java provides the ScrollPane class. You use scroll panes by adding components to them and letting the scroll
panes handle the scrolling. After you have added a large component to a scroll pane, only part of it is visible at
once, and you can use the scroll panes scroll bars to scroll to other parts of that component.
Thats it. Now that we have reviewed whats in this chapter, it is time to turn to the Immediate Solutions
section.
247
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
Immediate Solutions
Using Text Areas
Uh-oh, says the Novice Programmer, I have got a problem. I have been writing my novel in a Java text field,
and.... You smile and say, And you have run out of space? Well, says the NP, it is just not very convenient
to write an entire novel as one line of text. Try text areas, you suggest.
A text area is much like a two-dimensional text field; in fact, thats its big advantage you can display whole
documents in text areas, including word wrapping at the end of lines. You can also use scroll bars to move
through the text. Note, however, that if you have enabled a horizontal scroll bar, word wrapping will be turned
off. Heres the inheritance diagram for the AWT TextArea class:
java.lang.Object
|____java.awt.Component
|____java.awt.TextComponent
|____java.awt.TextArea
Youll find the fields of the TextArea class, which you use in the TextArea classs constructors, in Table 8.1, its
constructors in Table 8.2, and its methods in Table 8.3.
Table 8.1: Fields of the TextArea class
Field Does this
static int SCROLLBARS_BOTH It creates and displays both vertical and horizontal scroll bars
static int It creates and displays a horizontal scroll bar only
SCROLL BARS_HORIZONTAL_ONLY
static int SCROLLBARS_NONE It indicates not to create any scroll bars for the text area
static int It creates and displays a vertical scroll bar only
SCROLL BARS_VERTICAL_ONLY
248
Immediate Solutions
There are several ways to place text in a text area. For example, you can use the insert() method to insert the
text at a specific character position (starting at 0) in the string that the text area holds, or you can use the
append() method to append the text to the end of the current text. Lets look at an example. In this case, well
create a text area with 10 rows and 20 columns (note that these dimensions are measured in characters). Well
also add two radio buttons that the user can select. Heres the code:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=TextAreaDemo1.class
WIDTH=200
HEIGHT=200>
</APPLET> */
public class TextAreaDemo1 extends Applet implements ItemListener {
TextArea area1;
CheckboxGroup group;
Checkbox check1,check2;
public void init() {
area1 = new TextArea(10,20);
add(area1);
group = new CheckboxGroup();
check1 = new Checkbox("Male", false, group);
add(check1);
check1.addItemListener(this);
check2 = new Checkbox("Female", false, group);
add(check2);
check2.addItemListener(this);
}
public void itemStateChanged(ItemEvent e) {
249
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
250
Immediate Solutions
251
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
252
Immediate Solutions
Using Lists
The Product Support Specialist is back and says, Theres a problem. Yes? you ask. About your catalogue of
all the classical music CDs in your most recent programtheres more than a hundred-thousand listings.
Thats right, you say proudly. Of course, I guess that it makes the list a little tall on the screen. About 2,000
feet tall, says the PSS.
If you have a long list of items that you want to present, consider by using a list control. You can fill a list with
many text items (using the List classs add() method) and present only a few at a timeyou can choose how
manyto the user. The user can highlight an item in the list by clicking the item and can initiate some action by
double-clicking that item. In fact, the user can select multiple items in a list and initiate some action, typically by
clicking a button. Heres the inheritance diagram for the List class:
java.lang.Object
|____java.awt.List
|____java.awt.Component
Youll find the constructors for the List class in Table 8.4 and the methods for this class in Table 8.5. Take a
close look at the methods table; a lot of useful ones are listed, such as getItemCount(), which returns the
number of items in the list.
Table 8.4: Constructors of the List class
Constructor Does this
List() It creates a new scrolling list
List(int rows) It creates a new scrolling list with the specified number of visible lines
List(int rows, boolean It creates a new scrolling list with the specified number of rows. Multiple
multipleMode) selection is enabled if multipleMode is true
253
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
254
Immediate Solutions
Lets look at an example. In this case, well add six color names to a list control, making only three of them
visible at once. When the user double-clicks an item, background color of the applet changes accordingly. We
start by creating the list control and making only three items visible, like this:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=ListDemo.class
WIDTH=200
HEIGHT=200>
</APPLET> */
public class ListDemo extends Applet implements ActionListener {
List list1;
public void init() {
list1 = new List(3);
. . .
}
Now we add six list items by using the add() method:
public void init() {
list1 = new List(3);
list1.add("Red");
list1.add("Green");
list1.add("Orange");
list1.add("Pink");
list1.add("Magenta");
list1.add("Yellow");
add(list1);
. . .
}
After adding the list to the layout, we add a listener to it. It turns out that lists use ActionListener interfaces,
just as buttons do. Heres how we add this to the code:
public void init() {
255
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
256
Immediate Solutions
257
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
Next, we loop over that array, adding all the items to a string that starts The selected items are::
public void actionPerformed(ActionEvent e) {
String selected = new String("The selected items are:");
if(e.getSource() == button1) {
selections = list1.getSelectedItems();
for(int loopIndex = 0; loopIndex < selections.length;loopIndex++)
{ selected += " " + selections[loopIndex]; }
. . . }
}
Finally, we place the string with all the selections on the applets status bar:
public void actionPerformed(ActionEvent e) {
String selected = new String("The selected items are:");
if(e.getSource() == button1) {
selections = list1.getSelectedItems();
for(int loopIndex = 0; loopIndex < selections.length;loopIndex++)
{
selected += " " + selections[loopIndex]; }
showStatus(selected); }
}
And thats it. The result appears in Figure 8.6. As you can see in this figure, the user can make multiple
selections in this new list; and when he/she clicks the button, the selections made will appear on the status bar
of the applet.
258
Immediate Solutions
list1.add("Second");
list1.add("Third");
list1.add("Fourth");
list1.add("Fifth");
list1.add("Sixth");
list1.add("Seventh");
list1.add("Eighth");
list1.add("Ninth");
add(list1);
add(button1);
list1.addItemListener(this);
button1.addActionListener(this); }
public void itemStateChanged(ItemEvent e) {
if(e.getItemSelectable() == list1) {
String sel= ((List)e.getItemSelectable()).getSelectedItem();
if(sel!=null){
text1.setText("You selected: " +
((List)e.getItemSelectable()).getSelectedItem()); } }
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
ItemListener[] al = list1.getItemListeners();
for (int i=0; i<al.length; i++) {
list1.removeItemListener(al[i]);
text2.setText("Listener Removed"); }
}
}
}
The result appears in Figure 8.7. As you can see in this figure, users can select the items from the list box; and
when they do, the program displays that item in the text fields. But when the user clicks on Remove Listener
button, listener on list will be removed and user will not be able to select the item from the list.
259
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
</APPLET> */
public class ListItemDemo2 extends Applet implements ActionListener {
TextArea text1;
TextField text2;
List list1;
Button button1;
public void init() {
text1 = new TextArea(5,20);
text2 = new TextField(20);
button1 = new Button("Remove Listener");
add(text1);
add(text2);
list1 = new List(4, true);
list1.add("First");
list1.add("Second");
list1.add("Third");
list1.add("Fourth");
list1.add("Fifth");
list1.add("Sixth");
list1.add("Seventh");
list1.add("Eighth");
list1.add("Ninth");
add(list1);
add(button1);
list1.addActionListener(this);
button1.addActionListener(this); }
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting())
return;
text1.setText("");
Object[] items = list1.getSelectedItems();
for(int i=0; i<items.length; i++)
text1.append(items[i] +"\n"); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
ActionListener[] al = list1.getActionListeners();
for (int i=0; i<al.length; i++) {
list1.removeActionListener(al[i]);
text2.setText("Listener Removed"); }
}
}
}
260
Immediate Solutions
Youll find the constructor for the Choice class in Table 8.6 and the methods of this class in Table 8.7.
Table 8.6: The constructor of the Choice class
Constructor Does this
Choice() It creates a new choice control
Lets look at an example. In this case, well add a choice control to a program and use the controls add()
method to add items to its internal list. When the user makes a selection, well display the new selection in a text
field.
We start by creating a new choice control and populating its internal list with choices (note that you dont have a
lot of options when creating choice controlstheres only one constructor, and it doesnt take any parameters).
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
261
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
/* <APPLET
CODE=ChoiceDemo1.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
public class ChoiceDemo1 extends Applet implements ItemListener, ActionListener {
TextField text1, text2;
Choice choice1;
Button button1;
public void init() {
text1 = new TextField(20);
text2 = new TextField(20);
button1 = new Button("Remove Listener");
add(text1);
add(text2);
choice1 = new Choice();
choice1.add("First");
choice1.add("Second");
choice1.add("Third");
choice1.add("Fourth");
choice1.add("Fifth");
choice1.add("Sixth");
choice1.add("Seventh");
choice1.add("Eighth");
choice1.add("Ninth");
choice1.add("Tenth");
choice1.add("Eleventh");
choice1.add("Twelfth");
. . .
}
With a large number of items like this, the choice control will add a vertical scroll bar to the list automatically.
Now well handle events in the choice control. You use ItemListener interfaces with choice controls and
ActionListener interfaces, as you do with list controls. The ItemListener interface has only one method,
itemStateChanged():
void itemStateChanged(ItemEvent e)
This method is passed as an object of the ItemEvent class. This classs fields appear in Table 8.8, its constructor
in Table 8.9, and its methods in Table 8.10.
Table 8.8: Fields of the ItemEvent class
Field Does this
static int DESELECTED It indicates that a selected item was unselected
static int ITEM_FIRST It indicates the first number in the range of IDs used for item events
static int ITEM_LAST It indicates the last number in the range of IDs used for item events
static int ITEM_STATE_CHANGED It indicates that an items state changed
static int SELECTED It indicates that an item was selected
262
Immediate Solutions
263
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
264
Immediate Solutions
The output of the ChoiceDemo2 class has been given in Figure 8.9:
265
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
Scroll bars dont use ActionListener or ItemListener interfaces; instead, they use AdjustmentListener
interfaces. The AdjustmentListener interface has only one method, adjustmentValueChanged():
void adjustmentValueChanged(AdjustmentEvent e)
This method, adjustmentValueChanged(), passes an object of class AdjustmentEvent. Youll find the
fields of the AdjustmentEvent class in Table 8.13, its constructor in Table 8.14, and its methods in Table 8.15.
Note, in particular, that you can use the AdjustmentEvent classs getAdjustmentType() method to
determine what kind of scroll bar event occurred, as specified by the fields you see in Table 8.13.
266
Immediate Solutions
Lets look at an example. Here, well just add two scroll bars to a program and change the applets background
color when the user adjusts the scroll bars. When you construct a scroll bar, you can specify its orientation
(horizontal or vertical), its initial value, a page size, and its numeric range. The page size indicates how big you
want the thumb to be (it is customary to let the size of the thumb give an indication of the total rangeyou use a
smaller thumb for a longer range and a larger thumb for a shorter range, as you see in word processors when
they work with documents of varying sizes). Heres how we add a scroll bar to a program, giving it a horizontal
orientation, an initial value of 1, a page size of 20, and a range from 1 to 150:
import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
/* <APPLET
CODE=ScrollbarDemo.class
WIDTH=400
HEIGHT=100 >
</APPLET> */
public class ScrollbarDemo extends Applet implements AdjustmentListener {
Scrollbar scroll1, scroll2;
Note that we also add an AdjustmentListener interface to this new scroll bar.
267
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
You might think that this scroll bar can return any value in the range of 1 to 150; but in fact, the thumb must also be represented
in the track, so the scroll bar can only return values from 1 to 150 minus the page size (20, in this case), which equals 130.
Thats something to think about when you are creating scroll bars.
You can also configure the scroll bar by using the setUnitIncrement() and setBlockIncrement()
methods. The setUnitIncrement() method sets the amount the scroll bars setting changes when the user
clicks an arrow button (the default is 1), and the setBlockIncrement() method sets the amount the setting
changes when the user clicks the scroll bar track (the default is 10). The init() method looks like this:
public void init() {
scroll1 = new Scrollbar(Scrollbar.HORIZONTAL, 1, 20, 1, 150);
add(scroll1);
scroll1.addAdjustmentListener(this);
scroll2 = new Scrollbar(Scrollbar.VERTICAL, 1, 20, 1, 150);
add(scroll2);
scroll2.addAdjustmentListener(this);
}
All thats left is to update the background color when the user uses the scroll bars. We do that in the
adjustmentValueChanged() method, checking the AdjustmentEvent objects getAdjustable() method
to make sure we are dealing with one of the scroll bars and using that scroll bars getValue() method to
display the new settings in the text field. Heres how this looks in code:
public void adjustmentValueChanged(AdjustmentEvent e) {
if(e.getAdjustable() == scroll1 ||e.getAdjustable() == scroll2) {
setBackground(new Color(100,value1,value2));
showStatus("Horizontal: "+value1+" Vertical: "+value2);
}
}
}
The result appears in Figure 8.10.
268
Immediate Solutions
/* <APPLET
CODE=ScrollText.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
public class ScrollText extends Applet implements AdjustmentListener {
Scrollbar scroll1;
int x = 40;
int y = 40;
public void init() {
scroll1 = new Scrollbar(Scrollbar.HORIZONTAL, 1, 20, 20, 100);
add(scroll1);
scroll1.addAdjustmentListener(this); }
public void paint(Graphics g) {
g.drawString("Kogent", x, 80);
g.drawString("Learning",40, y);
}
. . .
}
When scroll events occur, well be notified in the adjustmentValueChanged() method, and we can set the
value in the variable x and y to reflect the new locations of the strings and redraw the applet (note that we are
using the Applet classs getSize() method here to determine the width of the applet and scale the motions of
the text strings accordingly):
public void adjustmentValueChanged(AdjustmentEvent e) {
if(e.getAdjustable() == scroll1) {
x = (int) (getSize().width * (float) scroll1.getValue() / 100);
y = (int) (getSize().width * (float) scroll1.getValue() / 100);
repaint(); }
}
The result appears in Figure 8.11. As you can see in this figure, the user can scroll the text strings around the
applet just by manipulating the horizontal scroll bar. Well take a closer look at scrolling text with scroll bars in
the next solution.
269
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
270
Immediate Solutions
if(e.getAdjustable() == horizontal2) {
horizontal1.setValue(horizontal2.getValue()); }
if(e.getAdjustable() == vertical2) {
vertical1.setValue(vertical2.getValue()); }
display.x = (int) (getSize().width * (float) horizontal1.getValue() / 200);
display.y = (int) (getSize().height * (float) vertical1.getValue() /150);
display.repaint();
}
And thats all it takes. The result appears in Figure 8.12. As you can see in this figure, the scroll bars appear
around the perimeter of the applet.
271
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
272
Immediate Solutions
Lets look at an example. It is easy enough to just add a component to a scroll pane; you simply use the
ScrollPane classs add() method. Heres how this looks when we add a text area to a scroll pane:
import java.applet.Applet;
import java.awt.*;
/* <APPLET
CODE=ScrollPaneDemo1.class
WIDTH=350
HEIGHT=200>
</APPLET> */
public class ScrollPaneDemo1 extends Applet {
ScrollPane scrollpane1;
TextArea area1;
public void init() {
scrollpane1 = new ScrollPane();
area1 = new TextArea(10,40);
scrollpane1.add(area1);
setLayout(new BorderLayout());
add(scrollpane1); }
}
273
Chapter 8: AWTLists, Choices, Text Areas, Scroll bars, and Scroll Panes
The result of ScrollPaneDemo1.java appears in Figure 8.14. As you can see in this figure, the user ends up
scrolling text around inside a scroll pane.
Summary
In this chapter, we provided you with a brief introduction on lists, choices, text areas, scrollbars, and scroll
panes. Then, you learned how to use the text areas, replace text in text areas, and search text in the text areas.
You also came to know about the use of lists, multiple selection lists, followed by the use of choice controls.
Toward the end, you studied about the scrollbars and scroll panes.
In the next chapter, we will discuss about AWT- graphics, images, text, and fonts.
274
Chapter 9: AWTGraphics, Images, Text, and Fonts
9
AWTGraphics,
Images, Text, and Fonts
If you need an immediate solution to: See page:
Using the Mouse 277
Using the Keyboard 279
Using Fonts 283
Using Images 289
Resizing Images 291
Drawing Graphics 292
Selecting Colors 300
Using Canvases 303
Using the ImageObserver Interface 305
Using the MediaTracker Class 306
Working Pixel by Pixel: The PixelGrabber and MemoryImageSource Classes 308
Brightening Images 311
Converting Images to Grayscale 312
Embossing Images 313
Chapter 9: AWTGraphics, Images, Text, and Fonts
In Depth
This chapter is all about some very powerful topics in Javagraphics, images, text handling, and working
with fonts. Java is a very visual language, and all these areas are popular with programmers. Well start with
an overview of these items.
Graphics
The graphics capability in AWT is pretty solid, and it is based on the huge Graphics class. You can use this
class to draw all kinds of figureslines, points, rectangles, ovals, polygons, and more. You can also select
colors and drawing modes as well as fill figures in with color. Youll see all this in this chapter, including a
special componentthe Canvas componentthat exists expressly, so you can draw in it.
Images
Images are the objects of Image class found in the java.awt package. Various classes have been provided in
the java.awt.image package to implement images. Youll see various different capabilities of AWT in this
chapter, such as loading images in distinct image formats, resizing images, waiting until images get loaded
completely, drawing images offscreen before displaying (known as double buffering), and animating images.
In fact, you can even gain access to the individual pixels in imagescopying images, brightening them,
converting them to grayscale, and giving them an engraved appearance.
Youll learn all about animating images and double buffering when we discuss multithreading in Chapter 19.
276
In Depth
Immediate Solutions
Using the Mouse
OK, says the Novice Programmer, in my program, the user can select text with Ctrl+Alt+F8, move the
insertion point with Shift+Alt+F3, and. . . Wait a minute, you say. Have you ever thought about adding mouse
support to your program? It might make things easier for the user. Hmm, says the NP thoughtfully. You can
work with the mouse using two AWT interfacesMouseListener, which handles mouse clicks, presses, and
releases as well as instances when the mouse enters a component and then leaves it, and
MouseMotionListener, which handles mouse movements and drag operations. You can find the methods of
the MouseListener interface in Table 9.1 and the methods of the MouseMotionListener interface in Table 9.2.
Bear in mind that you need to override all the methods in an interface if you want to implement that interface, which can get a
little tedious in the case of MouseListener, which has five methods. To make things easier, you can use adapter classes such
as MouseAdapter instead and just override the methods you want to use. For more on adapter classes, see Chapter 6.
Each of the mouse interface methods is passed an object of class MouseEvent, and the inheritance diagram for
that class looks like this:
java.lang.Object
|____java.util.EventObject
|____java.awt.AWTEvent
|____java.awt.event.ComponentEvent
|____java.awt.event.InputEvent
|____java.awt.event.MouseEvent
You can find the constructors of the MouseEvent class in Table 9.3.
Table 9.3: Constructors of the MouseEvent class
Constructor Does this
MouseEvent(Component source, int It constructs a MouseEvent object with the indicated source component,
id, long when, int modifiers, int type, modifiers, coordinates, click count, and popupTrigger flag
x, int y, int clickCount, boolean
popupTrigger )
MouseEvent(Component source, int It constructs a MouseEvent object with the indicated source component,
id, long when, int modifiers, int type, time, modifiers, coordinates, click count, popupTrigger flag, and
x, int y, int clickCount, boolean button number
popupTrigger, int button)
277
Chapter 9: AWTGraphics, Images, Text, and Fonts
The MouseEvent class adds only fields to its base classes, and you can find the fields of this class in Table 9.4.
Table 9.4: Fields of the MouseEvent class
Field Does this
static int BUTTON1 It indicates mouse button#1; used by getButton()
static int BUTTON2 It indicates mouse button#2; used by getButton()
static int BUTTON3 It indicates mouse button#3; used by getButton()
static int MOUSE_CLICKED It indicates the mouse clicked event
static int MOUSE_DRAGGED It indicates the mouse dragged event
static int MOUSE_ENTERED It indicates the mouse entered event
static int MOUSE_EXITED It indicates the mouse exited event
static int MOUSE_FIRST It indicates the first number in the range of IDs used for mouse events
static int MOUSE_LAST It indicates the last number in the range of IDs used for mouse events
static int MOUSE_MOVED It indicates the mouse moved event
static int MOUSE_PRESSED It indicates the mouse pressed event
static int MOUSE_RELEASED It indicates the mouse released event
static int MOUSE_WHEEL It indicates the mouse wheel event
static int NOBUTTON It indicates no mouse buttons; used by getButton()
Lets look at an example. This applet, called MousePlay.java, will display most of what the mouse can do. To
catch particular mouse actions, you just override the corresponding mouse listener method. To get the current
location of the mouse from a MouseEvent object, you can use the getX() and getY() methods. To determine
which button was pressed, you can use the MouseEvent classs getModifiers() method and then And the
result with these fields from the InputEvent class: ALT_GRAPH_MASK, ALT_MASK, BUTTON1_MASK,
BUTTON2_MASK, BUTTON3_MASK, CTRL_MASK, META_MASK, and SHIFT_MASK. Heres what this applet
looks like, with all this work put together:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=MousePlay.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
class ShapePanel extends Panel implements MouseListener,MouseMotionListener{
MousePlay play;
ShapePanel(MousePlay mp){
play=mp;
}
public void mousePressed(MouseEvent e){
play.showStatus("Mouse Pressed");
}
public void mouseClicked(MouseEvent e) {
if((e.getModifiers() & InputEvent.BUTTON1_MASK) ==InputEvent.BUTTON1_MASK) {
play.showStatus("Left Mouse Button Clicked at "+e.getX()+","+e.getY());
278
Immediate Solutions
Note that there are three different key eventsKeyPressed, KeyReleased, and KeyTyped. You usually use
the KeyTyped event when working with the keyboard, because you can use the getKeyChar() method in
279
Chapter 9: AWTGraphics, Images, Text, and Fonts
KeyTyped to get the Unicode character that was typed. In the keyPressed() and keyReleased() methods,
on the other hand, you can use the getKeyCode() (not getKeyChar()) method to get a virtual key code; this
code just tells you what key was pressed or released you are responsible for determining whether the Shift,
Ctrl, or other key was pressed down, which you can do with the KeyEvent object passed to the key event
methods. To determine which modifier keys (such as Shift) were pressed down, you can use the KeyEvent
objects getModifiers() method and then And the result with the following fields from the InputEvent
class: ALT_GRAPH_MASK, ALT_MASK, CTRL_MASK, META_MASK, and SHIFT_MASK.
In general, its not very easy to work with virtual key codes because theres a separate constant you have to use
for each key as returned by getKeyCode()for example, VK_F1 for the F1 key, VK_A for the character A,
VK_5 for the number 5, and so on, as enumerated in the fields of the KeyEvent class, which you can see in
Table 9.6. You can also find the constructors for the KeyEvent class in Table 9.7 and its methods in Table 9.8.
Heres the inheritance diagram for the KeyEvent class:
java.lang.Object
|____java.util.EventObject
|____java.awt.AWTEvent
|____java.awt.event.ComponentEvent
|____java.awt.event.InputEvent
|____java.awt.event.KeyEvent
280
Immediate Solutions
281
Chapter 9: AWTGraphics, Images, Text, and Fonts
Lets look at an example. This simple applet contains two text fields: one in which the user enters the text and the
second simultaneously displays the entered text. Here, the KeyEvent is trapped, and the applet uses the
getKeyChar() method to actually read the keys typed. Every time the user types a key, the corresponding
character is added to the end of the displayed string. Heres what the applet looks like:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/* <APPLET
CODE=KeyboardPlay.class
WIDTH=300
HEIGHT=200>
</APPLET> */
public class KeyboardPlay extends Applet implements KeyListener {
TextField text1,text2;
public void init() {
text1 = new TextField(20);
add(text1);
text2 = new TextField(20);
add(text2);
text1.addKeyListener(this);
}
public void keyTyped(KeyEvent e) {
String text = text2.getText();
text = text + e.getKeyChar();
text2.setText(text); }
public void keyPressed(KeyEvent e) { }
public void keyReleased(KeyEvent e) { }
}
The result of this code appears in Figure 9.2. As you can see in the figure, the user can type text in one text field
and it gets displayed in the other.
282
Immediate Solutions
Using Fonts
The banner you created for the Company Pride Picnic was good, the Big Boss says, but it didnt seem to be
bursting with pride. Why not? you ask. Well for one thing, the BB says, it was only a quarter of an inch
tall. Hmm, you say, guess I better use a bigger font.
The Font class allows you to select a font style, such as Arial, Courier, or Roman, set font size, and specify if its
bold, italic, and so on. Youll find the fields of the Font class in Table 9.9, its constructors in Table 9.10, and its
methods in Table 9.11.
Table 9.9: Fields of the Font class
Field Does this
static int BOLD The bold style
static int CENTER_BASELINE The baseline used in ideographic scripts (such as Japanese)
static String DIALOG A String constant for the canonical family name of the logical font Dialog
static String DIALOG_INPUT A String constant for the canonical family name of the logical font
DialogInput
static int HANGING_BASELINE The baseline used when laying text using scripts, such as Devanagari
static int ITALIC The italicized style
static int LAYOUT_LEFT_TO_RIGHT A flag to layoutGlyphVector indicating that the text is left to right as
determined by the Bidi analysis
static int LAYOUT_NO_LIMIT_CONTEXT A flag to layoutGlyphVector indicating that the text in the char array after
the indicated limit should not be examined
static int LAYOUT_NO_START_CONTEXT A flag to layoutGlyphVector indicating that the text in the char array before
the indicated limit should not be examined
static int LAYOUT_RIGHT_TO_LEFT A flag to layoutGlyphVector indicating that the text is right to left as
determined by the Bidi analysis
static int MONOSPACED A String constant for the canonical family name of logical font
Monospaced
protected String name The logical name of this Font
static int PLAIN The plain style
protected float pointSize The point size of this Font in float
static int ROMAN_BASELINE The baseline used in most roman scripts when laying out text
static String SANS_SERIF A String constant for the canonical family name of logical font SansSerif
static String SERIF A String constant for the canonical family name of logical font Serif
protected int size The point size of this Font, rounded to integer
protected int style The style of this Font
static int TRUETYPE_FONT Identify a font resource of type TRUETYPE
static int TYPE1_FONT Identify a font resource of type TYPE1
283
Chapter 9: AWTGraphics, Images, Text, and Fonts
284
Immediate Solutions
285
Chapter 9: AWTGraphics, Images, Text, and Fonts
As if all the methods in Table 9.11 werent enough, therere two another important classes the LayoutPath
class and FontMetrics class. The LayoutPath classs constructor appears in Table 9.12, its methods in
Table 9.13. Heres the inheritance diagram for the LayoutPath class:
java.lang.Object
|____java.awt.font.LayoutPath
The LayoutPath class extends Object. It is used for getting a mapping between locations that are relative to
the baseline and points in the space of user. Along the baseline, an advance of location is coneprised, and an
offset is perpendicular to the baseline at the advance. Locations are represented as a Point2D, where x is the
advance and y is the offset.
Table 9.12: The Constructors of the LayoutPath class
Constructor Does this
LayoutPath() It constructs a new LayoutPath
The FontMetrics class tells you about the physical dimensions of fonts. The FontMetrics classs field
appears in Table 9.14, its constructor in Table 9.15, and its methods in Table 9.16. Typically, you use the
FontMetrics class to determine the height of text while displaying multiline text. Its worthwhile going
through the tables in this solution to see whats available when working with fonts.
Table 9.14: The field of the FontMetrics class
Field Does this
protected Font font It determines the font from which the font metrics are created
286
Immediate Solutions
287
Chapter 9: AWTGraphics, Images, Text, and Fonts
Lets look at an example. In this case, well let the user type characters and display them in Courier font,
centered in the applet, by determining the screen size of the text using the FontMetrics classs
stringWidth() and getHeight() methods, and the width and height of the applet with the applets
getSize() method. Well also let the user specify the size of the text, as well as whether it should be in italics
or bold, and set a Font object accordingly. To actually install the font so that when you print text it appears in
that font, you use a Graphics objects setFont() method. Heres what the applet looks like:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/* <APPLET
CODE=FontDemo.class
WIDTH=600
HEIGHT=200>
</APPLET> */
public class FontDemo extends Applet implements ActionListener, KeyListener {
String text = "";
Button boldbutton, italicbutton, largebutton;
boolean bold = false;
boolean italic = false;
boolean large = false;
public void init() {
boldbutton = new Button("Bold");
italicbutton = new Button("Italic");
largebutton = new Button("Large");
boldbutton.addActionListener(this);
italicbutton.addActionListener(this);
largebutton.addActionListener(this);
add(boldbutton);
add(italicbutton);
add(largebutton);
addKeyListener(this);
requestFocus(); }
public void actionPerformed(ActionEvent event) {
if(event.getSource() == boldbutton) bold = !bold;
if(event.getSource() == italicbutton) italic = !italic;
if(event.getSource() == largebutton) large = !large;
requestFocus();
repaint(); }
public void paint(Graphics g) {
String fontname = "Courier";
int type = Font.PLAIN;
int size = 36;
Font font;
FontMetrics metrics;
if(bold) type = type | Font.BOLD;
if(italic) type = type | Font.ITALIC;
if(large) size = 72;
font = new Font(fontname, type, size);
g.setFont(font);
metrics = getFontMetrics(font);
int xloc = (getSize().width - metrics.stringWidth(text)) / 2;
int yloc = (getSize().height + metrics.getHeight()) / 2;
288
Immediate Solutions
Using Images
The Big Boss says, About this photo essay you wrote for the company newspaper.... Yes? you ask. Where
are the photos? the BB asks. Hmm, you say, this looks like a job for the Image class. You can support
images in AWT with the Image class, which is derived directly from java.lang.Object:
java.lang.Object
|____java.awt.Image
Images are manipulated using the classes found in the java.awt.image package. Youll find the fields of the
Image class in Table 9.17, its constructor in Table 9.18, and its methods in Table 9.19.
Table 9.17: Fields of the Image class
Field Does this
protected float The priority for accelerating this image
accelerationPriority
static int SCALE_AREA_AVERAGING Use the Area Averaging image-scaling algorithm
static int SCALE_DEFAULT Use the default image-scaling algorithm
static int SCALE_FAST Choose an image-scaling algorithm that gives higher priority to scaling
speed than smoothness
static int SCALE_REPLICATE Use the image-scaling algorithm in the ReplicateScaleFilter class
static int SCALE_SMOOTH Choose an image-scaling algorithm that gives higher priority to scaling
speed than smoothness
static Object UndefinedProperty The UndefinedProperty object should be returned whenever a property
that was not defined for a particular image is requested
289
Chapter 9: AWTGraphics, Images, Text, and Fonts
To create an image object, you can use the createImage() method like this:
Image createImage(int width, int height)
Suppose you want to create an instance of Img and then call the createImage() method to actually make an
Image object. This would look like this:
Img m = new Img();
Image test = m.createImage(200, 100);
At this point, the image is blank. To load an image into an applet, you can use the Applet classs getImage()
method:
Image getImage(URL url)
Image getImage(URL url, String name)
Here, you can specify the URL of the image file you want to read using the URL class. You can create a URL
object using the URL classs constructor, like this:
URL("http://www.oracle.com")
Youll learn more about this in the coming chapters. As far as this chapter is concerned, however, well use the
Applet classs getCodeBase() and getDocumentBase() methods to get the URL for the applet itself and
use that as the same location to find the image file.
Heres a short example that just reads in an image, Java8.jpg, and displays it. To read in the image, we use the
getImage() method. To draw the image, we use the Graphics classs drawImage() method. For a lot more
on the Graphics class, see the solution Drawing Graphics, later in this chapter. Heres the form of
drawImage() well use here, which lets you specify the image object to draw and position it in the applet:
boolean drawImage(Image img, int x, int y, ImageObserver observer)
Note that you have to pass an object that implements the ImageObserver interface to drawImage().
ImageObserver objects let you monitor the progress of image-loading operations, and well take a look at them
later in this chapter. Theres a default implementation of this interface in the Applet class, so we just use the
this keyword as the ImageObserver object:
import java.awt.*;
import java.applet.*;
/* <APPLET
CODE=ImageDemo.class
WIDTH=350
HEIGHT=300>
</APPLET> */
290
Immediate Solutions
Resizing Images
The Novice Programmer is working on a graphics program and needs your help. I want to let the user resize
images, the NP says. How the heck does that work? No problem, you say, you just specify the new height
and width of the image in the drawImage() method.
To resize an image, you can use this overloaded version of the Graphics classs drawImage() method, which
lets you specify an images width and height:
drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer)
The ImageObserver object allows you to monitor an image while it loads. Using this object you can perform
other actions, such as show a progress indicator to inform you of the download progress. This kind of
notification helps very much when an image is being loaded over the network.
Heres an example where you just need to press the mouse at one point and release it at another; the applet will
draw the image you saw in the previous solution, resize it to fit the rectangle you have defined:
import java.awt.*;
import java.lang.Math;
import java.awt.event.*;
import java.applet.Applet;
/* <APPLET
CODE=ResizeImageDemo.class
WIDTH=300
HEIGHT=300 >
</APPLET> */
public class ResizeImageDemo extends Applet implements MouseListener {
Image img;
boolean mouseUp = false;
Point start, end;
public void init() {
291
Chapter 9: AWTGraphics, Images, Text, and Fonts
Drawing Graphics
The Big Boss appears in a puff of cigar smoke and says, The design team has come up with a winner program
that I want you to write. What does it do? you ask. It lets the user draw lines, rectangles, and ovals as well as
freehand with the mouse, the BB says. Real cutting-edge stuff, you reply. The real core of AWT graphics is the
huge AWT Graphics class, which is derived directly from java.lang.Object.
Youll find the constructor of this class in Table 9.20 and its methods in Table 9.21.
Table 9.20: The constructor of the Graphics class
Constructor Does this
protected Graphics() It creates a new Graphics object
292
Immediate Solutions
293
Chapter 9: AWTGraphics, Images, Text, and Fonts
294
Immediate Solutions
We are going to put the Graphics class to work here by creating the program the Big Boss wanteda graphics
program that lets the user draw lines, ovals, rectangles, rounded rectangles, and freehand with the mouse, as
shown in Figure 9.6.
The user first picks the color of drawing out of red, gray, or orange by clicking the Red, Gray or Orange buttons.
If no color button is clicked, the drawing takes place in black color. Next, the user clicks a button indicating what
kind of figure he/she wants to draw, which sets a Boolean flag inside the program. When the user presses the
mouse in the drawing area, that location is stored as start, using a Java Point object (which has two data
members: x and y). When the user releases the mouse in a new location, that location is stored as end. Releasing
the mouse also repaints the program, and the user can select what figure to drawa line, oval, rectangle, or
rounded rectanglebetween start and end based on the Boolean flags set by clicking the buttons.
295
Chapter 9: AWTGraphics, Images, Text, and Fonts
java looks like (well take a look at the drawing sections in detail in the following pages):
import java.awt.*;
import java.lang.Math;
import java.awt.event.*;
import java.awt.Graphics;
import java.applet.Applet;
/* <APPLET
CODE=DrawingGraphicsDemo.class
WIDTH=500
HEIGHT=200 >
</APPLET> */
public class DrawingGraphicsDemo extends Applet implements ActionListener,
MouseListener,MouseMotionListener {
Button freeDraw, lineDraw, ovalDraw, rectDraw, roundedDraw;
Button button1, button2, button3;
String color="";
Point dot[] = new Point[1000];
Point start, end;
int dots = 0;
boolean mouseUp = false;
boolean draw = false;
boolean line = false;
boolean oval = false;
boolean rectangle = false;
boolean rounded = false;
public void init() {
lineDraw = new Button("Draw lines");
ovalDraw = new Button("Draw ovals");
rectDraw = new Button("Draw rectangles");
roundedDraw = new Button("Draw rounded rects");
freeDraw = new Button("Draw freehand");
button1 = new Button("Red");
button2 = new Button("Gray");
button3 = new Button("Orange");
add(lineDraw);
add(ovalDraw);
add(rectDraw);
add(roundedDraw);
add(freeDraw);
add(button1);
add(button2);
add(button3);
lineDraw.addActionListener(this);
ovalDraw.addActionListener(this);
rectDraw.addActionListener(this);
roundedDraw.addActionListener(this);
freeDraw.addActionListener(this);
button1.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);
addMouseListener(this);
addMouseMotionListener(this); }
public void mousePressed(MouseEvent e) {
mouseUp = false;
start = new Point(e.getX(), e.getY()); }
public void mouseReleased(MouseEvent e) {
if(line) { end = new Point(e.getX(), e.getY()); }
else {
end = new Point(Math.max(e.getX(), start.x),
Math.max(e.getY(), start.y));
start = new Point(Math.min(e.getX(), start.x),
Math.min(e.getY(), start.y)); }
mouseUp = true;
repaint(); }
public void mouseDragged(MouseEvent e) {
296
Immediate Solutions
if(draw) {
dot[dots] = new Point(e.getX(), e.getY());
dots++;
repaint(); }
}
public void mouseClicked(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseMoved(MouseEvent e) { }
public void paint (Graphics g) {
if(color.equals("red"))g.setColor(Color.red);
if(color.equals("gray"))g.setColor(Color.gray);
if(color.equals("orange"))g.setColor(Color.orange);
if (mouseUp) {
int width = end.x - start.x;
int height = end.y - start.y;
if(line) {
g.drawLine(start.x, start.y, end.x, end.y); }
else if(oval) {
g.drawOval(start.x, start.y, width, height); }
else if(rectangle) {
g.drawRect(start.x, start.y, width, height); }
else if(rounded) {
g.drawRoundRect(start.x, start.y, width, height, 10, 10); }
else if(draw) {
for(int loop_index = 0; loop_index < dots - 1;loop_index++) {
g.drawLine(dot[loop_index].x, dot[loop_index].y,dot[loop_index + 1].x, dot[loop_index +
1].y); }
}
}
}
public void actionPerformed(ActionEvent e) {
setFlagsFalse();
if(e.getSource() == freeDraw)draw = true;
if(e.getSource() == lineDraw)line = true;
if(e.getSource() == ovalDraw)oval = true;
if(e.getSource() == rectDraw)rectangle = true;
if(e.getSource() == roundedDraw)rounded = true;
if(e.getSource() == button1)color="red";
if(e.getSource() == button2)color="gray";
if(e.getSource() == button3)color="orange";}
void setFlagsFalse() {
rounded = false;
line = false;
oval = false;
rectangle = false;
draw = false; }
}
Now that you know what DrawingGraphicsDemo.java looks like, lets take a look at some of its drawing
functions. All these drawing functions, except for the freehand drawing functions, draw a figure between the
locations start and end, which the user indicates by dragging the mouse.
Drawing Lines
Using a Graphics object, you can draw a line between the points (x1, y1) and (x2, y2) with the
drawLine() method:
drawLine(int x1, int y1, int x2, int y2);
Heres how that looks in DrawingGraphicsDemo.java:
g.drawLine(start.x, start.y, end.x, end.y);
You can see the result in DrawingGraphicsDemo.java in Figure 9.7.
297
Chapter 9: AWTGraphics, Images, Text, and Fonts
Drawing Ovals
Ellipses, including circles, are called ovals in AWT, and you can draw them with the Graphics classs
drawOval() method:
drawOval(int x, int y, int width, int height);
Heres how ovals are drawn, as specified by the user when running DrawingGraphicsDemo.java:
int width = end.x - start.x;
int height = end.y - start.y;
g.drawOval(start.x, start.y, width, height);
You can see the result in DrawingGraphicsDemo.java, as shown in Figure 9.8.
Drawing Rectangles
You can draw rectangles using the Graphics classs drawRect() method:
drawRect(int x, int y, int width, int height);
Heres how we do it in DrawingGraphicsDemo.java:
int width = end.x - start.x;
int height = end.y - start.y;
g.drawRect(start.x, start.y, width, height);
You can see the result in DrawingGraphicsDemo.java, as shown in Figure 9.9.
298
Immediate Solutions
Drawing Freehand
You can draw freehand with the mouse using the AWT Graphics class, but youll have to implement it
yourself in code. Heres how we do it in DrawingGraphicsDemo.java using the mouseDragged() method.
After checking to make sure the user is drawing freehand by making sure the draw flag is true, we save all the
mouse locations in an array named dot[] as the mouse is dragged:
public void mouseDragged(MouseEvent e) {
if(draw) {
dot[dots] = new Point(e.getX(), e.getY());
dots++;
repaint(); }
}
Then, when its time to draw the figure, we just connect the dots using lines, like this:
for(int loop_index = 0; loop_index < dots - 1; loop_index++) {
g.drawLine(dot[loop_index].x, dot[loop_index].y,
dot[loop_index + 1].x, dot[loop_index + 1].y);
}
You can see the result in Figure 9.6 (shown previously).
Drawing Arcs
You can use the Graphics classs drawArc() method to draw arcs (you specify angles in degrees):
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle);
Drawing Polygons
There are a number of ways to draw polygons and multiple-segment lines with AWT:
drawPolygon(int[] xPoints, int[] yPoints, int nPoints);
drawPolygon(Polygon p);
drawPolyline(int[] xPoints, int[] yPoints, int nPoints);
299
Chapter 9: AWTGraphics, Images, Text, and Fonts
Selecting Colors
My graphics work has been a little drab, says the Novice Programmer, because everythings appearing in one
colorblack. Well, you say, you can select the drawing color easily enough. No discussion of graphics
would be complete without discussing colors, and you handle colors in AWT with the Color class. Youll find
the fields of this class in Table 9.22, its constructors in Table 9.23, and its methods in Table 9.24.
Table 9.22: Fields of the Color class
static Color black static Color blue static Color cyan
static Color darkGray static Color gray static Color green
static Color lightGray static Color magenta static Color orange
static Color pink static Color red static Color white
static Color yellow static Color BLACK static Color BLUE
static Color CYAN static Color DARK_GRAY static Color GRAY
static Color GREEN static Color LIGHT_GRAY static Color MAGENTA
static Color ORANGE static Color PINK static Color RED
static Color WHITE static Color YELLOW
300
Immediate Solutions
For example, to create a new color, you can specify red, green, and blue values in the Color classs constructor,
which is shown as:
Color c = new Color(red, green, blue);
301
Chapter 9: AWTGraphics, Images, Text, and Fonts
Note that the color values are specified in the range 0 to 255. Now you are free to set this new color as the
drawing color by using setForeground():
setForeground(c);
You can also use predefined colors, such as Color.blue, Color.red, and Color.orange to set the
background color:
setBackground(Color.blue);
You can also fill figures with the color you have specified using Graphics methods, such as fillArc(),
fillOval(), and so on.
The following applet shows various colors and their usage.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
/* <APPLET
CODE=ColorsDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class ColorsDemo extends Applet implements MouseListener{
TextField text1;
Label label1, label2, label3, label4, label5, label6, label7, label8;
Panel panel1;
public void init()
{
text1 = new TextField();
panel1 = new Panel();
label1 = new Label();
label1.setBackground(Color.red);
label1.addMouseListener(this);
label2 = new Label();
label2.setBackground(Color.green);
label2.addMouseListener(this);
label3 = new Label();
label3.setBackground(Color.cyan);
label3.addMouseListener(this);
label4 = new Label();
label4.setBackground(Color.pink);
label4.addMouseListener(this);
label5 = new Label();
label5.setBackground(Color.yellow);
label5.addMouseListener(this);
label6 = new Label();
label6.setBackground(Color.magenta);
label6.addMouseListener(this);
label7 = new Label();
label7.setBackground(Color.orange);
label7.addMouseListener(this);
label8 = new Label();
label8.setBackground(Color.blue);
label8.addMouseListener(this);
panel1.setLayout(new GridLayout(1,8));
panel1.add(label1);
panel1.add(label2);
panel1.add(label3);
panel1.add(label4);
panel1.add(label5);
panel1.add(label6);
panel1.add(label7);
panel1.add(label8);
setLayout(new BorderLayout());
add(text1,BorderLayout.CENTER);
add(panel1,BorderLayout.NORTH);
}
302
Immediate Solutions
Using Canvases
The canvas component is specially built to support graphics operations. As the name suggests, canvases provide
you with a blank space for you to draw on, using the Graphics object passed to the paint() method. Heres
the inheritance diagram for the AWT Canvas class:
java.lang.Object
|____java.awt.Component
|____java.awt.Canvas
Youll find the constructors for this class in Table 9.25 and its methods in Table 9.26.
Table 9.25: Constructors of the Canvas class
Constructor Does this
Canvas() It creates a new canvas
Canvas It creates a new canvas given a GraphicsConfiguration object
(GraphicsConfiguration config)
303
Chapter 9: AWTGraphics, Images, Text, and Fonts
One common use for canvases is to support an elementary form of animation, because you can use the AWT
Component classs setLocation() method to move a canvas (or any other component) around. Heres an
applet that does just that when its clicked:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
/* <APPLET
CODE=CanvasDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class CanvasDemo extends Applet implements MouseListener {
DrawingCanvas dc;
Button button1;
public void init() {
dc = new DrawingCanvas();
dc.setSize(260,190);
add(dc);
dc.addMouseListener(this); }
public void mousePressed(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
for(int index = 0;index < 80;index++) {
dc.setLocation(index, 0); }
}
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
}
class DrawingCanvas extends Canvas {
public void paint (Graphics g) {
g.setColor(new Color(48,58,86));
g.fillRect(50,35,150,119);
g.setColor(new Color(178,98,83));
g.fillRect(80,60,90,70);
}
}
The result appears in Figure 9.12. When you click the the canvas, which displays a small figure, it moves to the
left and then sweeps to the right. Note that because a Graphics object is passed in a canvass paint() method,
you can use any Graphics method in a canvas.
304
Immediate Solutions
305
Chapter 9: AWTGraphics, Images, Text, and Fonts
If you use MediaTracker once and call the addImage() method on an image, its garbage collection will not take place due to the
reference in MediaTracker. Therefore, if you want the garbage collection of tracked images, ensure that the collector can collect
the MediaTracker instance as well.
Youll find the fields of the MediaTracker class in Table 9.27, its constructor in Table 9.28, and its methods in
Table 9.29.
Table 9.27: Fields of the MediaTracker class
Field Does this
static int ABORTED It indicates that the downloading of media was aborted
static int COMPLETE It indicates that the downloading of media was completed
static int ERRORED It indicates that the downloading of media encountered an error
static int LOADING It indicates media is currently being loaded
306
Immediate Solutions
Heres an example. In this case, we use the waitForAll() method to wait until an image is fully loaded (note
the try/catch statement, which is there to handle exceptions youll see this in more detail later in this book):
import java.awt.*;
import java.applet.*;
/* <APPLET
CODE=TrackMedia.class
WIDTH=300
HEIGHT=250 >
</APPLET> */
public class TrackMedia extends Applet {
Image image;
public void init() {
MediaTracker tracker = new MediaTracker(this);
image = getImage(getDocumentBase(), "Java8.jpg");
tracker.addImage(image, 0);
try { tracker.waitForAll(); }
catch (InterruptedException ex) { }
307
Chapter 9: AWTGraphics, Images, Text, and Fonts
}
public void paint(Graphics g) { g.drawImage(image, 20, 20, this); }
}
The results appear in Figure 9.14.
308
Immediate Solutions
To create an image from an array of pixels, you can use the MemoryImageSource class. The inheritance
diagram for this class looks like this:
java.lang.Object
|____java.awt.image.MemoryImageSource
Youll find the constructors for the MemoryImageSource class in Table 9.32 and the methods for this class in
Table 9.33.
Table 9.32: Constructors of the MemoryImageSource class
Constructor Does this
MemoryImageSource(int w, int h It creates an ImageProducer object that uses an array of bytes to produce
ColorModel cm, byte[] pix, int the data for an Image object
off, int scan)
MemoryImageSource(int w, int h, It creates an ImageProducer object that uses an array of bytes to produce
ColorModel cm, byte[] pix, int the data for an Image object
off, int scan, Hashtable<?,?>
props)
309
Chapter 9: AWTGraphics, Images, Text, and Fonts
void newPixels (int[] newpix, It changes to a new integer array to hold the pixels for this image
ColorModel newmodel, int offset,
int scansize)
void newPixels(int x, It sends a rectangular region of the buffer of pixels to ImageConsumer
int y, int w, int h) objects interested in data for this image and notify them of completion of an
animation frame
void newPixels(int x, int y, int It sends a rectangular region of the buffer of pixels to ImageConsumer
w, int h, boolean framenotify) objects interested in data for this image
void removeConsumer It removes an ImageConsumer object from the list of consumers interested
(ImageConsumer ic) in data for this image
void It requests that the image data be delivered one more time in top-down, left-
requestTopDownLeftRightResend(Ima right order
geConsumer ic)
void setAnimated It changes this memory image into a multiframe animation or a single-frame
(boolean animated) static image
void setFullBufferUpdates It indicates whether this animated memory image should always be updated
(boolean fullbuffers) by sending the complete buffer of pixels whenever there is a change
void startProduction It adds an ImageConsumer object to the list of consumers and starts
(ImageConsumer ic) delivery of the image data
Heres an example using the PixelGrabber and MemoryImageSource classes. In this case, we just read in an
image and copy it to a new image object. We do this by loading in the image we have used in the previous
examples in this chapter, which are 230 by 218 pixels. First, we load the image into img1 variable; place the
pixels in that image into an array named pixels using a PixelGrabber objects grabPixels() method; and
310
Immediate Solutions
then create a new image, img2, using a MemoryImageSource object and the Applet classs createImage()
method:
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
/* <APPLET
CODE=CopierDemo.class
WIDTH=300
HEIGHT=250 >
</APPLET> */
public class CopierDemo extends Applet {
Image img1, img2;
public void init() {
img1 = getImage(getDocumentBase(), "Java8.jpg");
int pixels[] = new int[230 * 218];
PixelGrabber grabber = new PixelGrabber(img1, 0, 0, 230, 218,pixels, 0, 230);
try { grabber.grabPixels(); }
catch (InterruptedException e) {}
img2 = createImage(new MemoryImageSource(230, 218, pixels, 0,230)); }
public void paint(Graphics g) { g.drawImage(img2, 10, 10, this); }
}
Thats all there is to itnow the image is copied into img2 and displayed. Now that we have access to the pixels
in the image, well do a few more things with the image, such as brightening it, as discussed in the next solution.
Brightening Images
You can brighten images just by increasing their red, green, and blue color values by the same amount. In the
following code, we add 80 to each color value:
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
/* <APPLET
CODE=BrightDemo.class
WIDTH=300
HEIGHT=250 >
</APPLET> */
public class BrightDemo extends Applet {
Image img1, img2;
public void init() {
img1 = getImage(getDocumentBase(), " Java8.jpg");
int pixels[] = new int[230 * 218];
PixelGrabber grabber = new PixelGrabber(img1, 0, 0, 230,218, pixels, 0, 230);
try { grabber.grabPixels(); }
catch (InterruptedException e) { }
for (int loop_index = 0; loop_index < 485 * 88; loop_index++) {
int p = pixels[loop_index];
int red = (0xff & (p >> 16)) + 80;
int green = (0xff & (p >> 8)) + 80;
int blue = (0xff & p) + 80;
if (red > 255) red = 255;
if (green > 255) green = 255;
if (blue > 255) blue = 255;
pixels[loop_index] = (0xff000000 | red << 16 | green << 8 |blue); }
img2 = createImage(new MemoryImageSource(230, 218, pixels, 0,230)); }
public void paint(Graphics g) { g.drawImage(img2, 10, 10, this); }
}
The result appears in Figure 9.15. Now we are really manipulating images in code.
311
Chapter 9: AWTGraphics, Images, Text, and Fonts
312
Immediate Solutions
Embossing Images
Embossing is a powerful effect in which images appear to be raised from the viewing surface; well take a look at
this effect here. Embossing images is most convenient when you work in terms of a two-dimensional array.
However, the PixelGrabber and MemoryImageSource classes only work with one-dimensional arrays, so
well simulate two-dimensional addressing by multiplying and adding array indexes in this example. Here, we
emboss the Java8.jpg image you saw in the previous solution:
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
/*<APPLET
CODE=EmbossDemo.class
WIDTH=300
HEIGHT=300 >
</APPLET> */
public class EmbossDemo extends Applet {
Image img1, img2;
public void init() {
img1 = getImage(getDocumentBase(), "Java8.jpg");
int pixels[] = new int[248 * 248];
PixelGrabber grabber = new PixelGrabber(img1, 0, 0, 248, 248,pixels, 0, 248);
try { grabber.grabPixels(); }
catch (InterruptedException e) { }
for (int x = 2; x < 247; x++) {
for (int y = 2; y < 247; y++) {
int red = ((pixels[(x + 1) * 248 + y + 1] & 0xFF) -(pixels[x * 248 + y] & 0xFF)) + 128;
int green = (((pixels[(x + 1) * 248 + y + 1] & 0xFF00) /0x100) % 0x100 - ((pixels[x *
248 + y] & 0xFF00) /0x100) % 0x100) + 128;
int blue = (((pixels[(x + 1) * 248 + y + 1] & 0xFF0000) / 0x10000) % 0x100 - ((pixels[x *
248 + y] & 0xFF0000) / 0x10000) % 0x100) + 128;
int average = (red + green + blue) / 3;
pixels[x * 248 + y] = (0xff000000 | average << 16 | average << 8 | average); } }
img2 = createImage(new MemoryImageSource(248, 248, pixels, 0,248));
}
public void paint(Graphics g) { g.drawImage(img2, 10, 10, this); }
}
313
Chapter 9: AWTGraphics, Images, Text, and Fonts
Summary
In this chapter, we introduced you to the concepts of graphics, images, texts, fonts, and input devices followed
by their usage. You learned how to draw the graphics (lines, rectangles, or arcs) and resize the images. Later, you
learned the use of ImageObserver interface and the MediaTracker class. Toward the end, the chapter
helped you to develop applications to brighten the images and convert them to grayscale with embossing of
those images.
The next chapter discusses about AWT- windows, menus, and dialog boxes.
314
10
AWTWindows, Menus,
and Dialog Boxes
If you need an immediate solution to: See page:
Creating Frame Windows 318
Showing and Hiding Windows 319
Handling Window Events 320
Automatically Hiding Windows upon Closing 323
Using the Window Class 323
Creating Menus 330
Creating a MenuBar Object 331
Creating Menu Objects 332
Creating MenuItem Objects 333
Handling Menu Events 335
More Menu Options 336
Adding Menu Separators 338
Disabling Menu Items 338
Adding Checkboxes to Menus 339
Creating Submenus 341
Pop-Up Menus 342
Dialog Boxes 344
File Dialog Boxes 348
315
Chapter 10: AWTWindows, Menus, and Dialog Boxes
In Depth
This chapter is all about taking the next step beyond creating controls in AWT programs. In this chapter, well
create and display AWT windows and see all that goes into the process, using the AWT Window and Frame
classes. Well also look at how to use the Dialog class to create dialog boxes and the FileDialog class to
create file dialog boxes for specifying a file. This is also where well take a look at menus, because in AWT
programming, you need a window before you can display menus. First, well take a brief look at all these items
in overview.
Windows
Windows, of course, are the foundation of GUI programming. Just about everything having to do with the user
interface in a graphical environment happens in a window, and every GUI user is familiar with windows. You
host the components that make up an applet or windowed application in windows, and there are three types of
windows available to AWT programmers. The first type of window is the applet window, where the Applet
class manages the window itself, and automatically creates and handles the window. You can also create frame
windows, which are what you normally think of as windows. A frame window supports a frame around a
window, a title bar, minimize, maximize, and close buttons. Well create one here using the Frame class.
When you launch a frame window from an applet, Java adds a warning sign on the top right side of the window for security
purposes. The message Java Applet Window appears as a tooltip when you bring the mouse pointer over
that sign.
Theres another window class you can usethe Window class. This class just presents a blank windowno title
bar, no frame, just a blank rectangle. You are responsible for displaying what you want in these windows. As
you might expect, the Frame class is derived from the Window class. Paradoxically, however, you cant create a
direct Window object in your own programs unless you already have a frame window, because the publicly
available Window constructor requires you to pass either a Frame window object or another Window object.
Menus
Every GUI user knows about menusthey are those indispensable controls that hide all the options a program
can present by category. Imagine if all the options a word processor could present were available as buttons,
visible all at once there would be no space to enter text. Menus let you store those options away in a compact
way. This is a very attractive GUI technique, because space is always at a premium in windowed environments.
In AWT programming, you need a frame window to use menus. You create a MenuBar object and add that
menu bar to a frame window with the windows setMenuBar() method. You also create objects of the Menu
class to create the individual menus (such as File, Edit, and so on) that appear in the menu bar, and you create
objects of the MenuItem class to create the actual items in each menu (such as New, Open, Help, Exit, and
so on).
You can also support some nice options in menussubmenus that open when you select a menu item and
checkboxes that let you toggle menu items on and off (such as Automatic Spell Checking and View Toolbar).
Well look at all this in the chapter.
Dialog Boxes
Windowed programs frequently use dialog boxes to get user input, such as the name of a file to open, a
password, or a color thats selected from many colors. Like the other visual elements in this chapter, dialog
boxes are familiar to nearly all GUI users. You use dialog boxes when you want to get user input but dont want
to display a dedicated control, such as a text field, at all times for that option in your main window. That is,
dialog boxes are temporary windows you can fill with controls for user input.
316
In Depth
Youll see two types of dialog boxes in this chapter, as supported by the Dialog and FileDialog classes. You
use the Dialog class as a base class for the dialog boxes you create and customize, as youll see here. On the
other hand, you dont usually need to derive a class from the FileDialog classthis class presents a file dialog
box, which the user can use to select a file. The methods and data members of this class are sufficient for most
file-selection purposes, and all you need to do is to instantiate an object of this class and use it. Youll see all this
in the chapter, too.
Thats it. Now you have an overview of whats in this chapter. Now, lets turn to the Immediate Solutions
section.
317
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Immediate Solutions
Creating Frame Windows
OK, says the Novice Programmer, Im working on my word processor in Java and want to present various
views of the documenteach view is a window into a different place in the document. What do you think?
You say, I think you should think about letting the user launch new frame windows.
You have already seen the Frame window class in this book, because you use that class as the foundation of
applications in AWT programming. Heres the inheritance diagram for Frame class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____java.awt.Window
|____java.awt.Frame
You can see the constructors and methods of this class in Chapter 6, in Tables 6.4 and 6.5 respectively. Well
create a frame window over the next few solutions, showing and hiding it as needed, giving it a size, adding
controls to it, and handling events in it. To start, well create a new class, FrameDemo, based on the Frame
class, and well display a label with the text Kogent Learning Solutions First, we declare this new class by
extending the Frame class:
import java.awt.*;
class FrameDemo extends Frame { . . . }
Next, we create a constructor for the class. We are going to use the Frame class constructor, which takes a title
for the window. Therefore, we add a title parameter to the constructor and pass that back to the Frame class,
like this:
import java.awt.*;
class FrameDemo extends Frame {
FrameDemo(String title) {
super(title);
. . . }
}
Heres an important point: The default layout manager in frame windows is the BorderLayout manager
(unlike applet windows, which use the FlowLayout manager). Note that this applies for both frame windows
you display from applets and frame windows you use in windowed applications. If you want to use a different
layout manager, you have to set it yourself. In this case, we install a flow layout manager by using the
setLayout() method, like this:
import java.awt.*;
class FrameDemo extends Frame {
FrameDemo(String title) {
super(title);
setLayout(new FlowLayout());
. . . }
}
Now we are ready to create a label and add it to the layout:
import java.awt.*;
class FrameDemo extends Frame {
Label label1;
FrameDemo(String title) {
super(title);
setLayout(new FlowLayout());
label1 = new Label("Kogent Learning Solutions!");
add(label1); }
}
That completes the Frame window classthe next step is to display it. See the following solution for details.
318
Immediate Solutions
319
Chapter 10: AWTWindows, Menus, and Dialog Boxes
The new window object is ready to go. To display the window, we can use the setVisible() method. We pass
it a value True to display the window and False to hide the window. Heres what this looks like for the two
buttons in this applet:
public void actionPerformed(ActionEvent event) {
String text = text1.getText();
if(text.equalsIgnoreCase("show")){ frame.setVisible(true); }
else if(text.equalsIgnoreCase("hide")){ frame.setVisible(false); }
else text1.setText("Please enter either show or hide to show/hide frame");
}
Thats all thats needed. Now the applet is ready to go, as you can see in Figure 10.1. When you enter show in
the text field, the frame window appears, with warning sign on the top right side of the window (which is not
visible when you use a frame window in an application), as you can see in the figure. When you type hide in
the text field and press the Enter key, the window disappears from the screen.
320
Immediate Solutions
321
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Note that you can also use the WindowAdapter class to handle window events; this class already implements
all the methods of the WindowListener interface, and you just override the methods you want to use. The
methods of the WindowListener interface and WindowAdapter class are passed an object of the
WindowEvent class. Youll find the fields of this class in Table 10.2, its constructor in Table 10.3, and its methods
in Table 10.4.
Table 10.2: Fields of the WindowEvent class
Field Does this
static int WINDOW_ACTIVATED Window activated event
static int WINDOW_CLOSED Window closed event
static int WINDOW_CLOSING Window closing event
static int WINDOW_DEACTIVATED Window deactivated event
static int WINDOW_DEICONIFIED Window deiconified event
static int WINDOW_FIRST The first number in the range of IDs used for window events
static int WINDOW_GAINED_FOCUS Window getfocus event
static int WINDOW_ICONIFIED Window iconified event
static int WINDOW_LAST The last number in the range of IDs used for window events
static int WINDOW_LOST_FOCUS Window lostfocus event
static int WINDOW_OPENED Window opened event
static int WINDOW_STATE_CHANGED Window statechange event
We put one of the WindowListener interface methods to workthe windowClosing eventin the next
solution.
322
Immediate Solutions
323
Chapter 10: AWTWindows, Menus, and Dialog Boxes
324
Immediate Solutions
325
Chapter 10: AWTWindows, Menus, and Dialog Boxes
326
Immediate Solutions
Lets look at an example. In this case, we create a new window class named WindowDemo that displays a label
with the text Kogent Learning Solutions! we start by declaring this new class:
class WindowDemo extends Window { . . . }
We have to pass the Window classs constructor a Frame window object or another Window object. To make
things simpler, we use this new window in an application, so well pass the main Frame window object to the
WindowDemo classs constructor and then pass that object back to the Window classs constructor, like this:
class WindowDemo extends Window {
Label label1;
WindowDemo(ShowHideWindow shw) {
super(shw);
. . . }
}
As is the case with frame windows, the default layout manager here is a border layout manager, so well set a
flow layout and display the label with its message, Kogent Learning Solutions!, in the window:
class WindowDemo extends Window {
Label label1;
WindowDemo(ShowHideWindow shw) {
super(shw);
setLayout(new FlowLayout());
label1 = new Label("Kogent Learning Solutions!");
add(label1); }
. . .
}
Windows of the Window class are simply blank white spaces, so well also override the paint() method of this
window to add a very simple framejust a rectangle like this (note that we can determine the dimensions of
the window with the getSize() method, the same as with applets):
class WindowDemo extends Window {
Label label1;
WindowDemo(ShowHideWindow shw) {
super(shw);
setLayout(new FlowLayout());
label1 = new Label("Kogent Learning Solutions!");
add(label1); }
public void paint(Graphics g) {
int width = getSize().width;
int height = getSize().height;
g.drawRect(0, 0, --width, --height); }
}
That completes the WindowDemo class. Well put this class to work in an application now. In this case, well just
instantiate an object of the class and set its size this is required before the window can be displayed. Well also
set its screen location using setLocation() method, because theres currently no way for the user to move
this window when it appears; and if we just show it with the setVisible() method, itll appear at (0, 0) on the
screen, which is at the extreme upper-left corner. When the user enters show in the text field, the window
appears, and when the user enters hide, the window gets disappeared. Heres the code:
import java.awt.*;
import java.awt.event.*;
public class ShowHideWindow extends Frame implements ActionListener{
TextField text1;
WindowDemo window;
ShowHideWindow(){
text1 = new TextField(30);
text1.addActionListener(this);
add(text1);
window = new WindowDemo(this);
window.setSize(300, 200);
window.setLocation(300, 300);
setSize(300,200);
327
Chapter 10: AWTWindows, Menus, and Dialog Boxes
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(text1.getText().equalsIgnoreCase("show"))window.setVisible(true);
if(text1.getText().equalsIgnoreCase("hide"))window.setVisible(false); }
public static void main(String args[]){ new ShowHideWindow(); }
}
class WindowDemo extends Window {
Label label1;
WindowDemo(ShowHideWindow shw) {
super(shw);
setLayout(new FlowLayout());
label1 = new Label("Kogent Learning Solutions!");
add(label1); }
public void paint (Graphics g) {
int width = getSize().width;
int height = getSize().height;
g.drawRect(0, 0, --width, --height); }
}
You can see the result in Figure 10.3. As you can see in this figure, the window appears with its minimal border
and the label control, which displays a message.
328
Immediate Solutions
329
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Creating Menus
OK, says the Novice Programmer, I have been waiting to ask you this one. Oh boy, you say. The NP asks,
How do I create menus? You sit back and say, Better get some coffee.
You can add AWT menus to Frame class windows using three AWT classes: MenuBar, Menu, and MenuItem.
We list the details for these classes here. The first class you use is the MenuBar class, which adds a menu bar to a
frame window. After you have added a menu bar to a frame window, you can add menus, such as a File menu
and an Edit menu, to that menu bar using the Menu class. Finally, you add menu items to the menus in your
program using the MenuItem class.
Well create and use menus over the next few solutions while developing an applet named MenuDemo.java,.
This applet will display a frame window with a menu in it. Heres the applet:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/* <APPLET
CODE=MenuDemo.class
WIDTH=300
HEIGHT=200>
</APPLET> */
public class MenuDemo extends Applet implements ActionListener{
TextField text1;
MenuFrame frame;
public void init() {
text1 = new TextField(30);
add(text1);
text1.addActionListener(this);
frame = new MenuFrame("Menu Frame");
frame.setSize(300,200); }
public void actionPerformed(ActionEvent event) {
String text = text1.getText();
if(text.equalsIgnoreCase("show")){ frame.setVisible(true); }
else if(text.equalsIgnoreCase("hide")){ frame.setVisible(false); }
else text1.setText("Please enter either show or hide");}
}
class MenuFrame extends Frame implements ActionListener {
Menu menu1;
MenuBar menubar1;
MenuItem item1, item2, item3;
Label label1;
MenuFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
menu1.add(item1);
item1.addActionListener(this);
item2 = new MenuItem("Burger");
menu1.add(item2);
item2.addActionListener(this);
item3 = new MenuItem("Idli");
menu1.add(item3);
item3.addActionListener(this);
menubar1.add(menu1);
setMenuBar(menubar1);
}
330
Immediate Solutions
331
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Heres how we create a menu bar in the frame window of the MenuDemo.java applet introduced in the
Creating Menus solution (note that we install the menu bar in the frame window with the Frame classs
setMenuBar() method):
class MenuFrame extends Frame implements ActionListener {
MenuBar menubar1;
Label label1;
MenuFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
. . .
setMenuBar(menubar1); }
}
All this does, however, is display a blank menu barits time to add some menus to the menu bar. See the next
solution for details.
You can find the process of Creating a Menu Bar in detail in Chapter 16.
332
Immediate Solutions
Heres how we created a Food Items menu in the MenuDemo.java applet and added that menu to the menu
bar (note that we name the menu simply by passing the name to the Menu classs constructor):
class MenuFrame extends Frame implements ActionListener {
Menu menu1;
MenuBar menubar1;
Label label1;
MenuFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
. . .
menubar1.add(menu1);
setMenuBar(menubar1); }
}
One powerful way of creating menus is as tear-off menus, which you do by using the third form of the Menu constructor in Table
10.9. Users can tear off these menus with the mouse and place them where they like.
You can find the process of Creating a Menu in detail in Chapter 16.
333
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Youll find the constructors for the MenuItem class in Table 10.11 and its methods in Table 10.12.
Table 10.11: Constructors of the MenuItem class
Constructor Does this
MenuItem() It creates a new menu item without any label or keyboard shortcut
MenuItem(String label) It creates a new menu item with the given label and no keyboard shortcut
MenuItem(String label, It creates a menu item with an associated keyboard shortcut
MenuShortcut s)
334
Immediate Solutions
To add a menu item to a menu, you just create a new MenuItem object, pass the name of new item to the
MenuItem constructor, and then use the Menu objects add() method to add the new item to a menu. Heres an
example in which we added items to the Food Items menu in the MenuDemo.java applet:
class MenuFrame extends Frame implements ActionListener {
Menu menu1;
MenuBar menubar1;
MenuItem item1, item2, item3;
Label label1;
MenuFrame(String title) {
super(title);
label1 = new Label("Hello Java!");
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
menu1.add(item1);
item2 = new MenuItem("Burger");
menu1.add(item2);
item3 = new MenuItem("Idli");
menu1.add(item3);
menubar1.add(menu1);
setMenuBar(menubar1); }
}
Java menu items support shortcuts, which you can create by using the third form of the MenuItem constructor in Table 10.11.
Users can access menu items with shortcuts using the keyboard.
This is all fine as far as it goes, except that nothing happens when these menu items are clicked. To learn how to
support menu events, see the next solution.
You can find the process of Creating a Menu Item in detail in Chapter 16.
335
Chapter 10: AWTWindows, Menus, and Dialog Boxes
menu1.add(item3);
item3.addActionListener(this);
menubar1.add(menu1);
setMenuBar(menubar1);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
label1.setText("You ordered Pizza"); }
else if(e.getSource() == item2) {
label1.setText("You selected Burger"); }
else if(e.getSource() == item3) {
label1.setText("You selected Idli"); }
}
}
Thats it. Now the user can run the MenuDemo.java applet and report on the items he/she selected, as shown
in Figure 10.5. Its worth noting that although we used the ActionEvent classs getSource() method to
determine which menu item was clicked in this solution, you can also give each menu item an action command
with the setActionCommand() method as we did for buttons in Chapter 7and use the ActionEvent
classs getActionCommand() method to read the action command.
336
Immediate Solutions
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
item1.addActionListener(this);
menu1.add(item1);
item2 = new MenuItem("Burger");
item2.addActionListener(this);
menu1.add(item2);
menu1.addSeparator();
item3 = new CheckboxMenuItem("Idli");
item3.addItemListener(this);
menu1.add(item3);
menu1.addSeparator();
submenu1 = new Menu("Cold Drinks");
subitem1 = new MenuItem("Pepsi");
subitem2 = new MenuItem("Limca");
subitem3 = new MenuItem("Coke");
subitem1.addActionListener(this);
subitem2.addActionListener(this);
subitem3.addActionListener(this);
item2.addActionListener(this);
item2.addActionListener(this);
submenu1.add(subitem1);
submenu1.add(subitem2);
submenu1.add(subitem3);
menu1.add(submenu1);
menu1.addSeparator();
item4 = new MenuItem("Exit");
item4.addActionListener(this);
menu1.add(item4);
menubar1.add(menu1);
setMenuBar(menubar1);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
label1.setText("You ordered Pizza"); }
else if(e.getSource() == item2) {
item2.setEnabled(false);
label1.setText("You ordered Burger"); }
else if(e.getSource() == subitem1) {
label1.setText("You ordered Pepsi"); }
else if(e.getSource() == subitem2) {
label1.setText("You ordered Limca"); }
else if(e.getSource() == subitem3) {
label1.setText("You ordered Coke"); }
else if(e.getSource() == item4) {
setVisible(false); }
}
public void itemStateChanged (ItemEvent e) {
if(e.getSource() == item3) {
if(((CheckboxMenuItem)e.getItemSelectable()).getState())
label1.setText("You ordered Idli");
else { label1.setText("Idli not ordered"); }
}
}
}
You can see this applet in Figure 10.6. Well develop the various new aspects of this applet,
AdvancedMenu.java, over the next few solutions, as youll see how to handle its various parts in code.
337
Chapter 10: AWTWindows, Menus, and Dialog Boxes
338
Immediate Solutions
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
item1.addActionListener(this);
menu1.add(item1);
item2 = new MenuItem("Burger");
item2.addActionListener(this);
menu1.add(item2);
menubar1.add(menu1);
setMenuBar(menubar1); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
label1.setText("You ordered Pizza"); }
else if(e.getSource() == item2) {
item2.setEnabled(false);
label1.setText("You ordered Burger"); }
}
}
The result appears in Figure 10.7, where you can see the disabled menu item:
339
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Note that you use item listeners, not action listeners, with checkbox menu items. Heres how we add a
checkmark item to the applet AdvnancedMenu.java using an ItemListener object:
class MenuFrame extends Frame implements ActionListener, ItemListener {
Menu menu1, submenu1;
MenuBar menubar1;
Label label1;
MenuItem item1, item2, item4;
MenuItem subitem1, subitem2, subitem3;
CheckboxMenuItem item3;
MenuFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
item1.addActionListener(this);
menu1.add(item1);
item2 = new MenuItem("Burger");
item2.addActionListener(this);
menu1.add(item2);
menu1.addSeparator();
item3 = new CheckboxMenuItem("Idli");
item3.addItemListener(this);
menu1.add(item3);
. . .
menubar1.add(menu1);
setMenuBar(menubar1);
}
As the user selects this item time after time, Java will toggle the checkmark on and off automatically. To handle
events from this item, you have to override the itemStateChanged() method. In this case, we determine the
state of the menu item and display that state in a label, like this:
public void itemStateChanged (ItemEvent e) {
if(e.getSource() == item3) {
340
Immediate Solutions
if(((CheckboxMenuItem)e.getItemSelectable()).getState())
label1.setText("You ordered Idli");
else { label1.setText("Idli not ordered"); }
}
}
You can see the checkbox menu item in AdvancedMenu.java at work in Figure 10.8.
Creating Submenus
Another powerful aspect of working with menus in AWT programming involves submenus. Submenus are
attached to a menu item; and when the user selects the menu item, the submenu opens, as you saw in
Figure 10.6. The user can select items from the submenu just as he/she can select normal menus.
Using submenus is a very powerful technique when you need another level of detail; for example, you may want
to let the user select a drawing color with a menu item; and when that item is selected, a submenu opens
indicating possible colors, such as red, green, magenta, and blue.
Creating a submenu is easyyou just add menu items to another menu item using the add() method. Heres
how you do it:
MenuFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("Food Items");
item1 = new MenuItem("Pizza");
item1.addActionListener(this);
menu1.add(item1);
item2 = new MenuItem("Burger");
item2.addActionListener(this);
menu1.add(item2);
menu1.addSeparator();
item3 = new CheckboxMenuItem("Idli");
item3.addItemListener(this);
menu1.add(item3);
menu1.addSeparator();
submenu1 = new Menu("Cold Drinks");
subitem1 = new MenuItem("Pepsi");
subitem2 = new MenuItem("Limca");
subitem3 = new MenuItem("Coke");
subitem1.addActionListener(this);
subitem2.addActionListener(this);
subitem3.addActionListener(this);
item2.addActionListener(this);
341
Chapter 10: AWTWindows, Menus, and Dialog Boxes
item2.addActionListener(this);
submenu1.add(subitem1);
submenu1.add(subitem2);
submenu1.add(subitem3);
menu1.add(submenu1);
menu1.addSeparator();
item4 = new MenuItem("Exit");
item4.addActionListener(this);
menu1.add(item4);
menubar1.add(menu1);
setMenuBar(menubar1); }
Heres how we handle submenu item clicks in the actionPerformed() method:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
label1.setText("You ordered Pizza");
} else if(e.getSource() == item2) {
item2.setEnabled(false);
label1.setText("You ordered Burger");
} else if(e.getSource() == subitem1) {
label1.setText("You ordered Pepsi");
} else if(e.getSource() == subitem2) {
label1.setText("You ordered Limca");
} else if(e.getSource() == subitem3) {
label1.setText("You ordered Coke");
} else if(e.getSource() == item4) {
setVisible(false); }
}
You can see the submenu in Figure 10.9. When the user selects one of the submenu items, the applet displays
which item was ordered in the label in the frame window.
Pop-Up Menus
Hey, says the Novice Programmer, I saw that you can right-click some applications and a pop-up menu
appears. Can I do that in Java? Sure thing, you say, nothing to it. Just use the PopupMenu class.
You use the PopupMenu class to create pop-up menus that dont need to be attached to a menu bar. Heres the
inheritance diagram for this class:
java.lang.Object
|____java.awt.MenuComponent
|____java.awt.MenuItem
|____java.awt.Menu
|____java.awt.PopupMenu
342
Immediate Solutions
You can find the constructors for the PopupMenu class in Table 10.15 and the methods of this class in
Table 10.16.
Table 10.15: Constructors of the PopupMenu class
Constructor Does this
PopupMenu() It creates a new pop-up menu without any name
PopupMenu(String label) It creates a new pop-up menu with the given name
Lets look at an example. Here, we create a new pop-up menu and add four items to it (note that we also
implement a MouseListener interface to handle right clicks):
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/*<APPLET
CODE=PopupDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class PopupDemo extends Applet implements ActionListener,
MouseListener {
PopupMenu popup1;
MenuItem item1, item2, item3;
public void init() {
popup1 = new PopupMenu("Popup Menu");
item1 = new MenuItem("Red");
item1.addActionListener(this);
item2 = new MenuItem("Green");
item2.addActionListener(this);
item3 = new MenuItem("Blue");
item3.addActionListener(this);
popup1.add(item1);
popup1.addSeparator();
popup1.add(item2);
popup1.addSeparator();
popup1.add(item3);
add(popup1);
addMouseListener(this);
}
....
}
When the user right-clicks the applet window, we can use the PopupMenu classs show() method to display the
menu, passing that method a this keyword pointing to the applet and the position at which to display the pop-
up menu (here, we display the pop-up menu at the location where the mouse was clicked):
public void mousePressed(MouseEvent e) {
if(e.getModifiers() != 0) {
popup1.show(this, e.getX(), e.getY()); } }
343
Chapter 10: AWTWindows, Menus, and Dialog Boxes
Dialog Boxes
Uh-oh, says the Novice Programmer, I need some text input from the user, but the Big Boss said that if I put
one more text field into my program, I would live to regret it. How many text fields do you have in your
program? you ask. About four hundred, the Novice Programmer says. Hmm, you say, well, you can
always use a dialog box to get input from the user if you dont want to use another text field. The NP says,
Great!
AWT supports a special window classthe Dialog classthat you can use to create dialog boxes. The
windows created with this class look more like standard dialog boxes than the one you create with frame
windowfor example, dialog boxes do not have minimize and maximize buttons. Heres the inheritance
diagram for the Dialog class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____java.awt.Window
|____java.awt.Dialog
Youll find the constructors of the Dialog class in Table 10.17 and its methods in Table 10.18.
Table 10.17: Constructors of the Dialog class
Constructor Does this
Dialog(Dialog owner) It creates an initially invisible, modeless Dialog object with an empty title
and the given owner Dialog
Dialog(Dialog owner, String It creates an initially invisible, modeless Dialog object with the given owner
title) Dialog and title
344
Immediate Solutions
345
Chapter 10: AWTWindows, Menus, and Dialog Boxes
There are a few things to note in Tables 11.17 and 11.18. One is that you can create either modal dialog boxes
(that is, the user must dismiss the dialog box from the screen before interacting with the rest of the program) or
nonmodal dialog boxes, depending on which Dialog constructor you use or if you use the setModal()
method. Another point is that you can use the setResizeable() method to create a dialog box that the user
can resize.
Lets look at an example that puts the Dialog class to work. Well start by creating a new dialog box class
named OkCancelDialog that displays a text field and two buttons: OK and Cancel. If the user types text into
the text field and clicks the OK button, that text will appear in the main window of the application; otherwise, if
the user clicks the Cancel button, no text will appear. We start by extending OkCancelDialog from the Dialog
class, creating a new dialog box, and adding the controls well need in it:
class OkCancelDialog extends Dialog implements ActionListener {
Button ok, cancel;
TextField text;
public String data;
OkCancelDialog(Frame hostFrame, String title, boolean dModal) {
super(hostFrame, title, dModal);
setSize(300,100);
setLayout(new FlowLayout());
ok = new Button("OK"); add(ok);
ok.addActionListener((ActionListener)this);
cancel = new Button("Cancel"); add(cancel);
cancel.addActionListener(this);
text = new TextField(30); add(text);
data = new String(""); }
. . .
}
When the user clicks the OK button, we store the text the user typed in a public data member named data so
that itll be accessible to the rest of the program in the actionPerformed() method. If the user clicks Cancel,
we place an empty string in that data member. When the user clicks either of the buttons, we also hide the dialog
box. Heres the code:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == ok) { data = text.getText(); }
else { data = ""; }
setVisible(false);
. . .
}
346
Immediate Solutions
Thats it. We can make use of the new OkCancelDialog class in an application, displaying a dialog box of that
class when the user selects the item, Dialog box, in the File menu:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class DialogBoxDemo {
public static void main(String [] args) {
DialogFrame frame = new DialogFrame("Dialogs");
frame.setSize(200,200);
frame.addWindowListener(new WindowAdapter() { public void
windowClosing(WindowEvent e) {System.exit(0); } });
frame.setVisible(true); }
}
class DialogFrame extends Frame implements ActionListener {
Menu menu1;
MenuBar menubar1;
MenuItem item1;
Label label1;
OkCancelDialog dialog;
DialogFrame(String title) {
super(title);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("File");
item1 = new MenuItem("Dialog box");
menu1.add(item1);
item1.addActionListener(this);
menubar1.add(menu1);
setMenuBar(menubar1);
dialog = new OkCancelDialog(this, "Dialog", true); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
dialog.setVisible(true);
label1.setText(dialog.data); }
}
}
Note that we also recover the text data from the dialog box using a public data member named data and place it
in a label in the application. When this application runs and the Dialog box item in the File menu is clicked, the
dialog box appears, as shown in Figure 10.11.
347
Chapter 10: AWTWindows, Menus, and Dialog Boxes
348
Immediate Solutions
You can create file dialog boxes that indicate to the user that they are specifically intended for loading or saving files, depending
on which constant from Table 10.19 you use with the FileDialog constructor. If you dont specify which purpose the file dialog
box is for, youll just get a generic version.
Heres an example in which we let the user browse through directories with a file dialog box. When the user
selects a file, we display the file name in the main application window. Doing this is easy; we just create a
FileDialog object, show it with the setVisible() method, and then read the name of the file the user
selected by using the getFile() method:
import java.awt.*;
import java.awt.event.*;
public class FileDialogBoxDemo {
public static void main(String [] args) {
Dialogframe frame = new Dialogframe("Dialogs");
frame.setSize(200, 200);
frame.addWindowListener(new WindowAdapter() { public void
windowClosing(WindowEvent e) {System.exit(0); } });
frame.setVisible(true); }
}
class Dialogframe extends Frame implements ActionListener {
Menu menu1;
MenuBar menubar1;
MenuItem item1, item2;
Label label1;
FileDialog file, upload;
Dialog dialog;
Dialogframe(String title) {
super(title);
dialog = new Dialog(this, "Upload File", false, null);
label1 = new Label();
add(label1);
menubar1 = new MenuBar();
menu1 = new Menu("File");
item1 = new MenuItem("Open file");
item2 = new MenuItem("Upload file");
menu1.add(item1);
menu1.add(item2);
item1.addActionListener(this);
item2.addActionListener(this);
menubar1.add(menu1);
setMenuBar(menubar1);
file = new FileDialog(this, "File Dialog");
upload = new FileDialog(dialog, "Upload File"); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == item1) {
349
Chapter 10: AWTWindows, Menus, and Dialog Boxes
file.setVisible(true);
label1.setText("You selected " + file.getFile()); }
if(e.getSource() == item2) { upload.setVisible(true); }
}
}
Summary
In this chapter, you came to know about the windows, menus, and dialog boxes. Then, you learned how to
create frame windows, show and hide windows, automatically hide windows upon closing, and use the
Windows class. The chapter next helped you to create menus with menu objects and menu events, and add
menu separators to them. You also learned how to create submenus and pop-up menus. Lastly, you were
familiarized with the creation of dialog boxes.
In the next chapter, you will learn about Swing- Applets, Applications, and Pluggable Look and Feel.
350
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
11
SwingApplets,
Applications, and
Pluggable Look and Feel
If you need an immediate solution to: See page:
Working with Swing 358
Preparing to Create a Swing Applet 364
Understanding Content Panes 370
Creating a Swing Applet 372
Creating a Swing Application 374
Closing JFrame Windows 377
Using Insets for Selecting Component Borders 379
The Synth Skinnable Look and Feel 383
The Pluggable Look and Feel 386
The Pluggable Look and Feel for Components 390
The Nimbus Look and Feel 392
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
In Depth
This chapter begins with a discussion that a lot of programmers have been waiting fora discussion on Swing.
Lets get right into the solution with a look at some Java history.
352
In Depth
Swing
The Swing packages are built on a large number of built-in AWT classes and components (over 250 classes and
40 UI components). Generally, the UI components entice the programmers, so we begin our discussion with
them. Note that each UI component begins with the letter J; therefore, many programmers mistakenly use the
terms JFC and Swing interchangeably. The different Swing components classes are enlisted as follows:
JAppletIt is an extended version of java.applet.Applet that adds support for root panes and other
panes
JButtonIt is a push or command button
JCheckBoxIt is a checkbox that can be selected or deselected and displays its state visually
JCheckBoxMenuItemIt is a menu item that can be selected or deselected and displays its state visually
JColorChooserIt is a pane of controls for allowesing a user to select a color
JComboBoxIt is a combo box, which is a combination of a text field and a drop-down list
JComponentIt is the base class for the Swing components
JDesktopPaneIt is a container utilized for creating a multidocument interface or a desktop
JDialogIt is the base class for creating a dialog window
JEditorPaneIt is a text component that allows the user to edit various kinds of content
JFileChooserIt lets the user choose a file
JFrameIt is an extended version of java.awt.Frame that adds support root panes and other panes
JInternalFrameIt is a lightweight object that provides many of the features of a heavyweight frame
JInternalFrame.JDesktopIconIt represents an iconified version of a JInternalFrame component
JLabelIt is a display area for a short text string or an image (or both)
JLayeredPaneIt adds layers to a Swing container, allowing components to overlap each other
JListIt is a component that allows the user to select one or more objects from a list
JMenuIt is a pop-up menu containing JMenuItem objects that are displayed when the user selects it in
the JMenuBar component
JMenuBarIt is an implementation of a menu bar
JMenuItemIt is an implementation of a menu item
JOptionPaneIt makes it easy to pop up a standard dialog box
JPanelIt is a generic lightweight container
JPasswordFieldIt allows editing of a single line of text, where the view does not show the original
characters
JPopupMenuIt is a pop-up menu
JPopupMenu.SeparatorIt is a pop-up menu-specific separator
JProgressBarIt is a component that displays an integer value within an interval
JRadioButtonIt is a radio button that can be selected or deselected and displays its state visually
JRadioButtonMenuItemIt is a radio button menu item
JRootPaneIt is the fundamental component in the container hierarchy
JScrollBarIt is an implementation of a scrollbar
JScrollPaneIt refers to a container that handles a viewport, optional vertical and horizontal scrollbars,
as well as optional row and column heading viewports
JSeparatorIt is a menu separator
JSliderIt is a component that lets the user select a value by sliding a knob within an interval
353
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
drawn simply as an image inside the container and does not take up window from the operating system
environment. In addition, it consumes much less system resources. Therefore, the Swing components are
considered lightweight. A few more significant points are as follows:
All Swing components are derived from the JComponent class, and this class is, in turn, derived from the
AWT Container class, which has no heavyweight window (called a peer) itself. Therefore, the
JComponent is a lightweight class. Youll see in this chapter that the JComponent class adds a
tremendous amount of programming support to the AWT Component class. Note that as some top level
containers are not derived from the JComponent class, and the JComponent class is derived from the
AWT Container class, all Swing components are also AWT components. You can also mix the AWT
controls with the Swing controls in your programs. However, because Swing controls are merely drawn in
their container, you can end up with strange results as AWT controls will appear on top of them.
Not all Swing components are lightweight because lightweight components delete need the help of
operating system to draw lightweight controls over the window. For that reason, Swing supports these
heavyweight classes: JFrame, JDialog, JWindow, and JApplet.
Just as you build AWT applets by using the Applet class and AWT applications by using the Frame class,
you build Swing applets on the JApplet class and Swing applications by using the JFrame class. The fact
that Swing is built on top of AWT is by no means seamless to the programmer. For example, to paint
components, you dont override the paint() method anymore because Swing needs to do that to draw
component borders and you have direct access to the parts of the program in which menus and dialog
boxes are drawn. All in all, it takes some additional programming effort to move from AWT to Swing.
Swing Features
Apart from the large array of lightweight components in Swing, many other innovations have been introduced
in it. Some of the major innovations are discussed as follows:
BordersYou can draw borders in many different styles around components by using the setBorder()
method.
Graphics debuggingYou can use the setDebuggingGraphicsOptions() method for setting up
graphics debugging, which means that you can watch each line while drawing and flash it.
Easy mouseless operationIt allows to easily connect keystrokes to components.
TooltipsYou can use the setToolTipText() method of the JComponent class for providing tooltip to
the components. The tooltips are small windows that are visible whenever you move the mouse over a
component. They provide explanatory text.
Easy scrollingYou can connect scrolling feature to different components; this feature was not possible in
AWT.
Pluggable look and feelWith the help of this feature, the appearance of applets and applications can be
set to any one of the three standard appearances, such as Windows, Motif (Unix), or Metal (the standard
Swing look).
New layout managersThe BoxLayout and OverlayLayout layout managers are introduced in Swing.
Of these features, the pluggable look and feel is probably the most important because it allows you to select the
appearance style of your program. In AWT, controls were built on windows from the operating platform and
therefore, looked like other controls in that platformsomething that gave AWT programs a very platform-
specific appearance, which was not a good idea for a language that prides itself on being cross-platform. For
example, as different fonts and controls are used in different platforms, the layout of programs could appear
very different in different platforms. Swing introduces the Metal look, which is the new Java look, and it will
appear the same across all platforms. In addition, you can give your programs a Windows or Motif look if you so
choose. Well take a look at this process in this chapter.
355
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
In fact, Sun has created several other look and feel types that do not ship with the Software Development Kit (SDK), including
one for the Apple and another platform-independent look and feel called Organic. In addition, several third parties have also
created their own Java look and feels, such as JGoodies, Napkin, and Substance.
We have two essential programming differences between AWT and Swing programming to take a look at before
entering into the Immediate Solutions section. The first difference is that you work with panes when creating
Swing applets and applications, and the other is the Model View Controller programming architecture. Well
take a look at working with Swing panes first because you have to understand how panes work before setting
them anywhere at all in Swing.
Heres another difference between AWT and Swingwhen you redraw an item on any AWT screen, the update() method is
called to redraw the items background. To avoid flickering, the programmers often override the update() method by directly
calling the paint() method. On the other hand, case of the background of thean item is not redrawn by the update() method
in case of Swing. This is because the Swing components can be transparent, instead the update()method just calls the
paint() method directly.
Swing content panes use a border layout manager by default, whereas AWT applets use a flow layout by default, although AWT
frame windows do use border layouts by default.
356
In Depth
357
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
Immediate Solutions
Working with Swing
The NP appears and says, OK, Im ready to start working with Swing. Where do I start? Well, you say,
probably with the JComponent class.
All Swing components are derived from the JComponent class. It is a lightweight class that is derived from the
AWT Container class. The JComponent class is basically the javax.swing.JComponent class because the
javax package includes Swing. The inheritance diagram for the JComponent class is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
The JComponent class adds a lot to the AWT Container class, such as the ability to draw pre-defined borders
around UI components; add PropertyChangeListener objects, which are notified when a propertys value
changes; and much more. For understanding the fields, constructor, and methods of this large class, you can
refer Tables 11.1, 11.2, and 11.3, respectively:
Table 11.1: Fields of the JComponent class
Field Does this
protected AccessibleContext AccessibleContext represents the minimum information that all accessible
accessibleContext objects return. This information includes the accessible name, description,
role, and state of the object, as well as information about its parent and
children. This is associated with the JComponent class.
protected EventListenerList It is a list of the current event listeners.
listenerList
static String It is a comment to display when the cursor is over the component (also
TOOL_TIP_TEXT_KEY called value tip, flyover tip, or flyover label).
protected ComponentUI ui It is the look and feel delegate for this component.
static int It is a constant used by some of the APIs to mean that no condition is
UNDEFINED_CONDITION defined.
static int It is used for registerKeyboardAction, indicating that the command
WHEN_ANCESTOR_OF_FOCUSED_ should be invoked when the receiving component is an ancestor of the
COMPONENT focused component or is itself the focused component.
static int WHEN_FOCUSED It is a constant used for registerKeyboardAction, indicating that the
command should be invoked when the component has the focus.
static int It is a constant used for registerKeyboardAction, indicating that the
WHEN_IN_FOCUSED_WINDOW command should be invoked when the receiving component gets the focus
or is itself the focused component.
358
Immediate Solutions
359
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
360
Immediate Solutions
361
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
362
Immediate Solutions
363
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
364
Immediate Solutions
|____java.awt.Container
|____java.awt.Panel
|____java.applet.Applet
|____javax.swing.JApplet
You can find the fields of the JApplet class in Table 11.4, its constructor in Table 11.5, and the methods in
Table 11.6:
Table 11.4: Fields of the JApplet class
Field Does this
protected AccessibleContext It is an accessibility context
accessibleContext
protected JRootPane rootPane It is the root pane
protected boolean It indicates whether calls to the add and setLayout methods are
rootPaneCheckingEnabled forwarded to the contentPane
365
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
To start a Swing applet, you just derive a class from the JApplet class as follows (note that in this example, we
import javax.swing.* in order to use JApplet):
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE=SwingApplet.class
WIDTH=300
HEIGHT=200 >
</APPLET>
*/
public class SwingApplet extends JApplet { ... }
Unfortunately, things get more complex at this point (when you want to draw in an applet or add controls to it)
because you normally work with the content pane in the applet rather than directly with the applet itself. Both
the JApplet and JFrame objects have one child objectan object of the class JRootPaneand the content
pane is a part of the root pane. Well take a look at root panes in the next solution.
366
Immediate Solutions
367
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
As far as construction of applets and applications is concerned, you usually work with the content pane of the
root pane. The content pane itself, however, is a part of another panethe layered pane. Well take a look at
layered panes in the next solution.
368
Immediate Solutions
For convenience, JLayeredPane divides the depth range into the following different layers. Programmer can
put the component on any of the following layers, making it easy to ensure that components overlap properly,
without having to worry about the specific depths:
DEFAULT_LAYERThe standard, bottommost layer where most components go
PALETTE_LAYERThe palette layer resides above the default layer and is beneficial for floating toolbars
and palettes
MODAL_LAYERThe layer used for modal dialog boxes
POPUP_LAYERThe pop-up layer is displayed above the dialogs
DRAG_LAYERWhen you drag a component, assigning it to the drag layer makes sure that it is positioned
over all other components in the container
You can use the JLayeredPane methodsmoveToFront(), moveToBack(), and setPosition()to
reposition a component within its layer. You can also use the setLayer() method for changing the current
layer of the component. Youll find the fields of the JLayeredPane class in Table 11.10, its constructor in
Table 11.11, and its methods in Table 11.12:
Table 11.10: Fields of the JLayeredPane class
Field Does this
static Integer DEFAULT_LAYER It is a convenience object defining the Default layer
static Integer DRAG_LAYER It is a convenience object defining the Drag layer
static Integer It is a convenience object defining the Frame Content layer
FRAME_CONTENT_LAYER
static String LAYER_PROPERTY It is a bound property
static Integer MODAL_LAYER It is a convenience object defining the Modal layer
static Integer PALETTE_LAYER It is a convenience object defining the Palette layer
static Integer POPUP_LAYER It is a convenience object defining the Popup layer
369
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
As far as typical drawing operations go in applets and applications, the most important part of the layered pane
is the content pane, which well discuss in the following section.
370
Immediate Solutions
JFrame named myFrame, there was a need to call the getContentPane() method of JFrame foradding the
component as follows:
myFrame.getContentPane().add(someComponent)
But, after Java SE 5, the addition of a new component has become feasible without any such hindrances. Now, it
is also possible to directly set the layout manager and remove components from the container. This section
would enlighten upon how this is achieved, i.e., how can add(), setLayout(), and remove() be called
directly without calling the getContentPane()method and why cant ContentPane be ignored even though
you no longer have to call it to add components.
Suppose you have a JFrame for which you would like to set the layout manager and add various components. If
you refer the JFrame documentation, it can be seen that JFrame is inheriting the add() method from
java.awt.Container. The add() method is used to add a component to the JFrame container. The
Container class also includes the setLayout() method, which is used to specify the layout manager for the
given container, as shown in the following code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.Color;
public class JFrameDemo extends JFrame {
JFrameDemo() {
super("JFrameDemo");
setBackground(Color.BLACK);
setLayout(new GridLayout(7,7,2,2));
for(int i=0;i<49; i++) {
JPanel jpanel1 = new JPanel();
jpanel1.setBackground(new Color (
(int)(Math.random()*16777215)));
add(jpanel1); }
setSize(400,400);
setVisible(true); }
public static void main(String[] args){ new JFrameDemo();}
}
Compile and run the code of JFrameDemo.java. With this, a grid of forty-nine JPanel is found whose
background colors are assigned randomly to the JPanel, as shown in Figure 11.4:
371
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
Note that you can write the color name as in Color.BLACK in both the uppercase and lowercase. It might be
expected at this stage to have the background of the JFrame to be colored black so that the grid lines in between
the colored JPanel are black and not grey. The background of the JFrame is not ordinarily visible although it is
colored black because the color of the content pane is also black and resides on top of the region. If resizing of
the JFrame is done at this time, you might momentarily see the black background. Instead, change the
setBackground() line in the JFrameDemo program to the following:
getContentPane().setBackground(Color.BLACK);
Now, the grid lines are colored black, as shown in Figure 11.5:
372
Immediate Solutions
To add controls to a content pane, you first set the layout manager to whatever you like or use the default border
layout. To actually add the controls, you use the add() method, just as you do in AWT programming.
Lets take an example. In this case, well just display the text Kogent Learning Solutions! in an applet. How
does that text get displayed? We cant just display it in the default content pane of an applet because that pane is
an object, not a class. Therefore, we cant override its paintComponent() method. On the other hand, we can
add a panel, as represented by the JPanel class, to the applet so that it covers the content pane.
We can also draw in that panel by overriding its paintComponent() method (note that we could create a new
content pane class, override its paintComponent() method, and install it with the setContentPane()
method, but JPanel is generally used to create content panes anyway).
If you ever want to find out exactly what values were used to construct a visual component, such as JApplet, give it the focus,
press the Shift+Ctrl+F1 keys, and watch the console window for a complete overview.
The following code shows how we create a JPanel class that displays the text Kogent Learning Solutions!
(Note that we are giving this panel an orange background and calling the paintComponent() method; the
paintComponent() method is passed an AWT Graphics object, which we can use to draw the text):
class TextPanel extends JPanel {
TextPanel() { setBackground(Color.orange); }
public void paintComponent (Graphics g) {
super.paintComponent(g);
373
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
374
Immediate Solutions
void remove(Component comp) It removes the indicated component from this container
void repaint(long time, int x, int y It repaints the specified rectangle of this component within time
, int width, int height) milliseconds
void setDefaultCloseOperation It sets the operation that will happen by default when the user closes
(int operation) this frame
375
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
void setIconImage(Image image) It sets the image to be displayed as the icon for the window
void setJMenuBar (JMenuBar menubar) It sets the menu bar for this frame
Well put the JFrame class to work in an application now. In this case, well create a JPanel object (as in the
previous solution), install the panel in a JFrame object, and display the text Kogent Learning Solutions! in the
panel. We will set the background color of the panel as pink. The code is as follows:
class TextPanel extends JPanel {
TextPanel() { setBackground(Color.pink); }
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawString("Kogent Learning Solutions!", 50, 80); }
}
Next, we create an object of this new class and add it to the content pane of the JFrame object in an application,
as shown in the following code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class SwingAppDemo extends JFrame {
TextPanel panel;
public SwingAppDemo() {
super("Swing Application Demo");
Container c = getContentPane();
panel = new TextPanel();
c.add(panel); }
public static void main(String args[]) {
final JFrame frame = new SwingAppDemo();
frame.setBounds(100, 100, 250, 200);
frame.setVisible(true); }
}
In addition, note that we have used the setBounds()method to set the screen location and size of the JFrame
window. The result appears as shown in Figure 11.7:
376
Immediate Solutions
The EXIT_ON_CLOSE actually calls the System.exit(0) method and therefore, abruptly terminates the application or program.
The DISPOSE_ON_CLOSE, however, hides and disposes only the Jframe, not the other independent parts of the program;
they still remain active.
Note that these possibilities only deal with the window itself; if you want to end the application when the
application window is closed, youll still have to handle that yourself. Here, we dispose of the window and end
the application with a window adapter inner class, as shown in the following code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class JFrameCloseDemo extends JFrame {
TextPanel panel;
public JFrameCloseDemo() {
super("JFrame Close Demo");
Container c = getContentPane();
panel = new TextPanel();
c.add(panel); }
public static void main(String args[]) {
final JFrame frame1 = new JFrameCloseDemo();
frame1.setBounds(100, 100, 300, 200);
frame1.setVisible(true);
frame1.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame1.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e){
System.exit(0); }});
}
377
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
}
class TextPanel extends JPanel {
TextPanel() { setBackground(Color.cyan); }
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawString("Swing application using JPanel and JFrame!", 30, 60);
g.drawString("Close me to end the application!", 35, 100); }
}
Figure 11.8 shows the result of the program JFrameCloseDemo.java:
378
Immediate Solutions
import java.awt.*;
public class ExitDemo {
static JFrame jframe1 = new JFrame("The Frame Window being Sized");
public static void main(String[] args) {
Toolkit kit = jframe1.getToolkit();
Dimension d = kit.getScreenSize();
int x = d.width/3;
int y = (d.height)/3 - jframe1.getHeight();
jframe1.setBounds(x, y, d.width/3 , d.height/3);
jframe1.setVisible(true);
jframe1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }
}
In the preceding code, a Toolkit object is first created and used for getting the dimensions of the screen. The x
position is set to the horizontal center of the screen after dividing the screen width by 3. Next, the y position is
set to the vertical center (by dividing the screen height by 3), which is less than the width of the frame. The
setBounds() sets the position and size of the frame. The setDefaultCloseOperation (int operation)
void() sets the close operation to JFrame.EXIT_ON_CLOSE so that the frame is closed when the program
terminates.
379
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
380
Immediate Solutions
The BorderFactory class creates objects that implement the Border interface; youll find the methods of this
interface in Table 11.19:
Table 11.19: Methods of the Border interface
Methods Does this
Insets getBorderInsets (Component c) It gets the insets of the border
boolean isBorderOpaque() It determines whether the border is opaque
void paintBorder(Component c, It paints the border for the indicated component with the indicated
Graphics g, int x, int y, int width, position and size
int height)
Using Insets
An important aspect of working with borders is to know about insets, which indicate the distance you must
allow along each edge to account for the border. You can get the insets of a border with the
getBorderInsets() method of the Border interface; this method returns an object of the class Insets. The
inheritance diagram for the Insets class is given as follows:
java.lang.Object
|____java.awt.Insets
Youll find the fields of the Insets class in Table 11.20, its constructor in Table 11.21, and its methods in
Table 11.22:
Table 11.20: Fields of the Insets class
Field Does this
int bottom The inset from the bottom
int left The inset from the left
381
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
Lets consider an example in which we add a border to the JPanel object used in the applet. To do that, we just
use the panels setBorder() method (which most visual components have in Swing) and create a new titled
border with the BorderFactory classs createTitledBorder() method, as shown in the following code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/* <APPLET
CODE=BorderDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class BorderDemo extends JApplet {
TextPanel panel;
public void init() {
Container c = getContentPane();
panel = new TextPanel();
panel.setBorder(BorderFactory.createTitledBorder("Text Panel"));
c.add(panel); }
}
Besides adding a new border to the panel, we take the insets of this border into account to draw the message
Swing with Border Insets! without overlapping the border. To do that, we use the getBorder() method to
get the current border, the getBorderInsets() method of the object that supports the Border interface, and
the left data member of that object to determine where to start printing the message so as not to overlap the
border, as shown in the following code:
class TextPanel extends JPanel {
public void paintComponent (Graphics g) {
g.drawString("Swing with Border Insets!",
getBorder().getBorderInsets(this).left, 100); }
}
382
Immediate Solutions
383
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
jframe1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel jlabel1 = new JLabel("Synth look and feel");
jlabel1.setHorizontalAlignment(JLabel.CENTER);
jframe1.add(jlabel1);
jframe1.setSize(300,100);
jframe1.setVisible(true); }
};
EventQueue.invokeLater(r); }
}
The SynthDemo program creates a new SynthLookAndFeel object and loads an XML file, synth.xml, with
synth.load (InputStream class). This means that you need the XML file to complete this first example, as
shown in the following code:
<synth>
<style id="label">
<font name="Monospaced" size="18" style="BOLD ITALIC"/>
<opaque value="true"/>
<state>
<color value="RED" type="FOREGROUND"/>
</state>
</style>
<bind style="label" type="region" key="Label"/>
</synth>
Run the SynthDemo program with the synth.xml file. The program reads in the XML file, creates a JLabel
with a font "Monospaced". The size and style of the text of the label are 18 and BOLD ITALIC,
respectively. This label is then added on the screen, as shown in Figure 11.11:
C:\>java SynthDemo synth.xml
384
Immediate Solutions
Figure 11.12: Showing the Synth Look and Feel Window with Changed XML File Name
Here, we make a new program SynthDemo1.java calling the XML file synth1.xml.
This shows the capability of the Synth look and feel. Without any reprogramming, you can change the look and
feel of the program. A Synth File Format document contains the file format used in the XML file. You can see in
synth.xml that the outermost tag is <synth>. It can have other tags, such as <style>, <bind>, <font>,
<color>, <imagePainter>, and <imageIcon> inside it. In addition, there are several other special properties
that you can set. These properties are enlisted in a Component Specific Properties document. As seen in the just
stated preceding example, you define your styles and then bind them to the components. Most of the
information is contained in the <style> element. The other elements that can be configured for each named
style are:
<property>
<defaultsProperty>
<state>
<font>
<painter>
<imagePainter>
<backgroundImage>
<opaque>
<imageIcon>
<inputMap>
You can specify the fonts name, size, and style using the <font> tag. The other styles supported are PLAIN,
BOLD, and ITALIC. To specify two styles at the same time, both are written inside quotes with a space between
the two:
<font style="BOLD ITALIC"/>
However, the <state> tag is not always simple as it can be seen in the earlier examples. It can be more complex
too. For example, you can have a different look of a button when the mouse moves it. In such a case, you can
configure the MOUSE_OVER state as follows:
<state value="MOUSE_OVER">
<font name="Serif" size="20" style="BOLD"/>
</state>
This makes the appropriate state change to 20 point, bold, and Serif font. Besides the MOUSE_OVER state, the
other mouse state settings available are:
ENABLED
PRESSED
DISABLED
FOCUSED
SELECTED
DEFAULT
Depending upon the component, you can change the properties of any or all of these states. But, it must be
ensured that the size of the component remains unchanged with change in the configuration. Else, the
component will not revalidate itself when the state changes. In addition, the <imageIcon> element provides
you the means to work with icons. For example, you can have the following style to change the default tree
icons:
<style id="tree">
<imageIcon id="collapse" path="collapse.jpg"/>
<property key="Tree.collapsedIcon" value="collapse"/>
385
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
static Object get (Object key) It gets an object from the defaults table.
static Object get It gets an object from the defaults table that is appropriate for the
(Object key, Locale l) given locale.
static LookAndFeel[] It gets the list of auxiliary look and feel types.
getAuxiliaryLookAndFeels()
386
Immediate Solutions
static boolean getBoolean(Object key, It gets a boolean from the defaults table which is associated with the
Locale l) given key value and locale.
static Border getBorder(Object key) It gets a border from the defaults table which is associated with the
given key value.
static Border It gets a border from the defaults table that is appropriate for the
getBorder(Object key, Locale l) given locale.
static Color getColor(Object key) It gets a drawing color from the defaults table.
static Color It gets a drawing color from the defaults table that is appropriate for
getColor(Object key, Locale l) the given locale.
static String It gets the name of the LookAndFeel class that implements the
getCrossPlatformLookAndFeelClassName() default cross-platform look and feel (Java look and feel).
static UIDefaults getDefaults() It gets the defaults for this look and feel.
static Font getFont (Object key) It gets a font from the defaults.
static Font getFont It gets a font from the defaults, which is appropriate for the given
(Object key, Locale l) locale.
static Icon getIcon (Object key) It gets an icon from the defaults, which is appropriate for the given
locale.
static Icon getIcon (Object key, It gets an icon from the defaults.
Locale l)
static Insets getInsets It gets an Insets object from the defaults that is appropriate for the
(Object key, Locale l) given locale.
static int getInt (Object key) It gets an integer from the defaults .
static int getInt It gets an integer from the defaults, which is appropriate for the
(Object key, Locale l) given locale.
static LookAndFeel getLookAndFeel() It gets the current default look and feel.
static UIDefaults It gets the default values for this look and feel or null.
getLookAndFeelDefaults()
387
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
static String It gets a string from the defaults, which is appropriate for the given
getString(Object key, Locale l) locale.
static String It gets the name of the LookAndFeel class that implements the
getSystemLookAndFeelClassName() native systems look and feel if it exists; otherwise, name of the
default LookAndFeel class.
static void It adds the indicated look and feel to the set of available look and
installLookAndFeel(String name, String feels.
className)
static void It adds the indicated look and feel to the set of available look and
installLookAndFeel(UIManager.LookAndFe feels.
elInfo info)
static boolean It removes a LookAndFeel object from the list of auxiliary look and
removeAuxiliaryLookAndFeel feel types.
(LookAndFeel laf)
static void It sets the set of currently installed look and feels.
setInstalledLookAndFeels
(UIManager.LookAndFeelInfo [] infos)
static void setLookAndFeel It sets the current look and feel to the newLookAndFeel object.
(LookAndFeel newLookAndFeel)
static void setLookAndFeel (String It loads the current look and feel with a given class name and passes
className) it to the setLookAndFeel(LookAndFeel) method.
To change the look and feel as a program is tuning, you can use the UIManager classs setLookAndFeel()
method, passing it one of these arguments as a string:
javax.swing.plaf.metal.MetalLookAndFeel Pass this argument for the Metal look and feel.
com.sun.java.swing.plaf.motif.MotifLookAndFeel Pass this argument for the Motif look and feel.
com.sun.java.swing.plaf.windows.WindowsLookAndFeel Pass this argument for the Windows look
and feel.
After changing the look and feel of the content pane, you make it take effect with the
updateComponentTreeUI() method of the SwingUtilities class like this:
SwingUtilities.updateComponentTreeUI(getContentPane());
388
Immediate Solutions
Heres an example in which we add a Swing button and three radio buttons to see how the change in look and
feel changes the appearance of controls. The three radio buttons in this applet are labeled MetalLook,
MotifLook, and WindowsLook. When you click a radio button, the applet will change to the corresponding
look and feel. The code is as follows:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.sun.java.swing.plaf.motif.MotifLookAndFeel;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
/* <APPLET
CODE=LookAndFeelDemo.class
WIDTH=300
HEIGHT=200>
</APPLET> */
public class LookAndFeelDemo extends JApplet implements ActionListener{
JPanel jpanel1;
JRadioButton jradio1, jradio2, jradio3;
ButtonGroup group;
JButton jbutton1;
public void init() {
jpanel1 = new JPanel();
group = new ButtonGroup();
jbutton1 = new JButton("Kogent");
jradio1 = new JRadioButton("MotifLook");
group.add(jradio1);
jradio1.addActionListener(this);
jradio2 = new JRadioButton("MetalLook");
group.add(jradio2);
jradio2.addActionListener(this);
jradio3 = new JRadioButton("WindowsLook");
group.add(jradio3);
jradio3.addActionListener(this);
jpanel1.add(jradio1);
jpanel1.add(jradio2);
jpanel1.add(jradio3);
jpanel1.add(jbutton1);
Container c = getContentPane();
c.add(jpanel1); }
public void actionPerformed(ActionEvent e) {
JRadioButton src = (JRadioButton)e.getSource();
try {
if((JRadioButton)e.getSource() == jradio2)
UIManager.setLookAndFeel(
"javax.swing.plaf.metal.MetalLookAndFeel");
else if((JRadioButton)e.getSource() == jradio1)
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.motif.MotifLookAndFeel");
else if((JRadioButton)e.getSource() == jradio3)
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); }
catch(Exception ex) { }
SwingUtilities.updateComponentTreeUI(getContentPane()); }
}
389
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
You can see the applet in the Metal look and feel in Figure 11.13, the Motif look and feel in Figure 11.14, and the
Windows look and feel in Figure 11.15:
Figure 11.13: The Metal Figure 11.14: The Motif Look Figure 11.15: The Windows
Look and Feel and Feel Look and Feel
Switching between these looks is as easy as clicking a radio button.
abstract String getDescription() It gets a one-line description of this look and feel
implementation.
static Object getDesktopPropertyValue It gets the value of the specified system desktop property by
(String systemPropertyName, Object invoking
fallbackValue) Toolkit.getDefaultToolkit().getDesktopProperty().
LayoutStyle getLayoutStyle() It returns the LayoutStyle object for this look and feel.
abstract String getName() It gets a short string that identifies this look and feel.
390
Immediate Solutions
static void installProperty It installs a property with specified name and value on a
(JComponent c, String propertyName, component if that property does not already exist.
Object propertyValue)
abstract boolean If True, the underlying platform supports and/or permits this
isSupportedLookAndFeel() look and feel.
static void loadKeyBindings(InputMap It populates an InputMap object with the specified bindings.
retMap, Object[] keys)
static ComponentInputMap It creates a ComponentInputMapUIResource resource from
makeComponentInputMap keys.
(JComponent c, Object[] keys)
void provideErrorFeedback It is invoked when the user attempts an invalid operation (such
(Component component) as pasting into an uneditable JTextField)
391
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
Heres an example in which we give a Swing text field the look and feel of a Swing label using the
LookAndFeel classs installBorder() and installColorsAndFont() methods. Note that you have not
yet seen these controls at work formally; this example is just to indicate what can be done with the look and feel
types. Well create a Swing label here and a class extended from the text field class to look like a label. The code
is as follows:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE=LookAndFeelDemo1.class
WIDTH=200
HEIGHT=200 >
</APPLET> */
public class LookAndFeelDemo1 extends JApplet {
public void init() {
Container c = getContentPane();
TestJTextField test = new TestJTextField("This is a text field.");
c.setLayout(new FlowLayout());
c.add(new JLabel("This is a swing label."));
c.add(test); }
}
class TestJTextField extends JTextField {
public TestJTextField (String str) { super(str); }
public void updateUI() {
super.updateUI();
setHighlighter(null);
setEditable(false);
LookAndFeel.installBorder(this, "Label.border");
LookAndFeel.installColorsAndFont(this, "Label.background",
"Label.foreground", "Label.font"); }
}
The result appears as shown in Figure 11.16:
Figure 11.16: Setting the Look and Feel of a Text Field to be Like a Label
You can see in the figure that the text field, which appears under the label, has been given the look and feel of
the label. This gives you an indication of how powerful the look and feel handling in Swing is.
392
Immediate Solutions
After having created a cross-platform look and feel in the form of Metal, Sun enhanced its Swing capabilities
further, and added a new and different cross-platform look known as Nimbus look and feel. As stated earlier
also, it debuted in Java SE 6 Update 10. Instead of using static bitmaps, the Nimbus look and feel uses the Java2D
vector graphics to draw UI elements. This gives the elements an attractive and elegant look, independent of the
resolution. The look can even be customized as per the choice of the user.
In Java SE 7, the class NimbusLookAndFeel is located at the following location:
com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel.
To set the look and feel to Nimbus, you call the UIManagers method setLookAndFeel() and pass the
classname as an argument to it as:
UIManager.setLookAndFeel(com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel);
Heres an example in which we set the look and feel of the Swing components to Nimbus look and feel:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE=NimbusDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class NimbusDemo extends JApplet {
public void init() {
Container c = getContentPane();
c.add(new ComponentsPanel(), BorderLayout.CENTER); }
}
class ComponentsPanel extends JPanel {
public ComponentsPanel() {
add(new JButton("Kogent"));
add(new JTextField("Kogent"));
add(new JCheckBox("Kogent"));
add(new JRadioButton("Kogent"));
add(new JLabel("Kogent"));
add(new JList(new String[] {
" Item 1", " Item 2", " Item 3","Item 4","Item 5" }));
add(new JScrollBar(SwingConstants.HORIZONTAL));
try{
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); }
catch(Exception ex) { }
}
}
You can see the applet in the Nimbus look and feel in Figure 11.17:
393
Chapter 11: SwingApplets, Applications, and Pluggable Look and Feel
Summary
In this chapter, you have learned about the Java foundation classes. Then, you have learned Swings,
heavyweight and lightweight components, and features of Swings. The chapter has also explained how to create
graphic programming using panes. It has explored the use of Swings and discussed how to create an applet in
them. Further, you have learned how to close JFrame windows as well as use of insets to select component
borders. Next, synth skinnable look and feel, pluggable look and feel, pluggable look and feel for component,
and the nimbus look and feel have been explained.
In the next chapter, you will learn about SwingText Fields, Buttons, Toggle buttons, Checkboxes, and Radio
buttons.
394
12
SwingText Fields,
Buttons, Toggle Buttons,
Checkboxes,
and Radio Buttons
If you need an immediate solution to: See page:
Using Labels 399
Using Image Icons 401
Using Images in Labels 402
Using Text Fields 403
Setting Text Field Alignment 405
Creating Password Field 406
Creating Text Areas 407
Creating Editor Panes 409
Using HTML in Editor Panes 411
Using RTF Files in Editor Panes 412
Creating Text Panes 412
Setting Text Pane Text Attributes 414
Working with Sound in Applets 416
Working with Sound in Application 417
Abstract Button: The Foundation of Swing Buttons 417
Using Buttons 421
395
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
396
In Depth
In Depth
This chapter begins the discussion of Swing controls; specifically, well take a look at Swing labels, buttons, text
fields, toggle buttons, checkboxes, and radio buttons. All these are essential controls that make up a big part of
the foundation of Swing. With the exception of toggle buttons, all these controls should be familiar to you from
AWT programming. However, each of these Swing controls has a lot more functionality than the corresponding
AWT controls, and well emphasize whats new here. (Bear in mind that all Swing controls appear differently in
various looks and feels; this is important to remember when you start to program with them.)
Password Field
The JTextComponent class is extended by two classes: JTextArea and JEditorPane. JEditorPane is
extended by JTextPane class. JPasswordField is a JTextField used to write passwords, and the input
characters are usually marked with an asterisk. You can also modify the mask character using the
setEchoChar() method.
Text Area
The JTextArea is one of the subclasses of JTextComponent. It allows you to edit a multiline text. However, it
wont allow you to scroll directly, but you can add scrollbars by adding the text area to the JScrollPane
container.
Editor Pane
The JEditorPane is a special JTextComponent that can display and edit HTML 3.2 tags or formats, such as
RTF. It provides complex editing facilities in a rather simple and easy way. Notwithstanding, its just a
lightweight HTML viewer generally used to display the help text and not meant to create a full-fledged web
397
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
browser. To create an Editor Pane object, either you create it with a URL parameter or you use the setPage()
method to change the web pages. The HyperlinkListener interface is also provided to make the links within
an HTML page traversable.
Text Pane
The JTextPane class, a subclass of JEditorPane, lets you associate images or other components with the text
managed by the text pane. It supports formatted text, word wrap, and image display like a full-fledged text
editor. Additionally, to specify the font formatting it uses a linked list of objects and provides easy to use
methods for text formatting.
Buttons
In Swing, buttons of all kinds are built on the AbstractButton class, and well take a look at that class in this
chapter. As you might expect, Swing buttons have more capabilities than their AWT counterparts. For example,
using Swing buttons, you can display images, use mnemonics (keyboard shortcuts), designate a button as a
windows default button, and set a buttons margins and text alignment. You can also assign multiple images to
a button to handle the case where the mouse moves over the button, and more. Youll see all this in the chapter.
Toggle Buttons
Swing introduces toggle buttons, which are buttons that, when pressed, stay pressed until they are pressed
again. Toggle buttons are much like checkboxes and radio buttons that look like standard buttons. In fact, the
JToggleButton class is the base class for the Swing checkbox and radio button classes, but you can also
instantiate objects of this class directly. As with checkboxes and radio buttons, you can also put toggle buttons
into groups and use images with them.
398
In Depth
Immediate Solutions
Using Labels
The Novice Programmer appears and says, Im creating a new Swing applet, and I want to label the controls in
it, so Im starting with a Label component and Hold it, you say. You should be using a JLabel
component. The NP says, Oh.
The lightweight Swing label class is JLabel. Heres the inheritance diagram for this class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JLabel
Youll find the constructors for the JLabel class in Table 12.1 and its methods in Table 12.2:
Table 12.1: Constructors of the JLabel class
Constructor Does this
JLabel() It constructs a JLabel object with no image and title
JLabel(Icon image) It constructs a JLabel object with the indicated image
JLabel(Icon image, int It constructs a JLabel object with the indicated image and horizontal
horizontalAlignment) alignment
JLabel(String text) It constructs a JLabel object with the indicated text
JLabel(String text, Icon icon, It constructs a JLabel object with the indicated text, image, and horizontal
int horizontalAlignment) alignment
JLabel(String text, int It constructs a JLabel object with the indicated text and horizontal
horizontalAlignment) alignment
399
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
Heres a basic example that shows how to create a Swing label and add a text Kogent Learning Solutions!
to it:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE=JLabelDemo.class
WIDTH=250
HEIGHT=200>
</APPLET>*/
public class JLabelDemo extends JApplet {
public JLabelDemo() {
Container c = getContentPane();
JLabel jlabel1 = new JLabel("Kogent Learning Solutions!");
c.add(jlabel1); }
}
400
Immediate Solutions
Fortunately, theres an easy way to create icons from images in Swingyou can use the ImageIcon class,
coming up in the next solution.
401
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
The ImageIcon class is an extremely useful one in Swing because many Swing components can display icons.
Well put this class to work in the next solution.
402
Immediate Solutions
import javax.swing.*;
/*<APPLET
CODE=ImageLabelDemo.class
WIDTH=400
HEIGHT=200 >
</APPLET>*/
public class ImageLabelDemo extends JApplet {
public void init() {
Container c = getContentPane();
ImageIcon imgIcon = new ImageIcon("Java8.jpg");
JLabel jlabel1 = new JLabel("Kogent Learning Solutions", imgIcon, JLabel.CENTER);
jlabel1.setVerticalTextPosition(JLabel.BOTTOM);
jlabel1.setHorizontalTextPosition(JLabel.CENTER);
c.add(jlabel1); }
}
The result appears as shown in Figure 12.3:
403
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
Heres a quick example that does nothing more than displaying a text field with the text Kogent Learning
Solutions! written in red color:
import java.awt.*;
import javax.swing.*;
404
Immediate Solutions
/* <APPLET
CODE=JTextFieldDemo.class
WIDTH=250
HEIGHT=200>
</APPLET>*/
public class JTextFieldDemo extends JApplet {
JTextField jtextfield1;
public void init() {
jtextfield1 = new JTextField(15);
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(jtextfield1);
jtextfield1.setForeground(Color.RED);
jtextfield1.setText("Kogent Learning Solutions!"); }
}
The result of this code appears as shown in Figure 12.4:
405
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
if (align == JTextField.RIGHT)
jtextfield1.setHorizontalAlignment(JTextField.CENTER);
if (align == JTextField.CENTER)
jtextfield1.setHorizontalAlignment(JTextField.LEFT); }});
JFrame f = new JFrame("Alignment Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new java.awt.FlowLayout());
f.getContentPane().add(jtextfield1);
f.setSize(275, 75);
f.setVisible(true);
jtextfield1.requestFocus(); }
}
The result of the preceding code is shown in Figure 12.5(a), and the text is displayed as shown in Figure 12.5(b)
respectivel.
Figure 12.5(a): Showing the TextField Figure 12.5(b): The text is displayed
passwordField.selectAll(); resetFocus(); }
}
406
Immediate Solutions
Although the getText() method is available in the JPasswordField component, you should avoid using it
for security reasons; instead, you should use the getPassword() method. Also, in future, it may happen that
the getText() method may return a visible string (for example, kogent) ; therefore, it is not very safe. To
further enhance the security, as soon as you finish the character array returned by the getPassword()
method, you should set each of its elements to zero.
Usually, the program validates the password entered before using it to perform any action. In the following
code, the validation is performed by calling the isPasswordCorrect() method that compares the entered
password with the value stored in a different character array:
private static boolean isPasswordCorrect(char[] input) {
boolean isCorrect = true;
char[] correctPass = { 'b', 'u', 'g', 'a', 'b', 'o', 'o' };
if (input.length != correctPass.length) { isCorrect = false; }
else {
for (int i = 0; i < input.length; i++) {
if (input[i] != correctPass[i]) { isCorrect = false; }
}
}
for (int i = 0; i < correctPass.length; i++) { correctPass[i] = 0; }
return isCorrect;
}
407
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
408
Immediate Solutions
A text area is editable by default, but you can make it uneditable by passing False in the
setEditable(boolean) method. You can still select and copy the data from a text field, but making any
changes to the data directly will not be permitted. The \n character is used to write text in the next line; it is
called a newline character. The following code depicts how to add text to a text area and note that the text
system uses the '\n' character internally to represent newlines:
private final static String char = "\n";
. . .
area1.append(text + char);
By default, a text area automatically scrolls to make visible the appended text. However, automatically scrolling
doesnt occur when the user has moved the caret (also called insertion point) to some other point by dragging or
clicking in the text area. After you call the append() method, moving the caret position to the end of text area
scrolls it to the bottom. The setCaretPosition() method is used to explicitly set the caret position. This is
shown as follows:
area1.setCaretPosition(textArea.getDocument().getLength());
409
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
410
Immediate Solutions
If an editor pane displays the content of a new URL, then the content type determines the EditorKit you
should prefer to load the content. The following different kinds of content are available by default:
Text/plainIt uses an extension of DefaultEditorKit to produce a wrapped plain text view.
Text/htmlIt uses the class javax.swing.text.html.HTMLEditorKit, to provide HTML 3.2
support.
Text/rtfIt uses the class javax.swing.text.rtf.RTFEditorKit, to provide limited support for
the Rich Text Format.
411
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
412
Immediate Solutions
import javax.swing.text.*;
public class JTextPaneDemo extends JFrame {
static SimpleAttributeSet ITALIC_GRAY = new SimpleAttributeSet();
static SimpleAttributeSet BOLD_BLACK = new SimpleAttributeSet();
static SimpleAttributeSet BLACK = new SimpleAttributeSet();
JTextPane pane1 = new JTextPane();
static {
StyleConstants.setForeground(ITALIC_GRAY, Color.gray);
StyleConstants.setItalic(ITALIC_GRAY, true);
StyleConstants.setFontFamily(ITALIC_GRAY, "Helvetica");
StyleConstants.setFontSize(ITALIC_GRAY, 14);
StyleConstants.setForeground(BOLD_BLACK, Color.black);
StyleConstants.setBold(BOLD_BLACK, true);
StyleConstants.setFontFamily(BOLD_BLACK, "Helvetica");
StyleConstants.setFontSize(BOLD_BLACK, 14);
StyleConstants.setForeground(BLACK, Color.black);
StyleConstants.setFontFamily(BLACK,"Helvetica");
StyleConstants.setFontSize(BLACK, 14); }
public JTextPaneDemo() {
super ("JTextPane Demo");
JScrollPane jscrollPane1 = new JScrollPane(pane1);
getContentPane().add(jscrollPane1, BorderLayout.CENTER);
setEndSelection();
pane1.insertIcon(new ImageIcon("logo.jpg"));
insertText("\nHistory: Distant\n\n", BOLD_BLACK);
setEndSelection();
pane1.insertIcon(new ImageIcon("tom.jpg"));
insertText( " ", BLACK);
setEndSelection();
pane1.insertIcon (new ImageIcon("jerry.jpg"));
insertText( "\n Tom & "+ "Jerry\n\n" , ITALIC_GRAY);
setEndSelection();
JButton jbutton1 = new JButton("Visit Home");
jbutton1.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
pane1.setEditable(false);
try { pane1.setPage("http://www.logo.com"); }
catch(IOException ioe) {
ioe.printStackTrace(); }
}});
pane1.insertComponent(jbutton1);
setSize (675,500);
setVisible (true); }
protected void insertText (String text,AttributeSet set) {
try {
pane1.getDocument().insertString(
pane1.getDocument().getLength(), text, set); }
catch (BadLocationException e) { e.printStackTrace(); }
}
protected void setEndSelection() {
pane1.setSelectionStart (pane1.getDocument().getLength());
pane1.setSelectionEnd
(pane1.getDocument().getLength()); }
public static void main (String argv[]) { new JTextPaneDemo(); }
}
413
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
414
Immediate Solutions
The preceding code involves call to TextArea's setFont() and setForeground() methods. The former
sets the font style, while the latter sets the text color in the text area. The following code shows a (seemingly)
equivalent example using Swings JFrame and JTextPane classes:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class ListenerWindow1 extends WindowAdapter {
public ListenerWindow1() {
JFrame jframe1 = new JFrame("JTextPane Example");
jframe1.getContentPane().setLayout(new BorderLayout());
JTextPane pane1 = new JTextPane();
Font font = new Font("SansSerif", Font.ITALIC, 16);
pane1.setFont(font);
pane1.setForeground(Color.red);
jframe1.getContentPane().add(pane1, BorderLayout.CENTER);
jframe1.addWindowListener(this);
jframe1.setSize(300, 200);
jframe1.setVisible(true); }
public void windowClosing(WindowEvent evt) { System.exit(0); }
public static void main(String[] args) {
ListenerWindow1 listen = new ListenerWindow1(); }
}
The execution of the program is shown in Figure 12.8:
415
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
416
Immediate Solutions
{
if(sound != null)
sound.play(); }
}
The applet retrieves an AudioClip from the server. You must note that the applets only support sound files
having .au extension.
417
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
418
Immediate Solutions
419
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
420
Immediate Solutions
Using Buttons
The NP arrives and says, Im ready to start working with Swing buttons, what can they do? Hmm. you say,
Quite a lot! Better pull up a chair.
Swing buttons are supported in the JButton class. Heres the inheritance diagram for this class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.AbstractButton
|____javax.swing.JButton
The Swing buttons have more capabilities than their counterparts in AWT, such as you can add tooltip, margins,
mnemonics, and images to the Swing buttons. In addition, a Swing button is capable of performing what an
AWT button does, such as enabling or disabling, adding an action listener and an action command.
Youll find the constructors of the JButton class in Table 12.17 and its methods in Table 12.18. Note that this
class is based on the AbstractButton class, which means it inherits all of that classs functionality (see the
previous solution for the details).
Table 12.17: Constructors of the JButton class
Constructor Does this
JButton() It creates a button without any icon or text
JButton(Action a) It creates a button where properties are taken from the Action
supplied
JButton(Icon icon) It creates a button with an icon
JButton(String text) It creates a button with the given text
JButton(String text, Icon icon) It creates a button with the given text and icon
421
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
Lets look at an example that puts the JButton class to work. Here, we change the text and font of a label when
the user clicks a button. This example is very simple, as you can see in the following code.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE=JButtonDemo.class
WIDTH=300
HEIGHT=200>
</APPLET>*/
public class JButtonDemo extends JApplet {
JButton jbutton1;
JLabel jlabel1;
public void init() {
jbutton1 = new JButton("Click Me");
jlabel1 = new JLabel("Hello");
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(jlabel1);
c.add(jbutton1);
jbutton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Font font = new Font("Serif",Font.ITALIC,14);
jlabel1.setFont(font);
jlabel1.setText("Kogent"); }});
}
}
The result of this code appears as shown in Figure 12.10:
422
Immediate Solutions
As you can see in the figure that when the user clicks the button, the text and font of the text on label changes;
initially, it displays Hello and later Kogent.
Theres a lot more you can do with the JButton objects, and well take a look at the possibilities over the
following few solutions.
Lets look at another program (JButtonDemo1.java) which has some more featuresA text field asks for the
users name and then displays a salutation followed by the users name. For this, it uses JOptionPane (a
Swing component normally used to display messages) to say good morning to the user. In case the user clicks
without entering anything, the program displays an error message again using the JOptionPane:
import javax.swing.*;
import java.awt.event.*;
public class JButtonDemo1 extends JFrame {
public static void main(String [] args) { new JButtonDemo1(); }
private JButton ok;
private JTextField textName;
public JButtonDemo1() {
this.setSize(325,100);
this.setTitle("Identify yourself");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ButtonListener listener = new ButtonListener();
JPanel jpanel1 = new JPanel();
jpanel1.add(new JLabel("Enter your name: "));
textName = new JTextField(15);
jpanel1.add(textName);
ok = new JButton("OK");
ok.addActionListener(listener);
jpanel1.add(ok);
this.add(jpanel1);
this.setVisible(true); }
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ok) {
String name = textName.getText();
if (name.length() == 0) {
JOptionPane.showMessageDialog(JButtonDemo1.this,
"Please don't leave the box empty!", "Empty!!",
JOptionPane.INFORMATION_MESSAGE); }
else {
JOptionPane.showMessageDialog(JButtonDemo1.this,
"Good morning " + textName.getText(),
"Greetings to you",
JOptionPane.INFORMATION_MESSAGE); }
textName.requestFocus(); }
}
}
}
The result of this code that appears as shown in Figure 12.11:
423
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
The figure depicts the state when the user enters a name and clicks the button. In that case, JOptionPane
displays the message along with the users name.
Figure 12.12 depicts the state when the user clicks the button leaving the text field empty:
Figure 12.12: JOption displaying message not to leave the box empty
424
Immediate Solutions
425
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
add(click);
jtext1 = new JTextField(20);
add(jtext1); }
public void actionPerformed(ActionEvent e) {
jtext1.setText(e.getActionCommand()); }
}
The result appears as shown in Figure 12.14:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE=ButtonIconsDemo.class
WIDTH=300
HEIGHT=200>
</APPLET>*/
public class ButtonIconsDemo extends JApplet {
public void init() {
Container c = getContentPane();
Icon normalIcon = new ImageIcon("rollover 1.jpg");
Icon rolloverIcon = new ImageIcon("rollover 2.jpg");
Icon pressedIcon = new ImageIcon("rollover 3.jpg");
JButton jbutton1 = new JButton();
jbutton1.setRolloverEnabled(true);
jbutton1.setIcon(normalIcon);
jbutton1.setRolloverIcon(rolloverIcon);
jbutton1.setPressedIcon(pressedIcon);
c.setLayout(new FlowLayout());
c.add(jbutton1); }
}
You can see the result in Figure 12.15:
Figure 12.15: Using the rollover image and other images in a button
In the figure, when the mouse moves over the button, the rollover image becomes visible; and when the button
is pressed, a pressed image becomes visible.
427
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
CODE=DefaultButtonDemo.class
WIDTH=300
HEIGHT=200>
</APPLET>*/
public class DefaultButtonDemo extends JApplet {
JButton jbutton1 = new JButton("Button1");
JButton jbutton2 = new JButton("Button2");
JTextField jtext1 = new JTextField(20);
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
jbutton1.setMnemonic('1');
getRootPane().setDefaultButton(jbutton1);
c.add(jbutton1);
c.add(jbutton2);
c.add(jtext1);
getRootPane().requestFocus();
jbutton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
jtext1.setText("Hello Button1"); }});
jbutton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
jtext1.setText("Hello Button2"); }});
}
}
The result appears as shown in Figure 12.16:
428
Immediate Solutions
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
ClickListener cl = new ClickListener();
JPanel jpanel1 = new JPanel();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
exitButton.doClick(); }});
jbutton1 = new JButton("Press Enter or Click Mouse!");
jbutton1.setMnemonic('P');
getRootPane().setDefaultButton(jbutton1);
jbutton1.addActionListener(cl);
jpanel1.add(jbutton1);
exitButton = new JButton("EXIT");
exitButton.addActionListener(cl);
jpanel1.add(exitButton);
this.add(jpanel1);
this.setVisible(true); }
private class ClickListener implements ActionListener {
private int clickCount = 0;
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbutton1) {
clickCount++;
if (clickCount == 1)
jbutton1.setText("You clicked Me!");
else
jbutton1.setText("You clicked " + clickCount
+ " times!");
}
else if (e.getSource() == exitButton) {
if (clickCount > 0)
System.exit(0);
else {
JOptionPane.showMessageDialog(ClickMe.this,
"...try clicking once!!",
"In a hurry...!!",
JOptionPane.ERROR_MESSAGE); }
}
}
}
}
When the user clicks the Press Enter or Click Mouse! button, the buttons text changes to You clicked me! If
the user clicks the button again, the button text changes to You clicked 2 times! But if the user presses the Exit
button without pressing even once, an error message gets displayed.
The result of the preceding code is shown in Figure 12.17:
429
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
Well put JToggleButton to use in an example. In this example, we draw a few toggle buttons, most with
icons and some with text. Heres what the code looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE=JToggleButtonDemo.class
WIDTH=420
HEIGHT=650>
430
Immediate Solutions
</APPLET>*/
c.setLayout(new FlowLayout());
c.add(jtbutton1);
c.add(jtbutton2);
c.add(jtbutton3);
c.add(jtbutton4);
c.add(jtbutton5);
}
}
You can see the result of this code in Figure 12.18:
431
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
432
Immediate Solutions
Using Checkboxes
The NP says, I need some way for the user to select an option, from many options. In fact, I need some way for
the user to select multiple options from many options. I need.... Checkboxes, you say. What you need is
checkboxes. Right, says the NP.
The JCheckBox class has some advantages over the AWT CheckBox class, such as being able to display images.
Heres the inheritance diagram for the JCheckBox class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.AbstractButton
|____javax.swing.JToggleButton
|____javax.swing.JCheckBox
Youll find the constructors for the JCheckBox class in Table 12.21 and the methods of this class in
Table 12.22:
Table 12.21: Constructors of the JCheckBox class
Constructor Does this
JCheckBox() It constructs an unselected checkbox without any icon or text
JCheckBox(Action a) It constructs a checkbox with properties taken from the Action supplied
JCheckBox(Icon icon) It constructs an unselected checkbox with an icon
JCheckBox(Icon icon, boolean It constructs a checkbox with an icon and indicates whether its initially
selected) selected
JCheckBox(String text) It constructs an unselected checkbox with the given text
JCheckBox(String text, boolean It constructs a checkbox with the given text and indicates whether its
selected) initially selected
JCheckBox(String text, Icon icon) It constructs an unselected checkbox with the given text and icon
JCheckBox(String text, Icon icon, It constructs a checkbox with the given text and an icon and indicates
boolean selected) whether its initially selected
Lets take a look at an example. Here, we just display four checkboxes and indicate which one the user clicked
(note that, as with AWT checkboxes, ItemListener is used with JCheckBox objects, not ActionListener):
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
433
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
CODE=JCheckBoxDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class JCheckBoxDemo extends JApplet implements ItemListener {
JCheckBox jcheck1, jcheck2, jcheck3, jcheck4;
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
jcheck1 = new JCheckBox("Red");
jcheck2 = new JCheckBox("Green");
jcheck3 = new JCheckBox("Blue");
jcheck4 = new JCheckBox("Gray");
jcheck1.addItemListener(this);
jcheck2.addItemListener(this);
jcheck3.addItemListener(this);
jcheck4.addItemListener(this);
c.add(jcheck1);
c.add(jcheck2);
c.add(jcheck3);
c.add(jcheck4);
}
public void itemStateChanged(ItemEvent e) {
if (e.getItemSelectable() == jcheck1) {
showStatus("You clicked Red color checkbox"); }
else if (e.getItemSelectable() == jcheck2) {
showStatus("You clicked Green color checkbox"); }
else if (e.getItemSelectable() == jcheck3) {
showStatus("You clicked Blue color checkbox"); }
else if (e.getItemSelectable() == jcheck4) {
showStatus("You clicked Gray color checkbox"); }
}
}
You can see the result as shown in Figure 12.20:
434
Immediate Solutions
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ButtonListener listener = new ButtonListener();
JPanel mainPanel = new JPanel();
JPanel sizePanel = new JPanel();
mainPanel.add(sizePanel);
JPanel topPanel = new JPanel();
Border b2 = BorderFactory.createTitledBorder("Varieties available");
topPanel.setBorder(b2);
anchovies = new JCheckBox("Anchovies");
topPanel.add(anchovies);
Extra = new JCheckBox("Extra cheese");
topPanel.add(Extra);
pepperoni = new JCheckBox("Pepperoni");
topPanel.add(pepperoni);
onion = new JCheckBox("Onion");
topPanel.add(onion);
mushrooms = new JCheckBox("Mushrooms");
topPanel.add(mushrooms);
sausage = new JCheckBox("Sausage");
topPanel.add(sausage);
mainPanel.add(topPanel);
ok = new JButton("OK");
ok.addActionListener(listener);
mainPanel.add(ok);
this.add(mainPanel);
this.setVisible(true); }
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ok) {
String tops = "";
if (pepperoni.isSelected())
tops += "Pepperoni\n";
if (mushrooms.isSelected())
tops += "Mushrooms\n";
if (anchovies.isSelected())
tops += "Anchovies\n";
if (onion.isSelected()) { tops += "Onion\n"; }
if (sausage.isSelected()) { tops += "Sausage\n"; }
if (Extra.isSelected())
tops += "Extra cheese\n";
String msg = "You ordered ";
if (tops.equals("")) { msg += "no toppings."; }
else { msg += ":\n" + tops; }
JOptionPane.showMessageDialog(ok,
msg, "Your Order",JOptionPane.INFORMATION_MESSAGE);
pepperoni.setSelected(false);
mushrooms.setSelected(false);
anchovies.setSelected(false);
sausage.setSelected(false);
Extra.setSelected(false);
onion.setSelected(false); }
}
}
}
When the user does not select any of the toppings from the list, a message box gets displayed. In case he/she
selects some, the same message box details the chosen items. You can see the result of the code in Figure 12.21:
435
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
The example JCheckBoxDemo1.java uses the isSelected() method. You can read more about this method under the topic
Getting and Setting the State of Checkboxes and Radio Buttons.
JRadioButton(Action a) It constructs a radio button with properties taken from the Action
supplied
JRadioButton(Icon icon) It constructs an unselected radio button with the given image but no text
436
Immediate Solutions
JRadioButton(String text) It constructs an unselected radio button with the given text
JRadioButton(String text, boolean It constructs a radio button with the given text and selection state
selected)
JRadioButton(String text, Icon It constructs an unselected radio button that has the given text and
icon) image
JRadioButton(String text, Icon It constructs a radio button that has the given text, image, and selection
icon, boolean selected) state
String getUIClassID() It gets the name of the look and feel class that renders this component
void updateUI() It resets the UI property to a value from the current look and feel
Lets take a look at an example. Here, we just display four radio buttons and put them into the same button
group so that only one of the four can be selected at a time. Heres what the code looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE= JRadioButtonDemo.class
WIDTH=300
HEIGHT=200 >
</APPLET> */
public class JRadioButtonDemo extends JApplet implements ItemListener {
JRadioButton jradio1, jradio2, jradio3, jradio4;
ButtonGroup bg;
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
bg = new ButtonGroup();
jradio1 = new JRadioButton("Red");
jradio2 = new JRadioButton("Green");
jradio3 = new JRadioButton("Blue");
jradio4 = new JRadioButton("Gray");
bg.add(jradio1);
bg.add(jradio2);
bg.add(jradio3);
bg.add(jradio4);
jradio1.addItemListener(this);
jradio2.addItemListener(this);
jradio3.addItemListener(this);
jradio4.addItemListener(this);
c.add(jradio1);
c.add(jradio2);
c.add(jradio3);
c.add(jradio4);
}
public void itemStateChanged(ItemEvent e) {
437
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
if (e.getItemSelectable() == jradio1) {
showStatus("You selected Red color"); }
else if (e.getItemSelectable() == jradio2) {
showStatus("You selected Green color"); }
else if (e.getItemSelectable() == jradio3) {
showStatus("You selected Blue color"); }
else if (e.getItemSelectable() == jradio4) {
showStatus("You selected Gray color"); }
}
}
You can see the result of this code in Figure 12.22:
438
Immediate Solutions
sizeGroup.add(medium);
large = new JRadioButton("Large");
sizePanel.add(large);
sizeGroup.add(large);
mainPanel.add(sizePanel);
JPanel topPanel = new JPanel();
Border b2 = BorderFactory.createTitledBorder("Varieties available");
topPanel.setBorder(b2);
anchovies = new JCheckBox("Anchovies");
topPanel.add(anchovies);
Extra = new JCheckBox("Extra cheese");
topPanel.add(Extra);
pepperoni = new JCheckBox("Pepperoni");
topPanel.add(pepperoni);
onion = new JCheckBox("Onion");
topPanel.add(onion);
mushrooms = new JCheckBox("Mushrooms");
topPanel.add(mushrooms);
sausage = new JCheckBox("Sausage");
topPanel.add(sausage);
mainPanel.add(topPanel);
ok = new JButton("OK");
ok.addActionListener(listener);
mainPanel.add(ok);
this.add(mainPanel);
this.setVisible(true); }
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String msg = "", tops = "";
if (e.getSource() == ok) { tops = ""; }
if (pepperoni.isSelected()) { tops += "Pepperoni\n"; }
if (mushrooms.isSelected()) { tops += "Mushrooms\n"; }
if (anchovies.isSelected()) { tops += "Anchovies\n"; }
if (onion.isSelected()) { tops += "Onion\n"; }
if (sausage.isSelected()) { tops += "Sausage\n"; }
if (Extra.isSelected()) {
tops += "Extra cheese\n";
msg = "You ordered "; }
if (small.isSelected()) { msg += "A small pizza with "; }
if (medium.isSelected()) { msg += "A Medium pizza with "; }
if (large.isSelected()) { msg += "A Large pizza with "; }
if (tops.equals("")) { msg += "no toppings."; }
else { msg += "the toppings:\n" + tops; }
JOptionPane.showMessageDialog(ok, msg, "Your Order",
JOptionPane.INFORMATION_MESSAGE);
pepperoni.setSelected(false);
mushrooms.setSelected(false);
anchovies.setSelected(false);
small.setSelected(true); }
}
}
439
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
The example JRadioButtonDemo1.java uses the isSelected() method. You can read more about this method under the topic
Getting and Setting the State of Checkboxes and Radio Buttons.
440
Immediate Solutions
441
Chapter 12: SwingText Fields, Buttons, Toggle Buttons, Checkboxes, and Radio Buttons
if(checkbox[loop_index].isSelected()) {
msg += " CheckBox " + loop_index; }
}
showStatus(msg);
}
The result appears as shown in Figure 12.25:
Summary
In this chapter, we provided you with a brief introduction of labels, password field, text area, editor pane, text
pane, buttons, toggle buttons, checkboxes and radio buttons. You learned about the use of labels, image icons,
and how to set text field alignment. Then, you learned how to create password field, editor panes, HTML in
editor panes, and use of RTF files in editor panes. Later, we explored how to create and insert images in text
panes and set text pane attributes. We explored the work with sound and use of buttons.
In the next chapter, you will learn about Swing-Viewports, Scrolling, Sliders, Lists, Tables, and Trees.
442
13
SwingViewports,
Scrolling, Sliders, Lists,
Tables, and Trees
If you need an immediate solution to: See page:
Handling Viewports 447
Creating Scroll Panes 450
Creating Scroll Pane Headers and Borders 454
Scrolling Images 455
Creating Sliders 456
Filling a Slider 459
Painting Slider Tick Marks 460
Painting Slider Labels 460
Setting the Slider Extent 461
Creating Scrollbars 462
Creating Lists 465
Handling Multiple List Selections 469
Displaying Images in Lists 470
Creating a Custom List Model 471
Creating a Custom List Cell Renderer 472
Handling Double Clicks in Lists 472
Drag and Drop Support 473
Creating a Table 476
443
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
444
In Depth
In Depth
This chapter covers some important Swing topics, namely, Viewports, Scroll panes, Sliders, Scrollbars, List
controls, Tables, and Trees. The controls that are discussed in this chapter have one thing in commonscrolling.
The list control, in particular, is a very important control in Swing, but it does not handle scrolling by itself;
therefore, you need to understand how to work with scrolling before working with lists and many other Swing
controls. Let us take a quick look at the topics in this chapter before digging into the code.
Viewports
The JViewport class is at the heart of scrolling in Swing. A viewport is a window into a view, displaying a
section of your data. You can scroll viewports by yourself. Using viewports, you can move around in your
displayed data, much like handling the scrolling by yourself. Well take a look at using the JViewport class to
scroll images.
Scroll Panes
A common way to implement scrolling in Swing is to use scroll panes because you can scroll components by
using scroll panes. A number of Swing controls, such as the JList control, implement the Scrollable
interface to work with scroll panes. In fact, scroll panes are commonly used with JList controls to create
scrolling lists.
Sliders
Another scrollable control is the Swing slider control, which is supported by the JSlider class. Sliders are
much like the controls you see in audio devices that let you slide a knob along a track. In fact, sliders are similar
to scrollbars, except that you explicitly use sliders to let the user select a value from a continuous range. You can,
of course, do the same with scrollbars, but sliders were introduced because users expected that scrollbars will be
used to scroll other controls, such as text areas.
Scrollbars
Every Graphical User Interface (GUI) user generally knows about scrollbars, and Swing supports them just as
the Abstract Window Toolkit (AWT) does. We will use the JScrollBar class in this chapter, scrolling text
around an applet. When the scroll box (also called the thumb or bubble) is moved, the value of the scrollbar
changes. You can click the arrow buttons at the end of the scrollbar to change the value of the scrollbar by block
increment, or you can click the track of the scrollbar to change its value by unit increment.
Lists
Lists, supported by the JList class in Swing, are very popular controls because they let you present a list of
items in an easy way and hide a long list of items by making the list control scrollable. Well show you how to
scroll long lists as well as cover a number of other Swing topics. For example, you can make multiple selections
in various ways in Swing list boxes. You can also display images, handle double and even triple clicks, and
more. Well take a look at how to implement a new model for lists and cell renderers in order to handle the
actual display of each item in a list in a customized way.
Tables
The tables in Swing are important and powerful. In principle, they were created to constitute an interface related
to database and avoid the inherent complexity of handling data, thus providing flexibility to the programmer.
Nevertheless, its also possible to create a relatively simple JTable if it understands the operation correctly. The
JTable component is flexible enough to show and optionally allow you to edit the tabular data. It presents a
simple view of the data without any caching.
445
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Trees
Swing provides the JTree class to display data organized in the form of a tree. Each element in the tree is called
the JTree class and defines a component that displays the data arranged in a tree-like structure. Each element in
a tree is called a node, and the base node of a tree is referred to as the root node. A parent node is a node that has
other nodes attached to it, which are known as child nodes. Nodes that have no children are called leaf nodes.
The JTree class can be used to display database metadata, both in terms of the complexity of the structures it
can handle and in terms of the nature of the nodes in the structure. A JTree component is used for displaying
any tree structure virtually. The nodes in a tree can be any type of object, and they all can be different if you
need. To display the menu in a window, you can use the tree structure.
Thats it for the overview of this chapter. You can see that theres a lot coming up. Its time to turn to the
Immediate Solutions section.
446
Immediate Solutions
Immediate Solutions
Handling Viewports
Hmm, says the NP, I want to move an image around under programmatic control, without displaying any
scrollbars to the user. Is there any easy way to do that? As it happens, you say, there isyou can use a
viewport.
Viewports represent windows or portals into a view. For example, imagine that you have a huge document, not
all of which will fit on the screen at one time. To present the user with only a part of that document at once, you
can set up a viewport into that document, moving the viewport around the document until it fits. In fact, you
can have multiple viewports to let the user move around inside the data in your programs model at will.
Viewports are supported by the JViewport class, which is the foundation of scrolling in Swing. The inheritance
diagram for this class is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JViewport
Youll find the fields for the JViewport class in Table 13.1, its constructor in Table 13.2, and its methods in
Table 13.3:
Table 13.1: Fields of the JViewport class
Field Does this
protected boolean backingStore It is deprecated and returns True when the viewport maintains an
offscreen image of its contents
protected Image backingStoreImage It is the image used for a backing store
static int BACKINGSTORE_SCROLL_MODE It draws the viewport contents into an offscreen image
static int BLIT_SCROLL_MODE It uses the graphics.copyArea() method to implement scrolling
protected boolean isViewSizeSet It returns True when the viewport dimensions have been set
protected Point lastPaintPosition It indicates the last viewPosition painted
protected boolean scrollUnderway It indicates whether a scrolling operation is underway
static int SIMPLE_SCROLL_MODE It uses a very simple method to redraw the entire contents of the
scrollpane each time it is scrolled
447
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
448
Immediate Solutions
Lets take a look at a viewport example that enables the user to scroll the viewport, not with scrollbars but with
buttons. Here, we add a viewport with an image in it to a program as well as add a panel containing buttons
with the captions Scroll up and Scroll down. The user can scroll the image in the viewport by clicking the
buttons.
We start by creating a new viewport and then a new panel. We add a label with an image in it to the panel and
then add the panel to the viewport. When the user scrolls the viewport, he/she is actually scrolling the panel.
The following code shows how we create the viewport and add it to the program (note that to actually add the
panel to the viewport, we use the JViewport classs setView() method, which sets the viewports object):
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE=DemoJViewport.class
WIDTH=500
HEIGHT=200 >
</APPLET>*/
public class DemoJViewport extends JApplet {
public DemoJViewport() {
Container c = getContentPane();
JViewport port = new JViewport();
JPanel jp = new JPanel();
jp.add(new JLabel(new ImageIcon("illus.jpg")));
port.setView(jp);
c.add(port, BorderLayout.CENTER);
c.add(new ButtonPanel(port));
}
}
We also need another panel thats not a part of the viewport to display the buttons the user can use for scrolling.
Well call this panel ButtonPanel. Note that we must pass the viewport to this classs constructor so that it can
scroll the viewport. Heres how we store the viewport passed to the constructor and add the buttons needed for
scrolling:
class ButtonPanel extends JPanel implements ActionListener {
JViewport port;
JButton button1 = new JButton("Scroll up");
JButton button2 = new JButton("Scroll down");
449
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
All thats left is to implement scrolling when the user clicks a button. To do that, we use the JViewport classs
getViewPosition() method to get the current view position. Then, we change that positionaccording to the
button clickedby 15 pixels and use the setViewPosition() method to set the new viewport position, as
shown in the following code:
public void actionPerformed(ActionEvent e) {
Point position = port.getViewPosition();
if(e.getSource() == button1)
position.y = +15;
else if(e.getSource() == button2)
position.y =-15;
port.setViewPosition(position);
}
}
Now, we add a ButtonPanel object in the applet at the bottom as follows:
public class DemoJViewport extends JApplet {
public DemoJViewport() {
Container c = getContentPane();
JViewport port = new JViewport();
JPanel jp = new JPanel();
jp.add(new JLabel(new ImageIcon("illus.jpg")));
port.setView(jp);
c.add(port, BorderLayout.CENTER);
c.add(new ButtonPanel(port), BorderLayout.SOUTH); }
}
The result appears as shown in Figure 13.1:
450
Immediate Solutions
coordinated with the control being scrolled (the JViewport, JScrollPane, and JScrollBar classes all
implement this interface). The inheritance diagram for the JScrollPane class is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JScrollPane
Youll find the fields for the JScrollPane class in Table 13.4, its constructors in Table 13.5, and its methods in
Table 13.6:
Table 13.4: Fields of the JScrollPane class
Field Does this
protected JViewport columnHeader The column header child
protected JScrollBar horizontalScrollBar The scroll panes horizontal scrollbar child
protected int horizontalScrollBarPolicy The display policy for the horizontal scrollbar
protected Component lowerLeft The component to display in the lower left corner
protected Component lowerRight The component to display in the lower right corner
protected JViewport rowHeader The row header child
protected Component upperLeft The component to display in the upper left corner
protected Component upperRight The component to display in the upper right corner
protected JScrollBar verticalScrollBar The scroll panes vertical scrollbar child
protected int verticalScrollBarPolicy The display policy for the vertical scrollbar
protected JViewport viewport The scroll panes viewport child
451
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
452
Immediate Solutions
Lets look at an example in which we add a grid layout of text fields to a panel and scroll that panel in a scroll
pane. Well start by creating a JPanel object full of text fields as follows:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE=DemoJScrollPane.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJScrollPane extends JApplet {
public void init() {
Container c = getContentPane();
JPanel jp = new JPanel();
jp.setLayout(new GridLayout(11, 16));
for(int outer = 0; outer <= 10; outer++) {
for(int inner = 0; inner <= 15; inner++) {
jp.add(new JTextField("Text Field " + outer +
", " + inner)); }
}
/* some code */
}
}
Now, well add this new panel to a scroll pane. When you create a scroll pane object, you pass the object to be
scrolled, and you can specify when and where you want the scrollbars with these constants:
HORIZONTAL_SCROLLBAR_ALWAYS
HORIZONTAL_SCROLLBAR_AS_NEEDED
HORIZONTAL_SCROLLBAR_NEVER
VERTICAL_SCROLLBAR
VERTICAL_SCROLLBAR_ALWAYS
VERTICAL_SCROLLBAR_AS_NEEDED
VERTICAL_SCROLLBAR_NEVER
In this case, well always let the scroll pane display scrollbars, as shown in the following code:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE=DemoJScrollPane.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJScrollPane extends JApplet {
public void init() {
Container c = getContentPane();
JPanel jp = new JPanel();
jp.setLayout(new GridLayout(10, 15));
for(int outer = 0; outer <= 9; outer++) {
for(int inner = 0; inner <= 14; inner++) {
jp.add(new JTextField("Text Field " + outer +
", " + inner)); }
}
JScrollPane scrollpane = new JScrollPane(jp,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
c.add(scrollpane); }
}
453
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
The result of adding the scroll pane to the applets content pane is shown in Figure 13.2:
You can customize the corners of a scroll pane with the setCorner() method.
As an example, well put this customization to work in the scroll pane example that we have developed in the
previous solution. In this case, well use labels as the row and column headers and add an etched border, as
shown in the following code:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE=DemoJScrollPane1.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJScrollPane1 extends JApplet {
public void init() {
Container c = getContentPane();
c.setLayout(new BorderLayout());
JPanel jp = new JPanel();
jp.setLayout(new GridLayout(10, 15));
for(int outer = 0; outer <= 9; outer++) {
for(int inner = 0; inner <= 14; inner++) {
jp.add(new JTextField("Text Field " + outer +
", " + inner)); }
}
JScrollPane scrollpane = new JScrollPane(jp,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
454
Immediate Solutions
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
JLabel jl1 = new JLabel("Horizontal label");
JLabel jl2 = new JLabel("Vertical label");
scrollpane.setColumnHeaderView(jl1);
scrollpane.setRowHeaderView(jl2);
scrollpane.setViewportBorder(BorderFactory.createEtchedBorder());
c.add(scrollpane); }
}
You can see the result of this code in Figure 13.3:
Scrolling Images
Scroll panes provide an ideal way to scroll imagesall you have to do is display the image in a label (or a similar
component) and add that label to a scroll pane. Heres an example showing how this works:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE=DemoJScrollPane2.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJScrollPane2 extends JApplet {
public DemoJScrollPane2() {
Container c = getContentPane();
JLabel jl = new JLabel(new ImageIcon("bulg.jpg"));
JScrollPane scrollpane = new JScrollPane(jl);
c.add(scrollpane); }
}
The result appears as shown in Figure 13.4:
455
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Now, the user can scroll a large image, as needed, to handle an image that cant be displayed all at once.
Creating Sliders
The NP is back and says, I have seen a new control in various programssliders. When do you think will we
get those in Java? You smile and say, Quite a while ago.
You can use scrollbars to let the users select a value from a continuous range, but users have become more
familiar with using scrollbars to scroll other controls, such as lists. Therefore, Swing contains the JSlider class
to support slider controls.
Sliders present the user with controls that look like those you see in audio equipment; they are clearly intended
to let the user select a value from a range. To use the slider, the user moves a knob around with the mouse. The
inheritance diagram for the JSlider class is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JSlider
You can find the fields for the JSlider class in Table 13.7, its constructors in Table 13.8, and its methods in
Table 13.9:
Table 13.7: Fields of the JSlider class
Field Does this
protected ChangeEvent changeEvent The change event
protected ChangeListener The change listener
changeListener
protected int majorTickSpacing The number of values between the major tick marks
protected int minorTickSpacing The number of values between the minor tick marks
protected int orientation The orientation of the slider
protected BoundedRangeModel The data model, which handles the numeric maximum value,
sliderModel minimum value, and current position value for the slider
protected boolean snapToTicks If True, the thumb resolves to the closest tick mark next to where the
user positioned the thumb
456
Immediate Solutions
457
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Lets put the JSlider class to work in an example. In this case, well just create a slider that can return values
from 0 to 80 and report the current value in an applets status bar. The following code shows how we create a
horizontal slider with the constant SwingConstants.HORIZONTAL (as you might guess, the other possibility is
SwingConstants.VERTICAL) with a minimum value of 0, maximum value of 80, and initial value of 0:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
/* <APPLET
CODE=DemoJSlider.class
WIDTH=300
HEIGHT=200 >
</APPLET>
*/
public class DemoJSlider extends JApplet implements ChangeListener {
JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 0, 80, 0);
public void init() {
/* some code */
}
}
Now, in the init() method, well add this slider to the applets content pane. You use change listeners with
sliders, not adjustment listeners, as you do with scrollbars. The ChangeListener interface has only one
method, that is, stateChanged(), which you can see in Table 13.10:
Table 13.10: Method of the ChangeListener interface
Method Does this
void stateChanged (ChangeEvent e) It is invoked when the target of the listener has changed its state
We add a change listener to the slider in this applet and then add the slider to the applets layout, as shown in
the following code:
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
slider.addChangeListener(this);
c.add(slider);
}
458
Immediate Solutions
In the stateChanged() method, we use the JSlider() methods getMinimum(), getMaximum(), and
getValue() to display the settings for the slider in the status bar, as shown in the following code:
public void stateChanged(ChangeEvent e) {
JSlider js = (JSlider) e.getSource();
showStatus("Slider minimum: " + js.getMinimum() +
", maximum: " + js.getMaximum() +
", value: " + js.getValue());
}
The result appears as shown in Figure 13.5:
Filling a Slider
If you are using the default Metal look in Swing, you can fill in a slider, which means that its track will appear
filled from the origin to the sliders knob. To do that, you must set the JSlider classs isFilled client property
to True, which you can do as follows (note that we are adding this code to the slider example from the previous
solution):
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
slider.addChangeListener(this);
slider.putClientProperty("JSlider.isFilled", Boolean.TRUE);
c.add(slider);
}
The result appears as shown in Figure 13.6:
459
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
You can see that the slider in the figure is filled. The output of both the figures, Figure 13.5 and Figure 13.6,
appears same; therefore, the JSlider is filled by default. Try to run DemoFillJSlider.java by passing
Boolean.FALSE in the method putClientProperty() to notice the difference.
460
Immediate Solutions
461
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
When the user clicks the button, the sliders extent is set to 50, and as its maximum value is 80, the sliders value
cant exceed 30. You can see the result in Figure 13.9:
Creating Scrollbars
OK, says the NP, I want to let the users move through the data in my program. I want to let them adjust
values. I want to let them navigate through the items in a long list. I want.... Scrollbars, you say. What you
want is scrollbars. Right, says the NP.
The Swing lightweight scrollbar class is JScrollBar, and its inheritance diagram is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JScrollBar
You can find the fields of the JScrollBar class in Table 13.11, its constructors in Table 13.12, and its methods in
Table 13.13:
Table 13.11: Fields of the JScrollBar class
Field Does this
protected int blockIncrement The block increment
protected BoundedRangeModel model The model that represents the scrollbars minimum, maximum,
extent, and current values
protected int orientation The scrollbars orientation
protected int unitIncrement The unit increment
462
Immediate Solutions
463
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Lets take an example in which we use a scrollbar to scroll some text in an applet. To do that, we create a new
panel that displays a label with the text Hello ScrollBar! at the vertical position given by the public data
member named vertical. Heres what the panel class looks like:
class DemoPanel extends JPanel {
JLabel label = new JLabel("Hello ScrollBar!");
int vertical = 0;
DemoPanel() { label = new JLabel("Hello ScrollBar!"); add(label); }
public void paintComponent(Graphics g) {
super.paintComponent(g);
label.setLocation(0, vertical); }
public void setScrolledPosition(int newposition) { vertical = newposition; }
}
Now, we can add an object of this new panel class to an applet and a vertical scrollbar in a border layout as
follows:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE=DemoJScrollBar.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJScrollBar extends JApplet {
private JScrollBar sbar = new JScrollBar(JScrollBar.VERTICAL, 0,
0, 0, 150);
private DemoPanel jp = new DemoPanel();
public void init() {
Container c = getContentPane();
c.add(jp, BorderLayout.CENTER);
c.add(sbar, BorderLayout.EAST);
sbar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(
AdjustmentEvent e) {
JScrollBar sb = (JScrollBar)e.getSource();
jp.setScrolledPosition(e.getValue());
jp.repaint(); }});
}
}
464
Immediate Solutions
Creating Lists
The Big Boss appears in a cloud of cigar smoke and says, We have got 14,389 products now for the user to select
from. How are we going to display all those in a program? No problem, you say. Ill just use a list control.
The Big Boss smiles and says, Here are the product names to type in.
The JList class is the Swing lightweight list control. The inheritance diagram for the JList class is as follows:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.Jlist<E>
You can do more with JList controls than you can with AWT List controls; for example, you can display
images in Swing lists. In fact, well take a look at what you can do with Swing lists from this point to the end of
the chapter. You can find the constructors of the JList class in Table 13.14 and its methods in Table 13.15:
Table 13.14: Constructors of the JList class
Constructor Does this
JList() It constructs a JList object.
JList(ListModel<E> dataModel) It constructs a JList object that displays the elements in the indicated
data model.
JList(E[ ] listData) It constructs a JList object that displays the elements in the indicated
array.
JList(Vector<? extends E> listData) It constructs a JList object that displays the elements in the indicated
vector.
465
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
466
Immediate Solutions
467
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Note that you can get the currently selected items index with the JList classs getSelectedIndex()
method, multiple selections with the getSelectedIndices() method, the actual selected item with the
getSelectedValue() method, and the actual selected items with the getSelectedValues() method.
You should keep in mind that the data in a list is actually maintained by its model, so if you want access to an item thats not
selected, you can use the JList classs getModel() method to get the model and then the models getElementAt() method to get
the actual item.
Well put the JList class to work in this and the following few solutions. To start, we create a simple JList
example that just displays 10 items and reports which one the user clicks. We start by creating a list control with
those items in it as follows:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
/*<APPLET
CODE=DemoJList.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoJList extends JApplet implements ListSelectionListener {
JList list;
public void init() {
Container c = getContentPane();
String[] items = new String[10];
for(int loop_index = 0; loop_index <= 9; loop_index++) {
items[loop_index] = "Item " + loop_index; }
list = new JList(items);
/* some code */ }
/* some code */
}
Next, we add this list control to a scroll pane to enable scrolling, set it so that it will display four rows, and add a
selection listener to it, as shown in the following code:
public void init() {
Container c = getContentPane();
String[] items = new String[10];
for(int loop_index = 0; loop_index <= 9; loop_index++) {
items[loop_index] = "Item " + loop_index; }
list = new JList(items);
JScrollPane scrollpane = new JScrollPane(list);
list.setVisibleRowCount(4);
468
Immediate Solutions
list.addListSelectionListener(this);
c.setLayout(new FlowLayout());
c.add(scrollpane);
}
Now, in the valueChanged() method, we can use the getSelectedIndex() method to get the item the user
clicks and display the number of that item in the status bar:
public void valueChanged(ListSelectionEvent e) {
String msg = "You selected item no: ";
msg += list.getSelectedIndex();
showStatus(msg);
}
When the user clicks an item in the list, the applet displays which item was clicked, as you can see in
Figure 13.11:
469
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
HEIGHT=200 >
</APPLET>*/
public class DemoMultipleSelection extends JApplet implements ListSelectionListener {
JList list;
public void init() {
Container c = getContentPane();
String[] items = new String[10];
for(int loop_index = 0; loop_index <= 9; loop_index++) {
items[loop_index] = "Item " + loop_index; }
list = new JList(items);
JScrollPane scrollpane = new JScrollPane(list);
list.setVisibleRowCount(5);
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.addListSelectionListener(this);
c.setLayout(new FlowLayout());
c.add(scrollpane); }
/* some code */
}
When the user makes a selection, we can determine what items were selected in the valueChanged() method
by using the getSelectedIndices() method, which returns an array of the selected indexes. The end result
is that we can report these indexes in the applets status bar as follows:
public void valueChanged(ListSelectionEvent e) {
int[] indexes = list.getSelectedIndices();
String msg = "You selected:";
for(int loop_index = 0; loop_index < indexes.length; loop_index++) {
msg += " item " + indexes[loop_index]; }
showStatus(msg);
}
You can see the result in Figure 13.12:
470
Immediate Solutions
471
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
472
Immediate Solutions
473
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
ON_OR_INSERT It specifies that the data can be dropped on the existing items or in the
insert locations as specified by INSERT
ON_OR_INSERT_COLS It specifies that the data can be dropped on the existing items or in the
insert columns as specified by INSERT_COLS
ON_OR_INSERT_ROWS It specifies that the data can be dropped on the existing items or in insert
rows as specified by INSERT_ROWS
USE_SELECTION It tracks the drop location with the help of the components own internal
selection mechanism
All the components support a drop mode of USE_SELECTION. This is the way of indicating where to drop
something. A DropMode of ON is supported by the JList, JTable, and JTree components. The JTable
component has the following four additional drop-mode options:
INSERT_COLS
INSERT_ ROWS
ON_OR_INSERT_COLS
ON_OR_INSERT_ROWS
The inheritance diagram for the DropMode class is as follows:
java.lang.Object
|_ java.lang.Enum<DropMode>
|_ javax.swing.DropMode
While dragging and dropping, a drop mode determines the way a component tracks and shows the drop
location. You can find the methods of the DropMode class in Table 13.17:
Table 13.17: Methods of the DropMode Class
Method Does this
static DropMode valueOf(String It returns the enum constant of this type with the specified name
name)
static DropMode[] values() It returns an array containing the constants of this enum type in the order
they are declared
Various drop-mode options are signified by the DemoDragDrop class. In the JTextField, you are allowed to
enter and highlight anything, and then drag it over the JTree. After that, you can drop the text and view the
different behaviors for various settings of the mode.
The DemoDragDrop class describes different drop-mode options. Consider the following code:
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
public class DemoDragDrop {
public static void main(String args[]) {
Runnable run = new Runnable() {
474
Immediate Solutions
475
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
comboBox.getSelectedIndex();
tree.setDropMode(mode[selectedIndex]);
}});
bottomPanel.add(comboLabel);
bottomPanel.add(comboBox);
frm.add(bottomPanel,BorderLayout.SOUTH);
frm.setSize(300,400);
frm.setVisible(true); }
};
EventQueue.invokeLater(run); }
}
The output of this code shows the program window and dragging and dropping of the items of the JTree, as
shown in Figure 13.15(a) and Figure 13.15(b), respectively:
Figure 13.15(a): Displaying the JTree Figure 13.15(b): Showing the Drag and Drop Tree
It is aforementioned that you can type something in the text field of the program window, highlight it, and drag
it over the JTree.
Creating a Table
The Big Boss is concerned and wants to give flexibility to the programmer. Big Boss says, The table in Swing is
important. Is there any complexity in handling the data? No problem Boss you say. JDBC will help here to
fight with complexities. It gives much more flexibility to the programmer. Its easy to create a simple JTable.
A JTable displays similar or dissimilar type of data in the form of a rectangular array. The data contained in
each column can be of basic or class type. Although a JTable can be created in a number of ways, the most
general and convenient way is to create an object that encapsulates the data that the JTable would display. A
JTable can efficiently display the data stored in a database and has to implement the
javax.swing.TableModel interface for the same. The interfaces dealing with javax.swing.JTable are
listed in Table 13.18:
Table 13.18: Interfaces of JTable
Interface Does this
TableCellEditor This interface defines the method that any object needs to
implement. Here, the object would like to be an editor of values
for components, such as JListBox, JComboBox, JTree, or
JTable
476
Immediate Solutions
To create an object of JTable, you just need to pass the TableModel reference in the constructor. This is
shown as follows:
JTable table = new JTable(model);
Here, the variable model holds the object reference that encapsulates the data to be displayed in the JTable.
Next is the implementation of the TableModel interface that lies along with the JTable class in the
javax.swing.table package and contains a total of nine methods. An abstract class, AbstractTableModel,
implements six of the nine methods. Therefore, if you extend the AbstractTableModel class, three methods
still need to be implemented.
The class that implements the TableModel interface actually encapsulates the ResultSet object. Youll study
about ResultSet in Chapter 24.
The full set of methods declared in the TableModel interface is presented in Table 13.19:
Table 13.19: Methods of the TableModel class
Method Does this
void addTableModelListener It adds a listener to the list that is notified each time a change to
(TableModelListener l) the data model occurs
Class<?> It returns the most specific superclass for all the cell values in the
getColumnClass(int columnIndex) column
int getColumnCount() It returns the number of columns in the model
String getColumnName(int columnIndex) It returns the name of the column at columnIndex
int getRowCount() It returns the number of rows in the model
Object getValueAt(int rowIndex, It returns the value for the cell at columnIndex and rowIndex
int columnIndex)
boolean isCellEditable(int rowIndex, It returns True if the cell at rowIndex and columnIndex is editable
int columnIndex)
void removeTableModelListener It removes a listener from the list that is notified each time a
(TableModelListener l) change to the data model occurs
void setValueAt(Object aValue, It sets the value in the cell at columnIndex and rowIndex to
int rowIndex, int columnIndex) aValue
Note that it is the JTable object that actually calls these methods to access and manipulate the data in the table
model. While creating a class that implements the TableModel interface, its better to make it capable of
replacing the ResultSet object at any point of time. This will make a single JTable object capable of
displaying data corresponding to different resultsets just by assigning the reference of another ResultSet
object to the TableModel object. Its easy to accomplish this functionality; you just have to define a method that
accepts a ResultSet object as argument and make the data available with the help of the TableModel
interface, as shown in the following code:
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.swing.table.AbstractTableModel;
import java.util.Vector;
class DemoTableModel extends AbstractTableModel {
477
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Sorting Rows
For sorting and filtering rows, we use an abstract RowSorter class for supporting two mappings. One is for
mapping rows in a JTable to the elements of the underlying model and the other is for mapping from the
underlying model to the rows. It works with both TableModel and ListModel.
The Java SE provides a TableRowSorter class to work with JTable. The reference of class object
implementing the TableModel interface is passed to the TableRowSorter constructor and then the created
RowSorter is passed to the setRowSorter() method of JTable.
An example for the sorting table class DemoTableSort is as follows:
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class DemoTableSort {
public static void main(String args[]) {
Runnable run = new Runnable() {
public void run() {
JFrame frm = new JFrame("Sorting Table");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object rows[][] = {
{"AMZN", "Amazon", 43.28},
{"GOOG", "Google", 389.33},
{"MCRSFT", "Microsoft", 28.66},
{"SANSFT", "Sansoft Inc.", 128.76},
{"NOK", "Nokia Corp", 19.73},
{"ORCL", "Oracle Corp.", 14.58},
{"SUNMCRS", "Sun Microsystems Inc.", 5.97},
{"VODA", "Vodafone Group", 39.92},
{"YHO", "Yahoo!", 38.67}
};
String columns[] = {"Symbol", "Name", "Price"};
TableModel model =
new DefaultTableModel(rows, columns) {
public Class getColumnClass(int column) {
Class returnValue;
if ((column >= 0) &&
(column < getColumnCount())) {
478
Immediate Solutions
returnValue = getValueAt(0,
column).getClass(); }
else { returnValue = Object.class; }
return returnValue; }
};
JTable table = new JTable(model);
RowSorter<TableModel> rsorter =
new TableRowSorter<TableModel>(model);
table.setRowSorter(rsorter);
JScrollPane scrollpane = new JScrollPane(table);
frm.add(scrollpane, BorderLayout.CENTER);
frm.setSize(300, 150);
frm.setVisible(true); }
};
EventQueue.invokeLater(run); }
}
When you click on one of the column of the displayed table, youll get the contents of that column reordered. In
the following code, we are describing some important lines that are pertinent to sorting:
JTable table = new JTable(model);
RowSorter<TableModel> rsorter =
new TableRowSorter<TableModel>(model);
table.setRowSorter(rsorter);
The first line is used to associate the model with the table. The second line is then used for creating a RowSorter
according to the model. The third line is used for associating the RowSorter with the JTable. When a user
clicks on the column header, it sorts that column. If the same column header is clicked for a second time, it
reverses the sorted order.
Here, youll get three figures that describe the sorting of the table data. Figure 13.16 shows the table of three
columns:
Figure 13.16: Sorting Table when the Column Header Has Not Been Clicked
It is the initial table when the column header has not been clicked.
Figure 13.17 shows the table when a column header Name has been clicked once, and the names are sorted in
an alphabetical order:
Figure 13.17: Sorting Table when the Column Header Name Has Been Clicked Once
479
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Figure 13.18 shows the table when the column header Name has been double clicked; it sorts the names in
reverse of alphabetic order:
Figure 13.18: Sorting Table when the Column Header Name Has Been Double Clicked
480
Immediate Solutions
481
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
method is used internally for inclusion testing. The results of this code before and after filtering are displayed in
Figures 13.19 and 13.20, respectively:
Figure 13.19: Sorting Table before Filtering Figure 13.20: Sorting Table after Filtering
482
Immediate Solutions
Acquiring access to the ResultSetMetaData (will learn more about ResultSetMetaData in Chapter 24)
interface object corresponding to the ResultSet object is important for retrieving the names and number of
columns. You can use the getColumnLabel() method to obtain a label to be used for the column name. The
label depicts either the column name known to the database or the name you supply in the SELECT statement to
create the ResultSet object. The names of the columns are stored in the column_heading.
To remove any existing object references in the Vector<String[]>, you can use the clear() method. Each
vector element is a reference to an array of String objects, row_data, which is created inside the while loop.
The array elements are assigned values inside the for loop.
Once the array gets created, you store a reference to it in rows_data. After all the rows from the ResultSet
object have been stored, you call the fireTableChanged() method that the DemoTableModel class inherits
from the base class. This method notifies all listeners for the JTable object for this model that the model has
changed. Therefore, the JTable object should redraw itself from scratch. The argument of the
fireTableChanged() method is a reference to an object of the TableModelEvent type that can be used for
recording the portions of the model that have been modified.
Creating Trees
The NP is unhappy and says, Java might comprise very limited options for arranging data. What will be the
simple method to display required data as simple as it can be? No Sir, you say. It is possible with the JTree
class. The JTree class uses a TreeModel to get its data. It displays data organized in a tree-like structure.
The interfaces for dealing with javax.swing.JTree are enlisted in Table 13.20:
Table 13.20: Interfaces of the JTree class
Interface Does this
ImageObserver It observes the constructed images and gets the notifications about
image information
MenuContainer It is the super class of all menu-related containers
Serializable It enables serializability of class by implementing the
java.io.Serializable interface
Accessible It is the main interface for the accessibility package
Scrollable It provides information to scrolling containers, e.g., JScrollPane
An object of a class that implements the TreeNode interface is called a node. The methods declared by the
TreeNode interface that provide the mean of navigating a tree are enlisted in Table 13.21:
Table 13.21: Methods of the TreeNode interface
Method Does this
TreeNode getChildAt(int childIndex) It returns the child TreeNode at index childIndex
int getChildCount() It returns the number of children tree nodes the receiver contains
boolean isLeaf() It returns True if the receiver is a leaf
Enumeration children() It returns the children of the receiver as an Enumeration
boolean getAllowsChildren() It returns True if the receiver allows children
int getIndex(TreeNode node) It returns the index of node in the receivers children
TreeNode getParent() It returns the parent TreeNode of the receiver
The TreeNode interface does not provide enough ability for linking nodes in a tree. Each node must refer to its
parent node so that the tree structure gets created. The MutableTreeNode interface extends the TreeNode
interface and provides declaration of methods to construct the tree. The different methods of the
MutableTreeNode are listed in Table 13.22:
483
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
As per your requirement, you can create your own class to define nodes. In most of the cases, the
DefaultMutableTreeNode class in the javax.swing.tree package is sufficient. This class implements the
MutableTreeNode interface and also provides a few methods of its own. The default constructor of this class
creates a node with no parent and children.
The DefaultMutableTreeNode classs objects are most commonly used to create nodes of a tree. A user
object (a value supplied by the user in the DefaultMutableTreeNode constructor) acts as the value
displayed at each node. The toString() method of the user object actually represents what is displayed for
each node.
After you have created the nodes, organize them in a tree structure by using the
parentNode.add(childNode) method. The node is finally passed in the JTree constructor. You usually add
a JScrollPane element to support the change in size of the tree due to node expansion and collapse. The
following code represents a simple tree structure:
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Rootnode");
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
root.add(child1);
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
root.add(child2);
JTree tree = new JTree(root);
someWindow.add(new JScrollPane(tree));
When you create more complicated trees, its tough to maintain then when everything is done by hand.
Therefore, its better you first create a simple tree-like data structure and then use that data structure to create
and add other nodes.
484
Immediate Solutions
to the tree. You override the isLeaf() method so that the tree doesnt count and further create the nodes. The
code of the DemoJTree.java file is as follows:
import java.awt.*;
import javax.swing.*;
public class DemoJTree extends JFrame {
int n = 5;
public static void main(String[] args) {
int i = 5;
if (args.length > 0)
try { i = Integer.parseInt(args[0]); }
catch(NumberFormatException e) {
System.out.println("Can't parse number using defaultof "); }
new DemoJTree(i); }
public DemoJTree(int i) {
super("Creating a Dynamic JTree");
Container c = getContentPane();
JTree tree = new JTree(new App(1, n));
c.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize(300, 475);
setVisible(true); }
}
The DemoJTree.java will execute only after creating the App.java file because the method of the App.java
is being invoked. The result of the code is displayed in Figure 13.21:
485
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
return(super.getChildCount()); }
private void defineChild() {
ChildrenDefined = true;
for(int i=0; i<nChildren; i++)
add(new App(i+1, nChildren)); }
public String toString() {
TreeNode parent = getParent();
if (parent == null)
return(String.valueOf(outline_num));
else
return(parent.toString() + "." + outline_num);
}
}
The result of the code, DemoJTree.java, after expanding a few nodes is shown in Figure 13.22:
Container c = getContentPane();
DefaultMutableTreeNode root =
new DefaultMutableTreeNode("Root");
486
Immediate Solutions
DefaultMutableTreeNode childnode;
DefaultMutableTreeNode grandChildnode;
for(int childIndex=1; childIndex<4; childIndex++) {
childnode = new DefaultMutableTreeNode("Child " + childIndex);
root.add(childnode);
for(int grandChildIndex=1; grandChildIndex<4;
grandChildIndex++) {
grandChildnode =
new DefaultMutableTreeNode("Grandchild " + childIndex + "."
+ grandChildIndex);
childnode.add(grandChildnode); }
}
tree = new JTree(root);
tree.addTreeSelectionListener(this);
c.add(new JScrollPane(tree), BorderLayout.CENTER);
currentSelectionField = new JTextField("Current Selection: NONE");
c.add(currentSelectionField, BorderLayout.SOUTH);
setSize(250, 275);
setVisible(true); }
public void valueChanged(TreeSelectionEvent event) {
currentSelectionField.setText ("Current Selection: " +
tree.getLastSelectedPathComponent().toString()); }
}
The result of the code is shown in Figure 13.23:
487
Chapter 13: SwingViewports, Scrolling, Sliders, Lists, Tables, and Trees
Summary
This chapter has provided a brief introduction of viewports, scrollpanes, sliders, scrollbars, lists, tables, and
trees. Then, it has explained how to handle viewports, create scrollpanes, and scroll images. You have also
learned how to create and fill a slider and to paint the slider labels and slider tick marks. The chapter has
discussed how to create scrollbars, lists, and handle and display images in lists. Further, you have also learned to
create a custom list model and custom list cell renderer. The chapter also explained how to handle double clicks
in lists, implement drag and drop, and create a table.
In the next chapter, you will learn about Combo Boxes, Progress Bars, Tooltips, Separators, and Choosers.
488
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
14
SwingCombo Boxes,
Progress Bars, Tooltips,
Separators, and Choosers
If you need an immediate solution to: See page:
Creating Combo Boxes 492
Handling Combo Box Selection Events 496
Creating Editable Combo Boxes 497
Adding Images to Combo Boxes 499
Creating a Combo Box Model 500
Creating a Combo Box Custom Renderer 500
Creating Progress Bars 500
Updating Progress Bars 503
Handling Progress Bar Events 504
Creating Separators 507
Resizing Separators Automatically 508
Creating Color Choosers 510
Creating File Choosers 512
Creating File Chooser Filters 518
489
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
In Depth
In this chapter, we are going to cover some important Swing controlscombo boxes, progress bars, separators,
and choosers. Well also take a look at adding tooltips, those small windows that display explanatory text when
you let the mouse rest over a control. All these topics, especially combo boxes, are important topics in Java, and
well take a quick look at them before digging into the code.
Combo Boxes
The combo box is one of the most common controls in Graphical User Interface (GUI) programming, but the
AWT doesnt have a combo box. Swing rectifies that. Combo boxes are combinations of text fields and drop-
down lists. They are very useful in that they let the user either select an item from the list or enter own value into
the text field. Combo boxes are also very compact controlsthey only display one item and a button that the
user can use to display the drop-down list of other items. Combo boxes can function as drop-down lists,
presenting the user with an even more compact way of displaying a list of items than a list control could
manage, and they have become very popular for that reason. In fact, Swing makes the default combo box into a
drop-down list only because the default setting for combo boxes is to make them non-editable, which turns them
into drop-down lists.
Progress Bars
Progress bars are relatively new controls, got popular as a way to give the user some indication of the progress
of a long operation. Originally introduced as a way to show how an installation program is progressing,
progress bars are now used for all kinds of time-consuming operations, such as downloading from the Internet.
They display a colored bar inside them that grows (or shrinks), much like the mercury in a thermometer, to
display visually how an operation is proceeding. You can orient progress bars horizontally or vertically, select
the colors and labels used in them, and handle their events. Even so, progress bars remain simple controls,
because they really only have one functiondisplaying the progress of some task. Youll see all the possibilities
in this chapter.
Choosers
Like the AWT, Swing supports dialog boxes. Unlike the AWT, Swing also supports two dialog boxes that you
dont have to create or customize yourselffile choosers and color choosers. File choosers let the user select a
file for opening or saving, much like any standard file dialog box. Color choosers let the user select a color
among many. Both these choosers represent standard dialog boxes, and Sun has simply saved your time by
creating them for you. Well work with both these choosers in this chapter. We can use the color chooser in
programs immediately; but to actually use the file names returned by file choosers, we will have to wait until we
start working with files in a few chapters.
Tooltips
Tooltips are the small windows that appear and display explanatory text (such as Download Now or Open New
Folder) when the mouse rests over a control. Tooltips can be very useful because GUI users have a great
resistance to reading manuals. All the user has to do is let the mouse ride over your program to see what the
various controls do. On the other hand, bear in mind that too many tooltipsconnected with many different text
items in a text control can be a burden and make your program seem difficult to use.
490
In Depth
Separators
Separators are horizontal or vertical bars that let you organize your controls into groups. Although mostly used
in menus to divide options into logical groupings, separators can also be used in JApplet and JFrame
components, like any other control, as youll see in this chapter.
Thats it for the overview of whats in this chapter. As you can see, theres a lot coming up. Its time to turn to
the Immediate Solutions section now, starting with combo boxes.
491
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
Immediate Solutions
Creating Combo Boxes
Hmm, says the Novice Programmer, I want to let the user select a word from a list of words, but now users
say they want to enter their own words. Sounds reasonable, you say. What about using a combo box? OK,
says the NP. Can you add one to my code?
Combo boxes can be used in two ways in Swing: as normal combo boxes and as drop-down lists. Drop-down
lists let the users make a selection from a list that appears when they click a downwards pointing arrow. Normal
combo boxes, on the other hand, are combinations of text fields and drop-down lists; the users can select an item
from the drop-down list or enter their own text into the text field. Note that unlike list controls, only one item
may be selected at a time in a combo box. Combo boxes are supported by the JComboBox class in Swing, and
heres the inheritance diagram for that class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JcomboBox<E>
Youll find the fields for the JComboBox class in Table 14.1, its constructors in Table 14.2, and its methods in
Table 14.3.
Table 14.1: Fields of the JComboBox class
Field Does this
protected String actionCommand The action command
protected ComboBoxModel The data model
dataModel
protected ComboBoxEditor editor The editor responsible for the text field
protected boolean isEditable It indicates whether the combo box is editable
protected JComboBox.KeySelectionManager The key selection manager
keySelectionManager
protected boolean It indicates whether the drop-down list is enabled as a lightweight
lightWeightPopupEnabled component
protected int maximumRowCount It holds the row count
protected ListCellRenderer<? super E> The cell renderer
renderer
protected Object A reminder for the selected item
selectedItemReminder
492
Immediate Solutions
493
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
494
Immediate Solutions
The actual data in the combo box is stored in its model, which by default is an object of the
DefaultComboBoxModel class. You can find the methods of this class in Table 14.4. Note that to add and
delete items, you can use the models methods, as shown in the table. To get the model object, you can use the
getModel() method of JComboBox.
Table 14.4: Methods of the DefaultComboBoxModel class
Method Does this
void addElement(EanObject) It adds an item to the end of the model
E getElementAt(int index) It gets the value at the indicated index
int getIndexOf(Object anObject) It gets the index position of the indicated object in the list
Object getSelectedItem() It returns the selected item
int getSize() It gets the length of the list
void insertElementAt It adds an item at a specific index
(E anObject, int index)
void removeAllElements() It empties the list
void removeElement(Object anObject) It removes an item from the model
void removeElementAt(int index) It removes an item at a specific index
void setSelectedItem (Object anObject) It sets the selected item
To add items to a combo box, you can use the addItem() method, passing it an object that it will pass on to its
internal model. We put together an example here showing how this works. In this case, we just create a combo
box and add six itemsthat is, six String objectsto it. Heres the code:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE = DemoJComboBox.class
WIDTH = 200
HEIGHT = 150 >
</APPLET>*/
public class DemoJComboBox extends JApplet {
JComboBox combobox = new JComboBox();
public void init() {
Container c = getContentPane();
combobox.addItem("Item 1");
combobox.addItem("Item 2");
combobox.addItem("Item 3");
combobox.addItem("Item 4");
combobox.addItem("Item 5");
combobox.addItem("Item 6");
c.setLayout(new FlowLayout());
c.add(combobox); }
}
The result appears as shown in Figure 14.1, where you can see the combo box with its drop-down list open,
displaying all six items.
495
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
combobox.addItem("Item 6");
c.setLayout(new FlowLayout());
c.add(combobox);
combobox.addItemListener(this);
}
. . .
}
Now we add the itemStateChanged() method to this applet that the ItemListener interface needs:
public void itemStateChanged(ItemEvent e) { . . . }
This method is passed an object of the ItemEvent class, and we can determine whether the corresponding item
in the combo box list was selected by using the getStateChange() method, like this:
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
. . .
}
Well indicate whether an item was selected or deselected in the status bar of the applet like this:
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
msg += " Selected: " + (String)e.getItem();
else
msg += " Deselected: " + (String)e.getItem();
showStatus(msg);
}
The result of this code appears as shown in Figure 14.2:
497
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
In this example, we display the items text before its edited as well as after it has been edited, and the user
presses Enter. To get the items text before its edited, we use the getSelectedItem() method; and to get the
item after it has been edited, we use the editors getItem() method, like this:
public void actionPerformed(ActionEvent e) {
String msg = (String)combobox.getSelectedItem()
+ " was changed to " + (String)combobox.getEditor().getItem();
showStatus(msg);
}
The result appears as shown in Figure 14.3:
498
Immediate Solutions
500
Immediate Solutions
|____javax.swing.JComponent
|____javax.swing.JProgressBar
You can find the fields of the JProgressBar class in Table 14.6 (note that it also inherits two constants from
SwingConstants that you use for orientation: HORIZONTAL and VERTICAL), its constructors in Table 14.7, and
its methods in Table 14.8.
Table 14.6: Fields of the JProgressBar class
Field Does this
protected ChangeEvent changeEvent The change event
protected ChangeListener The change listener
changeListener
protected BoundedRangeModel The data model that holds data values for the progress bar
model
protected int orientation The orientation in which to display the progress bar
protected boolean paintBorder It returns True if there should be a border around the progress bar
protected boolean paintString It returns True if there should be a string label in the progress bar
protected String progressString An optional string that can be displayed on the progress bar
501
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
There are quite a few ways to display progress bars. For example, you can make them horizontal or vertical
when you call the classs constructor or use the setOrientation() method. You can also select the drawing
color for the actual bar, display a label inside the progress bar that indicates the current value, and more. The
basic use of all progress bars, however, is the same no matter what they look likeyou set a minimum and
maximum value for the progress bar (the default values are 0 and 100) and then update its display with the
setValue() method, as appropriate. Here are a few examples showing some of the ways you can display
progress bars:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE = DemoJProgressBar.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>*/
public class DemoJProgressBar extends JApplet
{
JProgressBar bar1, bar2, bar3,bar4, bar5, bar6;
public void init()
{
Container c= getContentPane();
c.setLayout(new FlowLayout());
bar1 = new JProgressBar();
502
Immediate Solutions
bar1.setValue(40);
c.add(bar1);
bar2 = new JProgressBar();
bar2.setMinimum(70);
bar2.setMaximum(150);
bar2.setValue(120);
bar2.setForeground(Color.green);
c.add(bar2);
bar3 = new JProgressBar();
bar3.setOrientation(JProgressBar.VERTICAL);
bar3.setForeground(Color.red);
bar3.setValue(30);
bar3.setStringPainted(true);
bar3.setBorder(BorderFactory.createRaisedBevelBorder());
c.add(bar3);
bar4 = new JProgressBar();
bar4.setOrientation(JProgressBar.VERTICAL);
bar4.setForeground(Color.blue);
bar4.setValue(70);
bar4.setStringPainted(true);
bar4.setBorderPainted(false);
c.add(bar4);
bar5 = new JProgressBar();
bar5.setOrientation(JProgressBar.VERTICAL);
bar5.setStringPainted(true);
bar5.setString("Hello from Java!");
bar5.setValue(80);
c.add(bar5);
}
}
The result of this code appears as shown in Figure 14.5, where you can see various progress bars displayed in a
number of ways: There is a lot of possibilities here (note, in particular, that you can add a label to the progress
bar to indicate its current setting, and you can customize the progress bars border).
On the other hand, static progress bars, like the one shown in Figure 14.5, arent much used because they dont
do anything:
503
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
After creating and displaying a progress bar, its up to you to update it with the setValue() method. Youll
usually do that by dividing your time-consuming task into parts, and youll update the progress bar as each part
completes:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE = DemoJProgressBarUpdate.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>*/
public class DemoJProgressBarUpdate extends JApplet {
JProgressBar bar = new JProgressBar();
JButton button = new JButton("Increment the progress bar");
public void init() {
Container c= getContentPane();
c.setLayout(new FlowLayout());
c.add(bar);
c.add(button);
bar.setStringPainted(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
bar.setValue(bar.getValue() + 15); }});
}
}
The result appears as shown in Figure 14.6:
/* <APPLET
504
Immediate Solutions
CODE = DemoJProgressBarEvent.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>*/
public class DemoJProgressBarEvent extends JApplet
{
JProgressBar bar = new JProgressBar();
JButton button = new JButton("Increment the progress bar");
public void init()
{
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(button);
bar.setForeground(Color.pink);
c.add(bar);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
bar.setValue(bar.getValue() + 15); }});
bar.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
showStatus("Minimum: " + bar.getMinimum()
+ " Maximum: " + bar.getMaximum() +
" Value: " + bar.getValue()); }} );
}
}
The result of this code appears as shown in Figure 14.7:
Creating Tooltips
Say, says the Product Support Specialist, no one seems to read the manuals, ever. Isnt there some way to
make our programs self-explanatory? Well, you say, we could reduce everything to a series of cartoons.
Hmm, says the PSS thoughtfully. Just kidding, you say quickly. Ill add tooltips to the controls in the
program.
505
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
Tooltips are small windows that appear when the user lets the mouse rest on a component. They display some
text that explains the purpose of the control. For example, a Cut buttons tooltip might read Cut selected text.
Tooltips are supported with the Swing JToolTip class, and heres that classs inheritance diagram:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JToolTip
Youll find the constructor of the JToolTip class in Table 14.9 and its methods in Table 14.10:
Table 14.9: The constructor of the JToolTip class
Constructor Does this
JToolTip() It constructs a tooltip
In fact, many components already have a method, setToolTipText(), that you can use to add a tooltip.
Heres an example in which we add a tooltip to a button:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE=DemoToolTip.class
WIDTH=300
HEIGHT=200 >
</APPLET>*/
public class DemoToolTip extends JApplet {
JButton button = new JButton("Click Here");
JTextField text = new JTextField(15);
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
button.setToolTipText("This is a button.");
text.setToolTipText("This is a text field.");
c.add(button);
c.add(text);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
text.setText("Kogent Solutions"); }});
}
}
Its as easy as adding a tooltip to most components. The result appears as shown in Figure 14.8, where you can
see the tooltip with its explanatory text as This is a button:
506
Immediate Solutions
Creating Separators
The NP says, The Big Boss told me that there are too many text fields in my program and I should divide them
into groups. You can do that in several easy ways, you say, such as adding text fields to panels and giving
the panels various background colors. You can even use separators. By the way, how many text fields are there
in your program? About 2,413, the NP says. Uh-oh, you say.
Separators are horizontal or vertical lines, and they usually appear in menus to separate options into logical
groups, but you can also use them to separate components in a layout. Theyre supported by the JSeparator
class in Swing, and heres that classs inheritance diagram:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JSeparator
You can find the constructors of the JSeparator class in Table 14.11 and its methods in Table 14.12:
Table 14.11: Constructors of the JSeparator class
Constructor Does this
JSeparator() It creates a new horizontal separator
JSeparator(int orientation) It creates a new separator with the indicated horizontal or vertical
orientation
507
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
Lets look at an example. Here, we put a separator between two text fields in a flow layout. To make a separator
visible, you have to do more than just add it to a layout you also have to give it a preferred size by using its
setPreferredSize() method. The usual way to do that is to use the separators getPreferredSize()
method to get the current width of the separator and then pass that and the new length you want to the
setPreferredSize() method. The setPreferredSize() and getPreferredSize() methods work with
objects of the AWT Dimension class, which has two fields: width and height. Heres how we create the new
separator and get its dimensions:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE = DemoJSeparator.class
WIDTH = 300
HEIGHT = 200 >
</APPLET>*/
public class DemoJSeparator extends JApplet {
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
Dimension dim = separator.getPreferredSize();
. . .
Now we can put the separator between two text fields, like this, making it 100 pixels high:
public class DemoJSeparator extends JApplet {
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
Dimension dim = separator.getPreferredSize();
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(new JTextField("Kogent Solutions"));
c.add(separator);
c.add(new JTextField("Kogent Solutions"));
separator.setPreferredSize(new Dimension(dim.width, 100));}
}
The result of this code appears as shown in Figure 14.9:
508
Immediate Solutions
For example, when you resize an applet, you can resize a separator to the new size you want. Heres an example in
which we create a separator between two text fields that goes from the top of an applet windows client area to the
bottom and maintains that extent even when the applet is resized. Heres what the code looks likenote the
resizing code in the ComponentShown (to display the separator the first time) and ComponentResized methods:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = DemoJSeparatorEvent.class
WIDTH = 300
HEIGHT = 200 >
</APPLET>*/
public class DemoJSeparatorEvent extends JApplet implements ComponentListener {
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
Dimension dim = separator.getPreferredSize();
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(new JTextField("Kogent Solutions"));
c.add(separator);
c.add(new JTextField("Kogent Solutions"));
addComponentListener(this); }
public void componentShown(ComponentEvent e) {
separator.setPreferredSize(new Dimension(dim.width,getSize().height));
separator.revalidate(); }
public void componentResized(ComponentEvent e) {
separator.setPreferredSize(new Dimension(dim.width,getSize().height));
separator.revalidate(); }
public void componentMoved(ComponentEvent e) { }
public void componentHidden(ComponentEvent e) { }
}
The result of this code appears as shown in Figure 14.10:
509
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
510
Immediate Solutions
Using a color chooser is easy; all you have to do is to show it with its showDialog() method, passing that
method a parent object, a caption, and a default color. This method returns the color selected by the user as a
Color object (or the default color if the user didnt select a color).
Lets look at an example in which we place a button in a panel and let the user display a color chooser when the
button is clicked. After the user selects a color, the code will set the background of the panel to that color. Heres
what the code looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = DemoJColorChooser.class
WIDTH = 200
HEIGHT = 200 >
</APPLET>*/
public class DemoJColorChooser extends JApplet implements ActionListener {
JPanel panel = new JPanel();
JButton button;
public void init() {
button = new JButton("Change background color");
button.addActionListener(this);
panel.add(button);
getContentPane().add(panel); }
public void actionPerformed(ActionEvent e) {
Color color = JColorChooser.showDialog(DemoJColorChooser.this,
"Select the color of your choice", Color.white);
511
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
panel.setBackground(color); }
}
As you can see, its easy to use a color chooser; the color chooser appears when the user clicks the Change
background color button, as shown in Figure 14.11 (a).
When the user selects a color in the color chooser, the new color appears in the applets panel, as shown in
Figure 14.11 (b).
512
Immediate Solutions
Youll find the fields of the JFileChooser class in Table 14.17, its constructors in Table 14.18, and its methods
in Table 14.19:
Table 14.17: Fields of the JFileChooser class
Field Does this
static String It identifies whether the AcceptAllFileFilter is used
ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY or not.
protected AccessibleContext The accessible context
accessibleContext
static String It indicates that a different accessory component is in use
ACCESSORY_CHANGED_PROPERTY
static String It indicates a change in the mnemonic for the Yes/OK
APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY button
static String It indicates a change in the text on the Yes/OK button
APPROVE_BUTTON_TEXT_CHANGED_PROPERTY
static String It indicates a change in the tooltip text for the Yes/OK
APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY button
static int APPROVE_OPTION The return value if the Yes/OK button is chosen
static String This is a instruction to approve the current selection
APPROVE_SELECTION
static int CANCEL_OPTION The return value if the Cancel button is chosen
static String CANCEL_SELECTION This is a instruction to cancel the current selection
static String It indicates a change in the list of predefined file filters the
CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY user can choose from
static String It is an instruction to display the control buttons.
CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY
static int CUSTOM_DIALOG It is a type value indicating that the file chooser supports a
developer-specified file operation
static String DIALOG_TITLE_CHANGED_PROPERTY It indicates a change in the dialog boxs title
static String DIALOG_TYPE_CHANGED_PROPERTY It indicates a change in the type of files displayed (files
only, directories only, or both files and directories)
static int DIRECTORIES_ONLY This is a instruction to display only directories
static String DIRECTORY_CHANGED_PROPERTY It indicates a directory change
static int ERROR_OPTION The return value if an error occurred
static String FILE_FILTER_CHANGED_PROPERTY It indicates the user changed the kind of files to display
static String FILE_HIDING_CHANGED_PROPERTY It indicates a change in the display-hidden-files property
static String It indicates a change in the kind of selection (single,
FILE_SELECTION_MODE_CHANGED_PROPERTY multiple, and so on)
static String It indicates that a different object is being used to find
FILE_SYSTEM_VIEW_CHANGED_PROPERTY available drives on the system
static String It indicates that a different object is being used to retrieve
FILE_VIEW_CHANGED_PROPERTY file information
static int FILES_AND_DIRECTORIES This is an instruction to display both files and directories
static int FILES_ONLY This is an instruction to display only files
static String It enables multiple-file selections
MULTI_SELECTION_ENABLED_CHANGED_PROPERTY
static int OPEN_DIALOG It indicates that the file chooser supports an Open file
operation
513
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
514
Immediate Solutions
515
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
You can use the JFileChooser classs showOpenDialog() method to show a file chooser for finding files to
open, and you can use the showSaveDialog() method to show a file chooser for specifying the file name and
path to use to save a file. These methods return the following values:
APPROVE_OPTIONIt is returned if the user clicks an approve button, such as Save or Open.
CANCEL_OPTIONIt is returned if the user clicks Cancel.
ERROR_OPTIONIt is returned if there was an error.
You can get the selected file as a File object with the file choosers getSelectedFile() method (youll see
the File class later in this book), and you can use the File classs getPath(), getName(), and other methods
to return information about the file.
Lets look at an example that puts this to work. In this case, we display an Open file chooser when the user
clicks a button (Figure 14.12). We let the user select a file, and then we display that files name and path in a text
field. Because you usually dont open files from applets (for security reasons), well make this example an
application. Heres the code (note that we check the return value from showOpenDialog() to see whether the
user clicked the Open button before displaying the file name in the text field):
import java.awt.*;
import java.io.File;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.filechooser.*;
public class DemoJFileChooser extends JFrame implements ActionListener {
JFileChooser chooser = new JFileChooser();
JButton button = new JButton("Display file chooser");
JTextField text = new JTextField(30);
public DemoJFileChooser() {
super();
Container c = getContentPane();
c.setLayout(new FlowLayout());
516
Immediate Solutions
c.add(button);
c.add(text);
button.addActionListener(this); }
public void actionPerformed(ActionEvent e) {
int result = chooser.showOpenDialog(null);
File file = chooser.getSelectedFile();
if(result == JFileChooser.APPROVE_OPTION) {
text.setText("You selected: " + file.getPath()); }
else if(result == JFileChooser.CANCEL_OPTION) {
text.setText("You clicked Cancel"); }
}
public static void main(String args[]) {
JFrame f = new DemoJFileChooser();
f.setBounds(200, 200, 400, 200);
f.setVisible(true);
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0); }} );
}
}
The file chooser that this application displays appears in Figure 14.13. The user can browse and select a file
(Figure 14.13). When he/she does, either by highlighting a file and clicking the Open button in the file chooser or
by simply double-clicking the file in the file chooser, the file chooser closes, and the name and path of the
selected file appear in the text field in the application, as you can see in Figure 14.14:
517
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
518
Immediate Solutions
Its not difficult to implement the methods of the FileFilter class; the accept() method is passed a File
object (youll see the File class later in this book). It returns True if the file should be displayed (that is, if its
extension is one that the filter accepts or, usually, if the file corresponds to a directory) and False otherwise. The
getDescription() method returns a string that will be displayed in the file chooser to indicate to the user
what types of files the filter is for.
The MyFilter1 class will accept .gif files (described as Gif Files (*.gif) in this filter) and directories, and
the MyFilter2 class will filter .java files (described as Java Files (*.java) in this filter) and directories.
Heres what these classes look like in code:
import java.io.File;
class MyFilter1 extends javax.swing.filechooser.FileFilter {
public boolean accept(File file) {
String extension = "";
if(file.getPath().lastIndexOf('.') > 0)
extension = file.getPath().substring(
file.getPath().lastIndexOf('.') + 1).toLowerCase();
if(extension != "") { return extension.equals("gif"); }
else { return file.isDirectory(); }
}
public String getDescription() { return "Gif Files (*.gif)"; }
}
class MyFilter2 extends javax.swing.filechooser.FileFilter {
public boolean accept(File file) {
String extension = "";
if(file.getPath().lastIndexOf('.') > 0)
extension = file.getPath().substring(
file.getPath().lastIndexOf('.') + 1).toLowerCase();
if(extension != "") { return extension.equals("java"); }
else { return file.isDirectory(); }
}
519
Chapter 14: SwingCombo Boxes, Progress Bars, Tooltips, Separators, and Choosers
Summary
In this chapter, you have learned about the Swings-based controls, combo boxes, progress bars, separators and
classes for tooltips. In the next chapter, youll learn about the panes and layouts part of Swing.
520
15
SwingLayered Panes,
Tabbed Panes, Split Panes,
and Layouts
If you need an immediate solution to: See page:
Understanding Swing Components and Z-order 523
Making Swing Components Transparent 524
Using Layered Panes 525
Creating Tabbed Panes 527
Specifying Tab Placement in the Tabbed Panes 532
Using Split Panes 535
Making Split Panes One-Touch Expandable 538
Setting Split Pane Orientation 539
Setting Split Pane Divider Size 540
Using the Box Layout Manager 541
Using the Box Class 543
Using the Overlay Layout Manager 547
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
In Depth
In this chapter, well take a look at some of the Swing lightweight containers: layered panes, tabbed panes, and
split panes. Swing provides a number of lightweight containers, including JPanel (which you have already
seen), to let programmers manage components in simple ways. Layered panes let you specify the layer of the
components you add, making it easy to set the Z-order (that is, the stacking order in the Z axis, which points out
of the screen) of components. Tabbed panes let you order the components much like adding them to a collection
of tabbed file folders, and you can click the tabs to open each folder. Finally, split panes let you display two
components side by side and adjust how much of each one is visiblea technique commonly used to support
two views in the same model.
Well also take a look at layouts in this chapter. You first saw the AWT layouts in Chapter 7. Swing supports all
those layouts and two more: box layouts and overlay layouts. Well consider these two new layouts in this
chapter. Box layouts let you create rows or columns of components. Overlay layouts, as the name implies, let
you draw overlapping components. Swing also defines the Box class, which lets you arrange components by
using visual constructs, such as struts, rigid areas, and glue. Youll see all these in this chapter.
Layered Panes
Layered panes, themselves lightweight containers, are important panes of heavyweight Swing containers, such
as JApplet and JFrame. They are divided into a number of vertical layers you can work with, and that Swing
works with as well. This is one of the areas in which the implementation of Swing on top of AWT is not
transparent to the programmer, because you can see the layers that Swing uses to display dialog boxes, drag
components, pop-up menus, and so on. One of the most popular aspects of the layered pane is that its home to
the content pane.
Tabbed Panes
Dialog boxes that let users choose from many options have come to be organized by tabs as programs have
become more complex and offer more options. Setup dialog boxes are customarily implemented this way,
organizing program settings into tabs, such as Display, User Information, General, Files, and so on. Swing
supports tabbed panes to let you create dialog boxes and programs of this kind. As you might expect, all the
Swing capabilities are available here, such as displaying images in the tabs.
Split Panes
Another popular Graphical User Interface (GUI) programming technique today is to let the user split a view into
a models data, thus creating a new view into that data. Word processors often let users split their presentations
into two panes, so they can move around in two areas of a document independently. Swing supports split panes
to let programs present two components side by side. These components can represent views in the same or
separate model data.
Layouts
You first saw the AWT layouts in Chapter 7, and Swing supports those layouts, as well as two more: box layouts
and overlay layouts. Of the two, box layouts are the most popular because they let you arrange components into
vertical and horizontal rows and columns, called boxes. In fact, Swing also supports the Box class, which goes a
step further by letting you specify the spacing and arrangement of components, as youll see in the chapter. The
overlay layout manager lets you overlap components in a well-defined way, and although not as common as
other layout managers, it has its uses.
Thats it for the overview of whats in this chapter. As you can see, theres a lot coming up. Its time to turn to
the Immediate Solutions section, starting with a look at stacking Swing components.
522
Immediate Solutions
Immediate Solutions
Understanding Swing Components and Z-order
Javas gone all wacky again, says the Novice Programmer. I drew some components in the same area of my
program by mistake, and they actually appeared on top of each other! You smile and say, Thats perfectly
possible. In fact, in Swing, its not uncommon to overlap or overlay components. The NP says, Weird!
When you add lightweight components to a content pane, those components are simply drawn on that pane, so
theres nothing to stop you from making those components overlap (that is, as long as you dont use a layout
managerexcept the overlay layout manager, which would stop overlaying from taking place). When
components overlap, their z-order becomes important; z-order represents the relative placement of components
along the z-axis, which goes out of the screen.
The lightweight components you add first will appear on top of those you add later. You can also add
heavyweight AWT components to your program; and those components, which have their own operating
system window, usually appear on top of Swing components.
Heres an example in which we remove the default border layout manager from a content pane and add a series
of overlapping labels, showing that the first added label will appear on top of the rest. Heres what this looks
like in code (note that we add a border to the labels to make the overlapping visible):
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE = DemoZOrder.class
WIDTH = 250
HEIGHT = 200 >
</APPLET>*/
public class DemoZOrder extends JApplet {
JLabel labels[];
public void init() {
Container c = getContentPane();
c.setLayout(null);
labels = new JLabel[5];
labels[0] = new JLabel("First");
labels[0].setOpaque(true);
labels[0].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[0]);
labels[1] = new JLabel("Second");
labels[1].setOpaque(true);
labels[1].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[1]);
labels[2] = new JLabel("Third");
labels[2].setOpaque(true);
labels[2].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[2]);
labels[3] = new JLabel("Fourth");
labels[3].setOpaque(true);
labels[3].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[3]);
labels[4] = new JLabel("Fifth");
labels[4].setOpaque(true);
labels[4].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[4]);
for(int loop_index = 0; loop_index < 5; loop_index++) {
labels[loop_index].setBounds(30 * loop_index, 30
* loop_index, 110, 50); }
}
}
523
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
524
Immediate Solutions
labels[2].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[2]);
labels[3] = new JLabel("Fourth");
labels[3].setOpaque(false);
labels[3].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[3]);
labels[4] = new JLabel("Fifth");
labels[4].setOpaque(false);
labels[4].setBorder(BorderFactory.createEtchedBorder());
c.add(labels[4]);
for(int loop_index = 0; loop_index < 5; loop_index++) {
labels[loop_index].setBounds(30 * loop_index, 30
* loop_index, 110, 50); }
}
}
The result appears in Figure 15.2, where you can see the overlapping transparent labels:
You have already learned about the layered pane in Chapter 11.
525
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
Heres how we add labels to all the layers outlined in the preceding list:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE = DemoLayeredPane.class
WIDTH = 250
HEIGHT = 200 >
</APPLET>*/
public class DemoLayeredPane extends JApplet {
JLayeredPane layeredpane = new JLayeredPane();
JLabel labels[];
public void init() {
setContentPane(layeredpane);
layeredpane.setLayout(null);
labels = new JLabel[6];
labels[0] = new JLabel("Content layer");
labels[0].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[0],
JLayeredPane.FRAME_CONTENT_LAYER.intValue());
layeredpane.add(labels[0]);
labels[1] = new JLabel("Default layer");
labels[1].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[1],
JLayeredPane.DEFAULT_LAYER.intValue());
layeredpane.add(labels[1]);
labels[2] = new JLabel("Palette layer");
labels[2].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[2],
JLayeredPane.PALETTE_LAYER.intValue());
layeredpane.add(labels[2]);
labels[3] = new JLabel("Modal layer");
labels[3].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[3],
JLayeredPane.MODAL_LAYER.intValue());
layeredpane.add(labels[3]);
labels[4] = new JLabel("Popup layer");
labels[4].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[4],
JLayeredPane.POPUP_LAYER.intValue());
layeredpane.add(labels[4]);
labels[5] = new JLabel("Drag layer");
labels[5].setBorder(BorderFactory.createEtchedBorder());
layeredpane.setLayer(labels[5],
JLayeredPane.DRAG_LAYER.intValue());
layeredpane.add(labels[5]);
for(int loop_index = 0; loop_index < 5; loop_index++) {
labels[loop_index].setBounds(30 * loop_index, 30
* loop_index, 110, 50); }
}
}
The result of this code appears as shown in Figure 15.3, where you can see what layer is on top of what other
layer:
526
Immediate Solutions
527
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
528
Immediate Solutions
529
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
An example will make all this information clearer. In this case, we create a tabbed pane with three tabs and give
each tab its own JPanel object with a label in it. The user will be able to move from tab to tab, seeing all the
labels in turn. We start by creating the panels well use:
import java.awt.*;
import javax.swing.*;
/*<APPLET
CODE = DemoTabbedPane.class
WIDTH = 500
HEIGHT = 200 >
</APPLET>*/
public class DemoTabbedPane extends JApplet {
public void init() {
Container c = getContentPane();
JTabbedPane tabbedpane = new JTabbedPane();
JPanel jp1 = new JPanel();
JPanel jp2 = new JPanel();
JPanel jp3 = new JPanel();
jp1.add(new JLabel("First Panel"));
jp2.add(new JLabel("Second Panel"));
jp3.add(new JLabel("Third Panel"));
. . .
Now we are ready to add these panels to a tabbed pane, so we create a new tabbed pane and use the addTab()
method to add three tabs to it. We pass the caption to addTab() method for each tab, the image icon to use in
each tab, the components to add to each tab (which are usually objects of the JPanel class), and a tooltip for
each tab, like this:
tabbedpane.addTab("Tab 1",new ImageIcon("tabb.jpg"),jp1, "First Tab");
tabbedpane.addTab("Tab 2",new ImageIcon("tabb.jpg"),jp2, "Second Tab");
tabbedpane.addTab("Tab 3",new ImageIcon("tabb.jpg"),jp3, "Third Tab");
c.setLayout(new BorderLayout());
c.add(tabbedpane); }
}
The result appears as shown in Figure 15.4:
530
Immediate Solutions
As you can see in the figure, each tab has its own image and caption, as specified to the addTab() method.
Clicking a new tab opens a new folder with a new label in it. Thats all there is to it.
You can do more with tabbed panesspecify the placement you want for the tabs. Here is another example that
will make this information clearer. In this case, we create a tabbed pane with 12 tabs, for months of the year, and
give each tab its own JPanel object with a label in it. The user will be able to move the alignment of tab and the
way tab should be displayed on the frame, seeing all the labels in turn.
import javax.swing.*;
import java.text.*;
import java.awt.*;
public class DemoTabsLayout {
public static void main(String args[]) {
String[] month = new DateFormatSymbols().getShortMonths();
JTabbedPane tabbedpane = new JTabbedPane();
tabbedpane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
for (int i=0; i<12; i++) {
JPanel tabpanel = new JPanel(new BorderLayout());
JButton tabbutton = new JButton(month[i]);
tabpanel.add(tabbutton);
tabbedpane.add(month[i], tabpanel); }
JFrame frm = new JFrame("Tabs Layout");
frm.getContentPane().add(tabbedpane, BorderLayout.CENTER);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setSize(300, 200);
frm.setVisible(true); }
}
The result appears as shown in Figure 15.5:
531
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
Now well make some changes to the previously mentioned code, say we delete the following code statement:
tabbedpane.setTabPlacement(JTabbedPane.LEFT);
and modify the code statement:
tabbedpane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
to:
tabbedpane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
The result of this modification appears in Figure 15.7:
/*
<APPLET
CODE = DemoTabbedPaneOrient.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>
*/
532
Immediate Solutions
tabbedpane.addTab("Panel 3",
new ImageIcon("tabb.jpg"),
jp3, "Third Panel");
button1 = new JButton("Top");
button2 = new JButton("Left");
button3 = new JButton("Right");
button4 = new JButton("Bottom");
buttonPanel.add(button1);
buttonPanel.add(button2);
buttonPanel.add(button3);
buttonPanel.add(button4);
button1.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);
button4.addActionListener(this);
c.setLayout(new BorderLayout());
c.add(tabbedpane, BorderLayout.CENTER);
c.add(buttonPanel, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
tabbedpane.setTabPlacement(JTabbedPane.TOP); }
else if(e.getSource() == button2) {
tabbedpane.setTabPlacement(JTabbedPane.LEFT); }
else if(e.getSource() == button3) {
tabbedpane.setTabPlacement(JTabbedPane.RIGHT); }
else if(e.getSource() == button4) {
tabbedpane.setTabPlacement(JTabbedPane.BOTTOM); }
tabbedpane.validate(); }
}
The result of this code appears as shown in Figure 15.8:
533
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
534
Immediate Solutions
535
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
536
Immediate Solutions
Well put the JSplitPane class to use in an example here. In this case, we add two text fields to a split pane.
Thats easy enough to dowe just create two text fields and a split pane, like this:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE = DemoSplitPane.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>*/
public class DemoSplitPane extends JApplet implements ActionListener {
JTextField textfield1 = new JTextField("TextField 1");
JTextField textfield2 = new JTextField("TextField 2");
JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
textfield1, textfield2);
. . .
If you dont explicitly add components to a split pane, it will display two buttons.
Now we just add the new split pane to the applets content pane as follows:
public class DemoSplitPane extends JApplet implements ActionListener {
JTextField textfield1 = new JTextField("TextField 1");
JTextField textfield2 = new JTextField("TextField 2");
JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
textfield1, textfield2); public void init() {
537
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
Container c = getContentPane();
c.add(splitpane, BorderLayout.CENTER); }
public void actionPerformed(ActionEvent e) { }
}
Thats all it takes. The result of this code appears as shown in Figure 15.10:
You will learn how to use creating scroll panes in Chapter 13 of this book.
538
Immediate Solutions
539
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
c.add(splitpane, BorderLayout.CENTER);
c.add(panel, BorderLayout.SOUTH); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
splitpane.setOneTouchExpandable(true); }
if(e.getSource() == button2) {
splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); }
}
}
The result of this code appears as shown in Figure 15.12:
540
Immediate Solutions
c.add(panel, BorderLayout.SOUTH); }
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
splitpane.setOneTouchExpandable(true); }
if(e.getSource() == button2) {
splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); }
if(e.getSource() == button3) {
splitpane.setDividerSize(splitpane.getDividerSize() + 5);
}
}
}
The result appears as shown in Figure 15.13:
541
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
Heres an example in which we arrange three panels using box layoutstwo vertically and one horizontally
and add four text fields to each panel. This simply entails using a new box layout manager in each panel
like this:
import java.awt.*;
import javax.swing.*;
/* <APPLET
CODE = DemoBoxLayout.class
WIDTH = 400
HEIGHT = 200 >
</APPLET>*/
public class DemoBoxLayout extends JApplet {
public void init() {
Container c = getContentPane();
JPanel panel1, panel2, panel3;
panel1 = new JPanel();
panel2 = new JPanel();
panel3 = new JPanel();
panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));
panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS));
panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS));
c.setLayout(new FlowLayout());
panel1.add(new JTextField("TextField 1"));
panel1.add(new JTextField("TextField 2"));
panel1.add(new JTextField("TextField 3"));
panel1.add(new JTextField("TextField 4"));
panel2.add(new JTextField("TextField 1"));
panel2.add(new JTextField("TextField 2"));
panel2.add(new JTextField("TextField 3"));
panel2.add(new JTextField("TextField 4"));
panel3.add(new JTextField("TextField 1"));
panel3.add(new JTextField("TextField 2"));
panel3.add(new JTextField("TextField 3"));
panel3.add(new JTextField("TextField 4"));
c.add(panel1);
c.add(panel2);
c.add(panel3); }
}
542
Immediate Solutions
The result appears in Figure 15.14, where you can see the three box layouts:
543
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
544
Immediate Solutions
Heres an example using the Box class. In this case, we use the createGlue(), createRigidArea(),
createHorizontalStrut(), and createVerticalStrut() methods of the Box class to create glue, rigid
areas, and struts. These components can be added to box layouts, so well create six panels, each with a box layout,
and add text areas to the panels using glue, struts, and rigid areas to show how all this works. Heres the code:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
/*<APPLET
CODE = DemoBox.class
WIDTH = 550
HEIGHT = 350 >
</APPLET>*/
public class DemoBox extends JApplet {
public void init() {
Container c = getContentPane();
c.setLayout(new FlowLayout());
JPanel panel1 = new JPanel();
panel1.setBorder(
BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Glue"));
panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS));
panel1.add(Box.createGlue());
panel1.add(new JTextField("TextField 1"));
panel1.add(Box.createGlue());
panel1.add(new JTextField("TextField 2"));
panel1.add(Box.createGlue());
panel1.add(new JTextField("TextField 3"));
panel1.add(Box.createGlue());
c.add(panel1);
JPanel panel2 = new JPanel();
panel2.setBorder(
BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Struts"));
panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS));
panel2.add(new JTextField("TextField 1"));
panel2.add(Box.createHorizontalStrut(20));
panel2.add(new JTextField("TextField 2"));
panel2.add(Box.createHorizontalStrut(20));
panel2.add(new JTextField("TextField 3"));
c.add(panel2);
JPanel panel3 = new JPanel();
panel3.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(), "Rigid"));
panel3.setLayout(new BoxLayout(panel3, BoxLayout.X_AXIS));
panel3.add(Box.createRigidArea(new Dimension(10, 40)));
panel3.add(new JTextField("TextField 1"));
panel3.add(Box.createRigidArea(new Dimension(10, 40)));
panel3.add(new JTextField("TextField 2"));
panel3.add(Box.createRigidArea(new Dimension(10, 40)));
panel3.add(new JTextField("TextField 3"));
545
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
c.add(panel3);
JPanel panel4 = new JPanel();
panel4.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(),"Glue"));
panel4.setLayout(new BoxLayout(panel4, BoxLayout.Y_AXIS));
panel4.add(Box.createGlue());
panel4.add(new JTextField("TextField 1"));
panel4.add(Box.createGlue());
panel4.add(new JTextField("TextField 2"));
panel4.add(Box.createGlue());
panel4.add(new JTextField("TextField 3"));
panel4.add(Box.createGlue());
c.add(panel4);
JPanel panel5 = new JPanel();
panel5.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(), "Struts"));
panel5.setLayout(new BoxLayout(panel5, BoxLayout.Y_AXIS));
panel5.add(new JTextField("TextField 1"));
panel5.add(Box.createVerticalStrut(30));
panel5.add(new JTextField("TextField 2"));
panel5.add(Box.createVerticalStrut(30));
panel5.add(new JTextField("TextField 3"));
c.add(panel5);
JPanel panel6 = new JPanel();
panel6.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(), "Rigid"));
panel6.setLayout(new BoxLayout(panel6, BoxLayout.Y_AXIS));
panel6.add(Box.createRigidArea(new Dimension(40, 60)));
panel6.add(new JTextField("TextField 1"));
panel6.add(Box.createRigidArea(new Dimension(40, 60)));
panel6.add(new JTextField("TextField 2"));
panel6.add(Box.createRigidArea(new Dimension(40, 60)));
panel6.add(new JTextField("TextField 3"));
c.add(panel6); }
}
The result of this code appears as shown in Figure 15.15:
546
Immediate Solutions
Heres how you use an overlay layout. In this kind of a layout, you add components to a container so that their
alignment points are at the same location. Each of these components also has an alignment attribute between 0.0
and 1.0, which you set with the setAlignmentX() and setAlignmentY() methods (the default value is 0.5).
These specify where the alignment point is in each dimension. For example, an x alignment attribute of 0.5 refers
to the center of the component in the x direction.
After you set the minimum, maximum, and preferred size of the components, the overlay layout manager
attempts to resize the components, so their alignment points overlap, and it maintains that overlap, if possible,
even when the container is resized.
Lets look at an example to make this clearer. In this case, we overlap two text fields, specify their minimum,
maximum, and preferred sizes, and set their alignment points, so one component will appear in the upper left
and the other in the lower right. Heres the code:
import java.awt.*;
import javax.swing.*;
547
Chapter 15: SwingLayered Panes, Tabbed Panes, Split Panes, and Layouts
/*<APPLET
CODE = DemoOverlayLayout.class
WIDTH = 300
HEIGHT = 300 >
</APPLET>*/
public class DemoOverlayLayout extends JApplet {
public void init() {
Container c = getContentPane();
JPanel panel = new JPanel();
panel.setLayout(new OverlayLayout(panel));
panel.setBackground(Color.white);
panel.setBorder(
BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
"Overlay Layout"));
JTextField textfield1 = new JTextField("TextField 1");
JTextField textfield2 = new JTextField("TextField 2");
textfield1.setMinimumSize(new Dimension(35, 35));
textfield2.setMinimumSize(new Dimension(35, 35));
textfield1.setPreferredSize(new Dimension(120, 120));
textfield2.setPreferredSize(new Dimension(120, 120));
textfield1.setMaximumSize(new Dimension(140, 140));
textfield2.setMaximumSize(new Dimension(140, 140));
textfield1.setAlignmentX(0.3f);
textfield1.setAlignmentY(0.3f);
textfield2.setAlignmentX(0.9f);
textfield2.setAlignmentY(0.9f);
panel.add(textfield1);
panel.add(textfield2);
c.setLayout(new FlowLayout());
c.add(panel); }
}
The result appears as shown in Figure 15.16, where you can see the two overlapped text fields:
Summary
In this chapter, you have learned about different panes such as layered, tabbed, and split. You have also come
across how to make split panes one-touch expandable, set split pane orientation, use of box layout manager, and
the Box class. Lastly, we discussed use of overlay layout manager.
In the next chapter, youll learn about the menus and toolbars put a dash instead an important part of any
application.
548
16
SwingMenus
and Toolbars
If you need an immediate solution to: See page:
Creating a Menu Bar 551
Creating a Menu 552
Creating a Menu Item 555
Creating a Basic Menu System 557
Adding Images to Menu Items 559
Creating Checkbox Menu Items 560
Creating Radio Button Menu Items 562
Creating Submenus 564
Creating Menu Accelerators 565
Enabling/Disabling and Changing Menu Items at Runtime 567
Adding and Removing Menu Items at Runtime 568
Adding Buttons and Other Controls to Menus 569
Creating Pop-Up Menus 570
Creating Toolbars 574
Adding Combo Boxes and Other Controls to Toolbars 576
549
Chapter 16: SwingMenus and Toolbars
In Depth
In this chapter, well cover two of the most important Swing componentsmenus and toolbars. Both of these
components are familiar to all GUI users, and youll see how to work with them in Swing. Lets see first what
Swing has to offer here in the overview itself.
Menus
Swing menus provide some substantial improvements over AWT menus, such as the ability to display images,
the ability to set a menu items look and feel, and, notably, the ability to display menus in applet windows.
Swing menus are supported by the JMenuBar, JMenu, and JMenuItemclasses, which support menu bars,
menus, and menu items, respectively. As in AWT, Swing menus are actually built by using buttons behind the
scenes, so you can use action listeners with them.
In this chapter, well take a look at what Swing menus have to offer, including creating basic menus, adding
images to menu items, creating checkbox and radio button menu items and submenus, adding controls such as
buttons to menus, creating menu accelerators and mnemonics, and more. Well also take a look at creating pop-
up menus here. Swing menus are more complex and powerful than their AWT components, as youll see.
Toolbars
Toolbars are popular GUI controls, and they are new in Swing. Like menus, toolbars are built by the use of
buttons in Swing. They provide a bar of buttons that are clickable, just like menu items. In fact, toolbars and
menus are closely related youll often add buttons to toolbars that represent popular menu items to save the
user from the trouble of opening a menu.
Well know about Swing toolbars, which are supported by the JtoolBar class, including adding images to
toolbar buttons, letting the user align the toolbar against any edge of a window, and adding other controls, such
as combo boxes, to toolbars.
Thats it for the overview of whats in this chapter. As you can see, theres a lot coming up. Its time to turn to
the Immediate Solutions section, which starts with a look at stacking Swing components.
550
Immediate Solutions
Immediate Solutions
Creating a Menu Bar
The Novice Programmer appears and says, The Big Boss says I need to add a menu system to my program.
How in the world do I do that? With three components: you say, menu bars, menus, and menu items. Get
some coffee and well start with menu bars. OK, the NP says.
To add a menu system to a Swing program, you must first create a menu bar using the JmenuBar class. You
can add the menu bar to applets or frame windows with the setJMenuBar()method. Heres the inheritance
diagram for the JmenuBar class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JMenuBar
You can find the constructor for JmenuBar in Table 16.1 and its methods in Table 16.2:
Table 16.1: The constructor of the JMenuBar class
Constructor Does this
JMenuBar() It constructs a new menu bar
551
Chapter 16: SwingMenus and Toolbars
Well put the JmenuBar class to work upon the next few solutions while creating a basic menu system. The
next step is to create menus to add to the menu bar, and well do that in the next solution.
Creating a Menu
The NP is back and says, I have created a menu bar, but nothing appears in itwhats up? You smile and say,
You have got to add menus to it explicitly. Ah, says the NP, now you can show me how that works.
You create the menus in a menu bar with the Jmenu class. Heres the inheritance diagram for that class (note
that Jmenu is actually subclassed from JMenuItem, which is the case because JMenuItem, which is subclassed
from AbstractButton, can respond to button clicks):
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.AbstractButton
|____javax.swing.JMenuItem
|____javax.swing.JMenu
Youll find the field of the JMenuclass in Table 16.3, its constructors in Table 16.4, and its methods in Table 16.5:
Table 16.3: The field of the JMenu class
Field Does this
protected It is the pop-ups window-closing listener
JMenu.WinListenerpopupListener
552
Immediate Solutions
553
Chapter 16: SwingMenus and Toolbars
When you have created menus by using the JMenu class, you populate those menus with menu items (see the
next solution for the details).
554
Immediate Solutions
555
Chapter 16: SwingMenus and Toolbars
As you can see in Tables 16.6 and 16.7, the JMenuItem class has a lot to offerfor example, you can determine
whether a menu item is armed (that is, it will be selected if the user releases the mouse) with the
isArmed()and setArmed()methods.
This one and the previous two solutions have introduced menu bars, menus, and menu items in Swing; well put
these elements together in the next solution to create a basic menu system.
556
Immediate Solutions
557
Chapter 16: SwingMenus and Toolbars
558
Immediate Solutions
Thats all to create a basic menu system. Working with menus in Swing is much like working with them in AWT,
with the obvious difference that applet windows in AWT cant display menus. The result of this code appears as
shown in Figure 16.1, where you can see the menu system at work.
559
Chapter 16: SwingMenus and Toolbars
jmenu2.add(jmenuitem4);
jmenu2.add(jmenuitem5);
jmenu2.add(jmenuitem6);
jmenuitem4.setActionCommand("You selected Cut");
jmenuitem5.setActionCommand("You selected Copy");
jmenuitem6.setActionCommand("You selected Paste");
jmenuitem4.addActionListener(this);
jmenuitem5.addActionListener(this);
jmenuitem6.addActionListener(this);
jmenubar.add(jmenu1);
jmenubar.add(jmenu2);
setJMenuBar(jmenubar);
setJMenuBar(jmenubar);
}
public void actionPerformed(ActionEvent e) {
JMenuItem jmenuitem = (JMenuItem)e.getSource();
showStatus(jmenuitem.getActionCommand()); }
}
The result appears as shown in Figure 16.2:
560
Immediate Solutions
Lets look at an example. In this case, we add four checkbox items to a menu by using the JCheckBoxMenuItem
class. Heres how we create and add those items to a menu (note that action listeners can be used with checkbox
menu items):
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = MenuCheckBox.class
WIDTH = 350
HEIGHT = 280 >
</APPLET>*/
public class MenuCheckBox extends JApplet implements ActionListener {
JCheckBoxMenuItem
jcheckboxmenuitem1 = new JCheckBoxMenuItem("MBA"),
jcheckboxmenuitem2 = new JCheckBoxMenuItem("MCA"),
jcheckboxmenuitem3 = new JCheckBoxMenuItem("BTECH"),
jcheckboxmenuitem4 = new JCheckBoxMenuItem("MTECH");
public void init() {
Container contentPane = getContentPane();
JMenuBar jmbar = new JMenuBar();
JMenu jmenu = new JMenu("COURSES");
jcheckboxmenuitem1.addActionListener(this);
jcheckboxmenuitem2.addActionListener(this);
jcheckboxmenuitem3.addActionListener(this);
jcheckboxmenuitem4.addActionListener(this);
jmenu.add(jcheckboxmenuitem1);
jmenu.add(jcheckboxmenuitem2);
jmenu.add(jcheckboxmenuitem3);
jmenu.add(jcheckboxmenuitem4);
jmbar.add(jmenu);
561
Chapter 16: SwingMenus and Toolbars
setJMenuBar(jmbar);
}
...
}
When the user clicks a checkbox item, we list the state of all four items as follows:
public void actionPerformed(ActionEvent e) {
showStatus("MBA: " + jcheckboxmenuitem1.getState() +
" MCA: " + jcheckboxmenuitem2.getState() +
" BTECH: " + jcheckboxmenuitem3.getState() +
" MTECH: " + jcheckboxmenuitem4.getState());
}
Thats all it takes. The result of this code appears as shown in Figure 16.3:
562
Immediate Solutions
Lets look at an example. In this case, we add four radio buttons to a menu and add an item listener to indicate
when each radio button is selected or deselected. Heres what the code looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = MenuRadioButton.class
WIDTH = 350
HEIGHT = 280 >
</APPLET>*/
public class MenuRadioButton extends JApplet implements ItemListener {
JRadioButtonMenuItem
jradiobuttonmenuitem1 = new JRadioButtonMenuItem("Uttar Pradesh"),
jradiobuttonmenuitem2 = new JRadioButtonMenuItem("Delhi"),
jradiobuttonmenuitem3 = new JRadioButtonMenuItem("Assam"),
jradiobuttonmenuitem4 = new JRadioButtonMenuItem("Chennai");
public void init() {
Container contentPane = getContentPane();
JMenuBar jmenubar = new JMenuBar();
JMenu jmenu = new JMenu("Radio Button Menu Items");
jmenu.add(jradiobuttonmenuitem1);
jmenu.add(jradiobuttonmenuitem2);
jmenu.add(jradiobuttonmenuitem3);
jmenu.add(jradiobuttonmenuitem4);
ButtonGroup group = new ButtonGroup();
group.add(jradiobuttonmenuitem1);
group.add(jradiobuttonmenuitem2);
group.add(jradiobuttonmenuitem3);
group.add(jradiobuttonmenuitem4);
jradiobuttonmenuitem1.addItemListener(this);
jradiobuttonmenuitem2.addItemListener(this);
jradiobuttonmenuitem3.addItemListener(this);
jradiobuttonmenuitem4.addItemListener(this);
jmenubar.add(jmenu);
setJMenuBar(jmenubar); }
public void itemStateChanged(ItemEvent e) {
JMenuItem jmenuitem = (JMenuItem) e.getSource();
String itemtext = jmenuitem.getText();
if(e.getStateChange() == ItemEvent.SELECTED)
itemtext += " was selected";
else
itemtext += " was deselected";
563
Chapter 16: SwingMenus and Toolbars
showStatus(itemtext); }
}
The result of this code appears as shown in Figure 16.4, where you can see the radio buttons in the menu
at work:
Creating Submenus
My menus are getting too big, the NP says. I want to let the user select the drawing color in my program by
selecting menu items, but all the colors are crowding out the other items in the menu. You should try putting
all the colors into a submenu, you say. How many colors do you want to display? About 3,000, says the NP.
You say, Uh-oh.
Submenus, also called cascading menus, are menus you open from other menus. Swing indicates that a menu item
is actually a submenu by adding a clickable arrow to the right of the menu item; when the user clicks the arrow,
the submenu opens.
You can create submenus easily in Swing. All you do to create a new menu is add items to the menu and then
add the menu itself as an item in another menu. Heres an example to make this clearer. In this case, we add four
menu items and three submenu items. Heres what this looks like in code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = SubMenus.class
WIDTH = 350
HEIGHT = 280 >
</APPLET>*/
public class SubMenus extends JApplet
{
public void init()
{
JMenuBar jmenubar = new JMenuBar();
JMenu jm = new JMenu("Sub Menus", true);
JMenu jsubmenu = new JMenu("Cascading Menu", true);
jm.add("Item 1");
jm.add("Item 2");
jm.add("Item 3");
jsubmenu.add("Sub Item a");
jsubmenu.add("Sub Item b");
jsubmenu.add("Sub Item c");
564
Immediate Solutions
jm.add(jsubmenu);
jmenubar.add(jm);
setJMenuBar(jmenubar);
}
}
The result of this code appears, as shown in Figure 16.5:
565
Chapter 16: SwingMenus and Toolbars
You can use the virtual key constants defined in the KeyEventclassKeyEvent.VK_A,KeyEvent.VK_ENTER,
and KeyEvent.VK_TABto specify the keycode when creating a KeyStroke object. The modifiers you can
specify can be any combination of the following:
InputEvent.SHIFT_DOWN_MASK
InputEvent.CTRL_DOWN_MASK
InputEvent.META_DOWN_MASK
InputEvent.ALT_DOWN_MASK
InputEvent.ALT_GRAPH_DOWN_MASK
Well put this together in an example. In this case, we add a mnemonic, the letter C to the Copyitem in the Edit
menu and give it the accelerator Ctrl+C. Heres how that looks in code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = MenuAccelerator.class
WIDTH = 350
HEIGHT = 280 >
</APPLET>*/
public class MenuAccelerator extends JApplet implements ActionListener {
public void init() {
Container contentPane = getContentPane();
JMenuBar jmenubar = new JMenuBar();
JMenu jmenu = new JMenu("Edit");
JMenuItem jmenuitem = new JMenuItem("Copy...");
jmenu.add(jmenuitem);
jmenu.add("Open ...");
jmenuitem.setMnemonic(KeyEvent.VK_C);
KeyStroke keystroke = KeyStroke.getKeyStroke(KeyEvent.VK_C,
Event.CTRL_MASK);
jmenuitem.setAccelerator(keystroke);
jmenuitem.addActionListener(this);
jmenubar.add(jmenu);
setJMenuBar(jmenubar); }
public void actionPerformed(ActionEvent e) {
showStatus("You selected the Copy item."); }
}
The result is shown in Figure 16.6, where you see the accelerator (Ctrl+C) in the Copy menu item:
566
Immediate Solutions
menu2.add(jmenuitem4);
menu2.add(jmenuitem5);
menu2.add(jmenuitem6);
jmenuitem4.addActionListener(this);
jmenuitem5.addActionListener(this);
jmenuitem6.addActionListener(this);
jmenubar.add(menu1);
jmenubar.add(menu2);
setJMenuBar(jmenubar); }
567
Chapter 16: SwingMenus and Toolbars
You shouldnt disable too many menu items at oncedoing so gives your program an inaccessible feel.
menu2.add(jmenuitem5);
jmenuitem4.setActionCommand("You selected Font");
jmenuitem4.addActionListener(this);
jmenuitem5.setActionCommand("You selected Font");
jmenuitem5.addActionListener(this);
jmenubar.add(menu1);
jmenubar.add(menu2);
setJMenuBar(jmenubar); }
public void actionPerformed(ActionEvent e) {
JMenuItem jmenuitem = (JMenuItem)e.getSource();
if(jmenuitem == jmenuitem4) { menu2.add(jmenuitem6); }
if(jmenuitem == jmenuitem5) { menu2.remove(jmenuitem6); }
}
}
The result of this code appears as shown in Figure 16.8, where you can see the new item added when the user
clicks Add item:
569
Chapter 16: SwingMenus and Toolbars
menu1.addSeparator();
menu1.add(jbutton);
menu1.addSeparator();
menu1.add(jmenuitem3);
JMenu jmenu2 = new JMenu("Edit");
JMenuItem jmenuitem4 = new JMenuItem("Cut"),
jmenuitem5 = new JMenuItem("Copy"),
jmenuitem6 = new JMenuItem("Paste");
jmenu2.add(jmenuitem4);
jmenu2.add(jmenuitem5);
jmenu2.add(jmenuitem6);
jmenubar.add(menu1);
jmenubar.add(jmenu2);
setJMenuBar(jmenubar); }
public void actionPerformed(ActionEvent e) {
JButton jbutton = (JButton)e.getSource();
showStatus(jbutton.getActionCommand()); }
}
The result of this code appears in Figure 16.9:
570
Immediate Solutions
571
Chapter 16: SwingMenus and Toolbars
You create pop-up menus, add new items to them with the add() method, and then display them with the
show() method.
Lets look at an example. In this case, we create a pop-up menu with three items in itFind, Find Next, and
Replacewhich will appear when the user right-clicks with the mouse. A pop-up menu needs to be the child of
some other component, so well add a text field to an applet and cover the applet with the text field. Heres what
creating the text field and the pop-up menu looks like in code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = PopUp.class
WIDTH = 350
572
Immediate Solutions
...
}
Now when the user clicks a mouse button, we can check whether the right mouse button was clicked by using
the MouseEventclasss getModifiers() method and the mask for the right mouse button
InputEvent.BUTTON3_MASK. If the right mouse button was indeed clicked, well show the new pop-up menu
at the mouse location, like this:
public void mousePressed (MouseEvent e)
{
if((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
jpopupmenu.show(jtextfield, e.getX(), e.getY());
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
The result appears as shown in Figure 16.10:
573
Chapter 16: SwingMenus and Toolbars
Creating Toolbars
Menus are fine, says the NP, but sometimes Im working too fast to use them, so I have got a lot of menu
accelerators in my program. But now I keep forgetting them. You smile and say, Have you tried adding a
toolbar?
Toolbars display buttons and other controls that represent common actions in your program, such as saving a
file or pasting the contents of the clipboard. Buttons in a toolbar often represent frequently used menu items in
your menu system. In Swing, you use the JToolBar class to create toolbars. Heres the inheritance diagram for
the JToolBar class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JToolBar
You can find the constructors for the JToolBarclass in Table 16.15 and its methods in Table 16.16:
Table 16.15: Constructors of the JToolBar class
Constructor Does this
JToolBar() It constructs a new toolbar
JToolBar(int orientation) It constructs a new toolbar with the given orientation
JToolBar(String name) It creates a new tool bar with the specified name
JToolBar(String name, int orientation) It creates a new tool bar with a specified name and orientation
574
Immediate Solutions
Heres an example in which we add a toolbar with two buttons to a program. Note that in many ways, a toolbar
just acts as a component that contains other components you have to add it to the layout of your program
where you want it. However, when you have done that, the user can grasp the toolbar handle, which appears on
the left in toolbars, and realign the toolbar against any edge of the window it appears in. In fact, the user can
simply leave the toolbar floating in mid space, not aligned against any edge of the window at all.
In the code for this example, we simply use the JToolBar classs add()method to add two buttons to a
toolbar, and we use its addSeparator()method to add some space between the buttons. We also add code to
make the applet display which of the toolbar buttons the user has clicked, and we add the toolbar to the north
section of the content panes border layout. Heres the code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = ToolBar.class
WIDTH = 500
HEIGHT = 280 >
</APPLET>*/
public class ToolBar extends JApplet implements ActionListener{
JButton jbutton1 = new JButton("Button 1", new ImageIcon("bulg2.jpg"));
JButton jbutton2 = new JButton("Button 2", new ImageIcon("bulg2.jpg"));
JButton setrollbutton = new JButton("Set Rollover");
JToolBar jtoolbar = new JToolBar();
JToolBar setrollover = new JToolBar();
public void init(){
Container contentPane = getContentPane();
jbutton1.addActionListener(this);
jbutton2.addActionListener(this);
setrollbutton.addActionListener(this);
jtoolbar.add(jbutton1);
jtoolbar.addSeparator();
jtoolbar.add(jbutton2);
setrollover.add(setrollbutton);
contentPane.add(jtoolbar, BorderLayout.NORTH);
contentPane.add(setrollover, BorderLayout.SOUTH);
jtoolbar.setFloatable(false);
jtoolbar.setRollover(false);}
public void actionPerformed(ActionEvent e){
if(jtoolbar.isRollover()){
if(e.getSource() == jbutton1){
showStatus("You clicked button 1"); }
else if (e.getSource() == jbutton2){
575
Chapter 16: SwingMenus and Toolbars
}
}
The result of this code is shown in Figure 16.11, where you can see the two buttons in the toolbar, placed on the
top of the screen, and one button in the toolbar, placed at the bottom of the screen:
576
Immediate Solutions
ImageIcon("bulg2.jpg"));
JButton jbutton2 = new JButton("Button 2", new
ImageIcon("bulg2.jpg"));
JComboBox jcombobox = new JComboBox();
public void init(){
Container contentPane = getContentPane();
JToolBar jtoolbar = new JToolBar();
jbutton1.addActionListener(this);
jbutton2.addActionListener(this);
jcombobox.addItem("Item 1");
jcombobox.addItem("Item 2");
jcombobox.addItem("Item 3");
jcombobox.addItem("Item 4");
jcombobox.addItemListener(this);
jtoolbar.add(jbutton1);
jtoolbar.addSeparator();
jtoolbar.add(jbutton2);
jtoolbar.addSeparator();
jtoolbar.add(jcombobox);
contentPane.add(jtoolbar, BorderLayout.NORTH);}
...
}
When the user selects an item in the combo box, we display that item in the status bar:
public void actionPerformed(ActionEvent e){
if(e.getSource() == jbutton1) {showStatus("You clicked button 1");}
else if (e.getSource() == jbutton2) {showStatus("You clicked button 2");}
}
public void itemStateChanged(ItemEvent e){
String outString = "";
if(e.getStateChange() == ItemEvent.SELECTED)
outString += "Selected: " + (String)e.getItem();
else
outString += "Deselected: " + (String)e.getItem();
showStatus(outString);
}
The result of this code appears as shown in Figure 16.12:
577
Chapter 16: SwingMenus and Toolbars
When the user clicks an item in the combo box, the applet will display that item in the status bar.
Summary
In this chapter, you have read about the menu and toolbars. You have also learned how to create a menu bar and
add images to the menu, create toolbars with combo boxes and other controls.
In the next chapter, youll come across different windows, desktop panes, and dialog boxes.
578
17
SwingWindows,
Desktop Panes, Inner
Frames, and Dialog Boxes
If you need an immediate solution to: See page:
Creating a Window 581
Designing Shaped and Translucent Windows 583
Creating a Frame Window 588
Creating a Desktop Pane 589
Creating Internal Frames 591
Using JOptionPane to Create Dialog Boxes 598
Creating Option Pane Confirmation Dialog Boxes 604
Creating Option Pane Message Dialog Boxes 605
Creating Option Pane Text Field Input Dialog Boxes 606
Creating Option Pane Combo Box Input Dialog Boxes 608
Creating Option Pane Internal Frame Dialog Boxes 609
Creating Dialog Boxes with JDialog 609
Getting Input from Dialog Boxes Created with JDialog 613
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
In Depth
In this chapter, well take a look at handling all kinds of windows in Swing. Well cover how to work with the
JWindow, JFrame, JDesktopPane, JInternalFrame, JOptionPane, and JDialog classes. These classes can
be conveniently broken down into two categorieswindows and dialog boxes.
Windows
The JWindow and JFrame classes are the counterparts of the AWT Window and Frame classes, and they serve
the same purpose. You can use the JWindow class to create a simple window thats, in fact, nothing more than a
blank rectangle. Although, you can add borders and controls to JWindow objects, you usually use the JFrame
class to create windows that you present to the user.
The JDesktopPane and JInternalFrame classes are new in Swing, although together they represent
something thats become common in GUIsa multipledocument interface. Objects of the JDesktopPane
class present a space in which you can display multiple internal frames of the JInternalFrame class. For
example, a word processor application may let the user open several views into the same document, or multiple
documents, using a desktop with a number of internal frame windows. Internal frames are lightweight, drawn
windows that appear inside the other windows. In fact, desktop panes are lightweight components, too, derived
from JLayeredPane, and you can add internal frame windows to the layers, you select, of a desktop pane.
Dialog Boxes
Swing provides a lot of support for dialog boxes with the JOptionPane class. Using the methods of this class,
you can display all kinds of dialog boxesmessage dialog boxes, confirmation dialog boxes, input dialog boxes,
and more. As youll see here, its easy to create dialog boxes by using JOptionPane.
In addition to JOptionPane, Swing also has the JDialog class, which you can use as the foundation of your
own custom dialog box class. Well cover how to use both JOptionPane and JDialog in this chapter in depth.
Thats it for the overview of whats in this chapter. As you can see, theres a lot coming up. Its time to turn to
the Immediate Solutions section, starting with a look at the JWindow class.
580
Immediate Solutions
Immediate Solutions
Creating a Window
The Novice Programmer appears and says, I want to create an entirely customized window in my program.
For that, you say, you need the JWindow class, which displays an entirely blank window. OK, says the NP,
can you code it for me?
The JWindow class is much like the AWT Window class because it displays a blank window that you can
customize as you like. In fact, JWindow objects are so unadorned that youll generally use the JFrame class
instead. However, if you really need simplicity, JWindow is the place to start. Heres the inheritance diagram for
this class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____java.awt.Window
|____javax.swing.JWindow
You can find the constructors for JWindow in Table 17.1 and its methods in Table 17.2:
Table 17.1: Constructors of the JWindow class
Constructor Does this
JWindow() It constructs a window
JWindow(Frame owner) It constructs a window with the indicated owner frame
JWindow It constructs a window with the specified
(GraphicsConfiguration gc) GraphicsConfiguration of a screen device
JWindow(Window owner) It constructs a window with the indicated owner window
JWindow(Window owner, It constructs a window with the specified owner window and
GraphicsConfiguration gc) GraphicsConfiguration of a screen device
581
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
When you create a JWindow object, you can add a border to it with the root panes setBorder() method,
show the window with the setVisible(true) method, hide it with the setVisible(false) method, and
get rid of it with the dispose() method. Note that the default layout in a JWindow object is a border layout.
Well create a JWindow object now for example. In this case, we add a button to an applet and display the
window when that button is clicked. We also add a border to the window and a button that, when clicked, will
dispose of the window. Note that JWindow objects have content panes just like other windows, so we add the
button to that pane. Also note that before a window can be displayed, it must be given a size, which we do here
with the setBounds() method. Heres the code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
CODE = Window.class
WIDTH = 350
HEIGHT = 280 >
</APPLET> */
public class Window extends JApplet implements ActionListener {
JWindow jwindow = new JWindow();
public void init() {
Container contentPane = getContentPane();
JButton jbutton = new JButton("Display window");
JButton jwindowbutton = new JButton("Close");
contentPane.setLayout(new FlowLayout());
contentPane.add(jbutton);
jwindow.getRootPane().setBorder(
BorderFactory.createRaisedBevelBorder() );
Container windowContentPane = jwindow.getContentPane();
windowContentPane.setLayout(new FlowLayout());
windowContentPane.add(jwindowbutton);
jwindowbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jwindow.dispose(); } });
jbutton.addActionListener(this); }
public void actionPerformed(ActionEvent e) {
582
Immediate Solutions
Although in this example, we pass numeric values to the windows setBounds() method, you can also set the location of the
window with respect to its parent window. First, you can get the location of the applet windows content pane like this: Point loc
= contentPane.getLocation(). This point is in local coordinates, so you can convert it into screen coordinates, like this:
SwingUtilities.convertPointToScreen(loc, contentPane). Then you are free to use loc with setBounds().
583
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
The steps required to implement the code using per-pixel translucency are as follows:
1. Invoke setBackground (new Color(0,0,0,0)) on the window.
2. Create a JPanel instance that overrides the paintComponent() method.
3. Create a GradientPaint instance in the paintComponent() method.
The GradientPaint class smoothly estimates the alpha values from the top to the bottom of the rectangle.
4. Set the GradientPaint instance as the panel's paint() method.
The code for designing per-pixel translucent window is as follows:
import java.awt.*;
import javax.swing.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
public class PerPixelTranslucentWindowEg extends JFrame {
public PerPixelTranslucentWindowEg () {
super("Per-Pixel Translucent Window");
setBackground(new Color(0,0,0,0));
setSize(new Dimension(300,200));
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
if (g instanceof Graphics2D) {
final int R = 240;
final int G = 240;
final int B = 240;
Paint p =
new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0),
0.0f, getHeight(), new Color(R, G, B, 255), true);
Graphics2D g2d = (Graphics2D)g;
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
};
setContentPane(panel);
setLayout(new GridBagLayout());
add(new JButton("kogent"));
}
public static void main(String[] args) {
// Determine what the GraphicsDevice can support.
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
boolean isPerPixelTranslucencySupported =
gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);
//If translucent windows aren't supported, exit.
if (!isPerPixelTranslucencySupported) {
System.out.println(
"Per-pixel translucency is not supported");
System.exit(0);
}
JFrame.setDefaultLookAndFeelDecorated(true);
// Create the GUI on the event-dispatching thread
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PerPixelTranslucentWindowEg gtw = new
PerPixelTranslucentWindowEg ();
// Display the window.
gtw.setVisible(true);
}
585
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
});
}
}
The result for the preceding program of per-pixel translucent window is shown in Figure 17.3:
586
Immediate Solutions
setUndecorated(true);
setSize(300,200);
587
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new JButton("I am a Button"));
}
588
Immediate Solutions
We have been using the JFrame class as the foundation of Swing applications, so you are already familiar with
this class. We are including it in this chapter on windows and dialog boxes for completeness.
Heres a quick example of using a JFrame window in which we add a panel to the window and then draw in
the panel and add a text field to it. Because JFrame windows are used as the basis of Swing applications. Heres
the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class JFrameDemo extends JFrame {
jpanel j;
public JFrameDemo() {
super("Here is the window");
Container contentPane = getContentPane();
j = new jpanel();
contentPane.add(j); }
public static void main(String args[]) {
final JFrame f = new JFrameDemo();
f.setBounds(100, 100, 300, 300);
f.setVisible(true);
f.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0); } });
}
}
class jpanel extends JPanel {
JTextField jtextfield = new JTextField("Kogent Solutions!");
jpanel() {
setBackground(Color.pink);
add(jtextfield); }
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawString(" Welcome to Kogent Learning Solutions!", 60, 80);
}
}
You can see the result of this code in Figure 17.6:
589
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
The Swing desktop pane mimics a desktop and allows you to display multiple objects on it. In the next solution,
well add inner frame windows to a desktop pane. Heres the inheritance diagram for the JDesktopPane class,
which the class Swing uses to support desktop panes:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JLayeredPane
|____javax.swing.JDesktopPane
Youll find the constructor of the JDesktopPane class in Table 17.3 and its methods in Table 17.4:
Table 17.3: The constructor of the JDesktopPane class
Constructor Does this
JDesktopPane() It constructs a new JDesktopPane
Heres an example in which we just add a desktop pane to an applets content pane. The code looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/* <APPLET
590
Immediate Solutions
CODE = DesktopFrame.class
WIDTH = 350
HEIGHT = 280>
</APPLET> */
public class DesktopFrame extends JApplet {
JDesktopPane jdesktoppane = new JDesktopPane();
public void init() {
Container contentPane = getContentPane();
contentPane.add(jdesktoppane, BorderLayout.CENTER); }
}
The result of this code is shown in Figure 17.7:
You will learn how to use creating scroll panes in Chapter 13 and also how to use using split panes in Chapter 15 of this book.
591
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
Youll find the fields of the JInternalFrame class in Table 17.5, its constructors in Table 17.6, and its methods
in Table 17.7:
Table 17.5: Fields of the JInternalFrame class
Field Does this
protected boolean closable It indicates whether the frame can be closed
static String CONTENT_PANE_PROPERTY It is the bound property name
protected JInternalFrame.JDesktopIcon It is displayed when the frame is iconified
desktopIcon
static String FRAME_ICON_PROPERTY It is the FRAME_ICON_PROPERTY bound property name
protected Icon frameIcon It is shown in the top-left corner of the frame
static String GLASS_PANE_PROPERTY It is the GLASS_PANE_PROPERTY bound property name
protected boolean iconable It returns True if the frame can be minimized and displayed as an
icon image
static String IS_CLOSED_PROPERTY It indicates that the frame is closed
static String IS_ICON_PROPERTY It indicates that the frame is iconified
static String IS_MAXIMUM_PROPERTY It indicates that the frame is maximized
static String IS_SELECTED_PROPERTY It indicates that this frame has selected status
protected boolean isClosed It return True if the frame has been closed
protected boolean isIcon It returns True if the frame has been iconified
protected boolean isMaximum It returns True if the frame has been expanded to its maximum
size
protected Boolean isSelected It returns True if the frame is currently selected
static String LAYERED_PANE_PROPERTY It is the LAYERED_PANE_PROPERTY bound property name
protected boolean maximizable It returns True if the frame can be expanded to the size of the
desktop pane
static String MENU_BAR_PROPERTY It is the bound MENU_BAR_PROPERTY property name
protected boolean resizable It returns True if the frames size can be changed
static String ROOT_PANE_PROPERTY It is the bound ROOT_PANE_PROPERTY property name
protected JRootPane rootPane The JRootPane instance for this frame
protected Boolean It returns True when calling the add and setLayout methods
rootPaneCheckingEnabled cause an exception to be thrown
protected String title It displayes the title in the frames title bar
static String TITLE_PROPERTY It is the bound TITLE_PROPERTY property name
592
Immediate Solutions
593
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
594
Immediate Solutions
Well now put together an example showing how to use internal frames in a desktop pane. We start by adding a
desktop pane to an applet, and we add a JPanel object as well. We place a button with the caption New
internal frame in the panel. When the user clicks that button, the applet displays a new internal frame in the
desktop pane. Each internal frame will enclose a text area object of the JTextArea class (which youll see in a
few chaptersfor our purposes here, it acts like the AWT TextArea class), thus allowing the user to enter text.
Heres how we set up the applet with a desktop pane and the button New internal frame:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*
<APPLET
CODE = InternalFrame.class
WIDTH = 450
HEIGHT = 300>
595
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
</APPLET>
*/
public class InternalFrame extends JApplet implements ActionListener
{
JDesktopPane jdesktoppane = new JDesktopPane();
static int framenumber = 1;
public void init()
{
JPanel jpanel = new JPanel();
Container contentPane = getContentPane();
JButton jbutton = new JButton("New internal frame");
jpanel.add(jbutton);
contentPane.add(jpanel, BorderLayout.SOUTH);
contentPane.add(jdesktoppane, BorderLayout.CENTER);
jbutton.addActionListener(this);}
}
The real action takes place when the user clicks the button to display a new internal frame. We give each internal
frame a new caption in its title bar, so we must keep track of the number of internal frames in a new variable.
Next, we create, configure, and add new internal frames to the desktop pane. Heres how we create and
configure the internal frames, setting their locations and titles. We enable them so that the user can close, resize,
maximize, and minimize these frames, and we add a text area to the frames content panes. Note, in particular,
that internal frames must be made visible with the setVisible() method. After the components have been
added to the content pane, the pack() method is used to resize the frame window to match its contents. Also
note that when internal frames are added to desktop panes by using the add() method, a layer must be
specified to add those frames to. Heres what the code looks like:
public void actionPerformed(ActionEvent event)
{
JInternalFrame jinternalframe = new JInternalFrame();
Container contentPane = jinternalframe.getContentPane();
jinternalframe.setLocation(20, 20);
jinternalframe.setTitle("Internal Frame " + framenumber);
framenumber++;
jinternalframe.setClosable(true);
jinternalframe.setResizable(true);
jinternalframe.setMaximizable(true);
jinternalframe.setIconifiable(true);
jinternalframe.setVisible(true);
contentPane.setLayout(new FlowLayout());
contentPane.add(new JTextArea(5, 20), "Center");
jinternalframe.pack();
jdesktoppane.add(jinternalframe, 5);
}
The result of this code is shown in Figure 17.8:
596
Immediate Solutions
As you can see in the figure, you can create multiple internal frame windows in this applet, and you can resize
and move them around. You can even minimize them, as you see in the figure.
Now coming to the second example, InternalframeEg.java, to create an applet. Following is the code to
display the use of Internal Frame in applet:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.net.URL;
import javax.swing.border.*;
import javax.swing.event.*;
/* <APPLET
CODE = InternalframeEg.class
WIDTH = 400
HEIGHT = 400>
</APPLET> */
public class InternalframeEg extends JApplet implements ActionListener {
JDesktopPane jdesktoppane = new JDesktopPane();
static int framenumber = 1;
String msg="";
TextArea txt1;
public void init() {
JPanel jpanel = new JPanel();
Container contentPane = getContentPane();
JButton jbutton = new JButton("New internal frame");
txt1= new TextArea("output displayed here",3,30);
jpanel.add(jbutton);
jpanel.add(txt1);
contentPane.add(jpanel, BorderLayout.SOUTH);
contentPane.add(jdesktoppane, BorderLayout.CENTER);
jbutton.addActionListener(this); }
InternalFrameAdapter activator1 = new InternalFrameAdapter() {
public void internalFrameActivated(InternalFrameEvent e) {
JInternalFrame fr = (JInternalFrame)e.getSource();
InternalFrameListener[] jarr=fr.getInternalFrameListeners();
txt1.setText(" "+ jarr[1] + " " + jarr[2]+ " "); }
public void internalFrameIconified(InternalFrameEvent e) {
JInternalFrame fr = (JInternalFrame)e.getSource();
txt1.setText(" " +fr.getMostRecentFocusOwner()); }
public void internalFrameClosed(InternalFrameEvent e) {
JInternalFrame fr = (JInternalFrame)e.getSource();
txt1.setText(" " +fr.getFocusCycleRootAncestor()); }
};
InternalFrameAdapter activator2 = new InternalFrameAdapter() {
public void internalFrameOpened(InternalFrameEvent e) {
JInternalFrame fr = (JInternalFrame)e.getSource();
txt1.setText("2nd listener event "); }
};
public void actionPerformed(ActionEvent event) {
String str= event.getActionCommand();
if(str.equals("New internal frame")) {
JInternalFrame jinternalframe = new JInternalFrame();
Container contentPane = jinternalframe.getContentPane();
jinternalframe.setLocation(20, 20);
jinternalframe.setTitle("Frame " + framenumber);
if(framenumber==1) {
jinternalframe.addInternalFrameListener(activator1);
jinternalframe.addInternalFrameListener(activator2); }
else if(framenumber==2){ }
framenumber++;
jinternalframe.setClosable(true);
jinternalframe.setResizable(true);
597
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
jinternalframe.setMaximizable(true);
jinternalframe.setIconifiable(true);
jinternalframe.setVisible(true);
contentPane.setLayout(new FlowLayout());
contentPane.add(new JTextArea(5, 15), "Center");
jinternalframe.pack();
jdesktoppane.add(jinternalframe, 2); }
}
}
Output of this code is as shown in Figure 17.9:
598
Immediate Solutions
|____java.awt.Container
|____javax.swing.JComponent
|____javax.swing.JOptionPane
Youll find the fields of the JOptionPane class in Table 17.8, its constructors in Table 17.9, and its methods in
Table 17.10:
Table 17.8: Fields of the JOptionPane class
Field Does this
static int CANCEL_OPTION The return value from the class method if CANCEL is chosen
static int CLOSED_OPTION The return value from the class method if the user closes the
window without selecting anything
static int DEFAULT_OPTION The look and feel should not supply any options but only use the
options from the JOptionPane
static int ERROR_MESSAGE It is used for error messages
protected Icon icon The icon used in the pane
static String ICON_PROPERTY The bound property name for the icon
static int INFORMATION_MESSAGE It is used for information messages
static String The bound property name for initialSelectionValue
INITIAL_SELECTION_VALUE_PROPERTY
static String INITIAL_VALUE_PROPERTY The bound property name for initialValue
protected Object initialSelectionValue The initial value to select in selectionValues
protected Object initialValue The value that should be initially selected in the options
static String INPUT_VALUE_PROPERTY The bound property name for inputValue
protected Object inputValue The value the user has entered
protected Object message The message to display
static String MESSAGE_PROPERTY The bound property name for the message
static String MESSAGE_TYPE_PROPERTY The bound property name for the type
protected int messageType The message type
static int NO_OPTION The return value from the class method if the NO button is clicked
static int OK_CANCEL_OPTION The type used for showConfirmDialog
static int OK_OPTION The return value from the class method if OK is chosen
static String OPTION_TYPE_PROPERTY The bound property name for optionType
protected Object[] options The options to display to the user
static String OPTIONS_PROPERTY The bound property name for the option
protected int optionType The option type (DEFAULT_OPTION, YES_NO_OPTION,
YES_NO_CANCEL_OPTION, or OK_CANCEL_OPTION)
static int PLAIN_MESSAGE It indicates that no icon should be used
static int QUESTION_MESSAGE It is used for questions
static String The bound property name for selectionValues.
SELECTION_VALUES_PROPERTY
protected Object[] selectionValues The array of values, the user can choose from
static Object UNINITIALIZED_VALUE It indicates that the user has not yet selected a value
protected Object value The currently selected value. It will be a valid option,
UNINITIALIZED_VALUE, or null
static String VALUE_PROPERTY The bound property name for the value
599
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
600
Immediate Solutions
601
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
602
Immediate Solutions
You can use the JOptionPane static methods (that is, class methods, which you invoke directly by using the
class, like this: JOptionPane.showMessageDialog()) to display four types of dialog boxes. Here are those
methods and the dialog boxes they create:
showMessageDialog()It displays some message to the user.
showConfirmDialog()It asks a confirming question and receives a yes/no/cancel response.
showInputDialog()It prompts for input.
showOptionDialog()A configurable dialog box.
603
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
For each of these methods, theres also an internal (lightweight) frame version, such as
showInternalMessageDialog(), showInternalInputDialog(), and so on, in case you want to stick to
internal frames to conserve system resources.
All these methods can return an integer indicating which button the user has clicked; the possible values are
YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. These dialog boxes are modal,
which means the user must dismiss them before continuing with the rest of the program (clicking any other
window in the program just results in a beep).
All this is best understood through examples, so well dissect this class by using several examples over the next
few solutions.
604
Immediate Solutions
/* <APPLET
CODE = DialogMessage.class
WIDTH = 350
HEIGHT = 280 >
</APPLET> */
605
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
contentPane.add(jbutton4);
contentPane.add(jbutton5);
jbutton1.addActionListener(this);
jbutton2.addActionListener(this);
jbutton3.addActionListener(this);
jbutton4.addActionListener(this);
jbutton5.addActionListener(this); }
606
Immediate Solutions
HEIGHT = 280>
</APPLET> */
public class DialogTextEg extends JApplet implements ActionListener {
JButton jbutton = new JButton("Display dialog");
String message = "Enter the text";
public void init() {
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(jbutton);
jbutton.addActionListener(this); }
public void actionPerformed(ActionEvent e) {
String result = JOptionPane.showInputDialog(message);
if(result == null) { showStatus("You clicked Cancel"); }
else { showStatus("You typed: " + result); }
}
}
The result of this code is shown in Figure 17.13(a). On clicking the Display dialog button, the input dialog box
appears, as shown in Figure 17.13(b). When the user clicks the OK button, the dialog box disappears and the text
from the text field in the dialog box appears in the applets status bar as shown in Figure 17.13(c).
Note that we can put showInputDialog() to other uses as wellfor example, you can display a combo box in
a dialog box. See the next solution for the details.
Figure 17.13(a): A basic text-input dialog box Figure 17.13(b): Enter the text
607
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
608
Immediate Solutions
609
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
The JDialog class is the foundation of dialog boxes you customize in Swing. Heres the inheritance diagram for
this class:
java.lang.Object
|____java.awt.Component
|____java.awt.Container
|____java.awt.Window
|____java.awt.Dialog
|____javax.swing.JDialog
Youll find the fields of the JDialog class in Table 17.11, its constructors in Table 17.12, and its methods in
Table 17.13:
Table 17.11: Fields of the JDialog class
Field Does this
protected AccessibleContext accessibleContext The accessible context
protected JRootPane rootPane The root pane
protected Boolean rootPaneCheckingEnabled It determines whether root pane checking is enabled
610
Immediate Solutions
Well create a dialog box example by using the JDialog class here. In this case, we make the dialog box modal
by passing a final parameter set to True to the JDialog constructor, and we add two buttons to the dialog box
Yes and No. By adding action listeners to these buttons, we can tell which button was clicked, and we can
611
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
indicate that in the applets status bar. After a button is clicked, we call the dialog boxs dispose() method to
dispose of it. Heres what the code looks like (note that as with other Swing windows, you add controls to a
JDialog object by using its content pane):
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/*<APPLET
CODE = Dialog.class
WIDTH = 350
HEIGHT = 280>
</APPLET> */
612
Immediate Solutions
As you can see in the figure, the dialog box does display Yes and No buttons. Clicking a button closes the dialog
box and a message appears in the applets status bar indicating which button was clicked.
Note that the dialog box in Figure 17.16 only accepts button input from the user; for a more advanced example,
see the next solution.
In the previously mentioned code, you can replace:
private JDialog dialog = new JDialog((Frame) null,
"Dialog", true);
with:
private JDialog dialog = new JDialog((Frame) null,
"Dialog", true, getGraphicsConfiguration());
613
Chapter 17: SwingWindows, Desktop Panes, Inner Frames, and Dialog Boxes
The result of this code appears in Figure 17.17, where you can see the dialog box with the text field:
Summary
In this chapter, you have learned how to create a simple window and frame-based window. You have also read
about working with dialog boxes, such as confirmation dialog box and message dialog box.
In the next chapter, youll read about the Streams Handling File and I/O.
614
18
Working with
Streams, Files,
and I/O Handling
If you need an immediate solution to: See page:
Working with Streams 630
Working with the Reader Class 640
Working with the Writer Class 641
Accepting Input from the Keyboard with the InputStreamReader Class 641
Working with the OutputStreamWriter Class 643
Working with Files 643
Working with the RandomAccessFile Class 649
Working with Character Arrays 651
Working with Buffers 654
Working with the PushbackReader Class 656
Working with the PrintWriter Class 657
Working with the StreamTokenizer Class 659
Implementing the Serializable Interface 661
Working with the Console Class 665
Working with the Clipboard 667
Working with the Printer 667
Printing with the Formatter Class 668
Scanning Input with the Scanner class 671
615
Chapter 18: Working with Streams File and I/O Handling
In Depth
In this chapter, well take a look at stream, I/O, and file handling in Java. Using streams is the way you handle
I/O in languages such as Java. A stream is composed of bytes or characters (which are used to be considered
much the same in Java until Unicode and its 2-byte characters arrived) that you can read from or write to, and
you can connect them to various data sources and storeseven byte and character arrays.
NIO
Initially, New Input Output, also known as NIO, was introduced with the J2SE 1.4 by Sun Microsystems. It is a
collection of Java programming language Application Programming Interface (API) that provides features for
performing I/O operations.
The APIs of NIO were created for providing accessibility to the low-level I/O operations. The objective of
creating such high-level APIs is to enable an implementation that can easily utilize the most effective operations
of the existing platform.
The java.nio package and its sub-packages contain the Java NIO APIs. Some of their features are as follows:
Buffers for the primitive type data
Character set encoders and decoders
Pattern matching on the basis of Perl-style regular expressions (in package java.util.regex)A new
primitive I/O abstraction provisionA file interface inclusion, which supports locking and memory mapping
of files up to Integer.MAX_VALUE bytes (2 GiB)
A multiplexed, non-blocking I/O facility for writing scalable servers
Essentials in NIO
NIO is built on two fundamental itemsbuffers and channels. These are used in data handlinga buffer holds
data, while a channel represents an open connection to an I/O device, such as a file or a socket. Generally, to use
the NIO system, you obtain a channel to an I/O device and a buffer to hold that data. Operating can be done on
the buffer by providing input or output data.
616
In Depth
Buffers
Buffers are the integral part of the java.nio package. All buffers are subclasses of the Buffer class. The
Buffer class defines the core functionalitycurrent position, limit, and capacity. The current position is the
index in the buffer where the next read or write operation takes place. The current position is advanced by most
read and write operations. The limit in the index is the end of the buffer. The capacity is the number of elements
that the buffer can hold.
The Buffer class also supports the mark() and reset() methods. It defines several methods, which are
shown in Table 18.1, and Table 18.2 shows the specific buffer sub classes derived from the Buffer class:
Table 18.1: The methods of the Buffer class
Method Description
abstract Object array() It returns an array backing this buffer.
abstract int arrayOffset() It returns the offset of the first element of the buffer in backing array.
int capacity() It returns the number of elements that the invoking buffer is capable of
holding.
Buffer clear() It clears the invoking buffer and returns a reference to the buffer.
Buffer flip() It sets the invoking buffers limit to the current positions and resets the
current positions to 0. It returns a reference to the buffer.
abstract boolean hasArray() It returns true if the buffer is backed by some accessible array.
boolean hasRemaining() It returns true if there are elements remaining in the invoking buffer;
otherwise, it returns false.
abstract boolean isDirect() It returns true if the buffer is direct.
abstract boolean is ReadOnly() It returns true if the invoking buffer is read only; otherwise, it returns
false.
int limit() It returns the invoking buffers limit.
Buffer limit(int n) It sets the invoking buffer limit to n. It returns a reference to the buffer.
Buffer mark() It sets the mark and returns a reference to the invoking buffer.
int position() It returns the current positions.
Buffer position(int n) It sets the invoking buffers current position to n. It returns a reference to
the buffer
int remaining() It returns the number of elements between current position and the limit.
Buffer reset() It resets the current position of the invoking buffer to the previously set
mark. It returns a reference to the buffer.
Buffer rewind() It sets the positions of the invoking buffer to 0. It returns a reference to the
buffer.
Table 18.2: The specific buffer subclasses derived from the Buffer class
ByteBuffer CharBuffer
DoubleBuffer FloatBuffer
IntBuffer LongBuffer
MappedByteBuffer(a subclass of ShortBuffer
ByteBuffer; used to map a file
to a buffer)
617
Chapter 18: Working with Streams File and I/O Handling
All buffers support methods that perform different operations. For example, the allocate() method is used
for allocating a buffer manually . On the other hand, the wrap()method is used for wrapping an array inside a
buffer. Moreover, a subsequence of a buffer can be created by using the slice()method. The Buffer class also
supports various get() and put() methods, which allow you to get data from a buffer or put data into a
buffer. The get() and put() methods are described in Table 18.3:
Table 18.3: The get() and put() methods
Method Description
abstract byte get() It returns the byte at the current position.
ByteBuffer get(byte vals[]) It copies the invoking buffer into the array referred to by vals. It returns a
reference to the buffer.
ByteBuffer get(byte vals[], int It copies num elements from the invoking buffer into the array referred to
start, int num) by vals, beginning from the index specified by start. It returns a reference
to the buffer. If there are not num elements remaining in the buffer, a
BufferUnderflowException exception is thrown.
abstract byte get(int idx) It returns byte at the index specified by idx within the invoking buffer.
abstract bytebuffer put(byte b) It copies b into the invoking buffer at the current position. It returns a
reference to the buffer.
final ByteBuffer put(byte It copies all elements of vals into the invoking buffer, beginning from the
vals[]) current position. It returns a reference to the buffer.
ByteBuffer put(byte vals[], int It copies num elements from vals, beginning from start, into the invoking
start, int num) buffer. It returns a reference to the buffer if the buffer cannot hold all the
elements a BufferOverflowException is thrown.
ByteBuffer put(ByteBuffer bb) It copies the elements in bb to the invoking buffer, beginning from the
current position. If the buffer cannot hold all of the elements, a
BufferOverflowException is thrown. It returns a reference to the
buffer
abstract ByteBuffer put(int idx, It copies b into the invoking buffer at the location specified by idx. It
byte b) returns a reference to the buffer.
Channels
A channel represents an open connection to an I/O source or destination and is defined in the
java.nio.channels package.
A channel can be retrieved by using the getChannel()method on an object supporting channels. Table 18.4
shows its I/O classes:
Table 18.4: The I/O classes supported by the getChannel() method
DatagramSocket FileInputStream
FileOutputStream RandomAccessFile
ServerSocket Socket
To obtain a channel, you first obtain an object of one of these classes and then call getChannel() on that object.
The type of channel returned totally depends upon the type of object on which the getChannel() method is
called.
For example, when the getChannel()method is called using a FileInputStream, FileOutputStream, or
RandomAccessFile object, a channel of type FileChannel is returned. When called on a Socket,
getChannel() method returns a SocketChannel.
618
In Depth
Channels such as FileChannel and SocketChannel support various read() and write() methods that
allow you to perform I/O operations through the channel. For example, a few of the read() and write()
methods defined for FileChannel are listed in Table 18.5 in which all can throw an IOException:
Table 18.5: The read() and write() methods of the FileChannel class
Method Description
abstract int read(ByteBuffer bb) It reads bytes from the invoking channel into bb until the buffer is full or
there is no more input. It returns the number of bytes actually read.
abstract int read(ByteBuffer bb, Beginning at the file location specified by start, read bytes from the
long start) invoking channels into bb until the buffer is full or there is no more
input. The current position is unchanged. It returns the number of bytes
actually read or 1 if start is beyond the end of the file.
abstract int write(ByteBuffer bb) It writes the contents of bb to the invoking channel, starting at the
current position. It returns the number of bytes written.
abstract int write(ByteBuffer bb, Beginning at the file location specified by start, writes the contents of bb
long start) to the invoking channel. The current position is unchanged. It returns
the number of bytes written.
The methods are supported by all channels that let access to and control over them. For example, the map()
method is supported by FileChannel which allows you to map a file to a buffer. Heres a simple example
that uses all three types of stream to produce channels that are writeable, readable/writeable, and readable:
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
619
Chapter 18: Working with Streams File and I/O Handling
620
In Depth
621
Chapter 18: Working with Streams File and I/O Handling
622
In Depth
623
Chapter 18: Working with Streams File and I/O Handling
624
In Depth
java.lang.Object
|____java.nio.file.Paths
The methods of the Paths class are listed in Table 18.8:
Table 18.8: Methods of the Paths class
Method Does this
static Path get(String first, String It converts the strings passed as arguments to a Path by joining all
more) the specified strings.
static Path get(URI uri) It changes the given URI to a Path.
625
Chapter 18: Working with Streams File and I/O Handling
626
In Depth
The constructors of the FileSystem class are provided in Table 18.10 and its methods in Table 18.11:
Table 18.10: The constructor of the FileSystem class
Constructor Does this
Protected FileSystem() It is used to initialize a new instance of the FileSystem class.
627
Chapter 18: Working with Streams File and I/O Handling
as that of the earlier instantiated provider, then the file system provider is rejected because of duplicity. You
should note that the URI schemes are case-insensitive. During instantiation, a provider can retrieve the data
related to the default provider from files in the secured manner, but the circular loading of other installed
providers should be avoided. (This is because the circular loading of installed providers can cause an unknown
error).
The FileSystems class also defines some methods that allow you to specify the ClassLoader to be used
while locating a provider. If a thread starts loading of installed file system providers and another thread requests
a method that also wants to load the providers, then the method will block until the loading completes. The
inheritance diagram for this class is as follows:
java.lang.Object
|____java.nio.file.FileSystems
628
In Depth
Prospects of NIO
Only time and usage can tell whether the new approach will someday replace the traditional approach.
However, it is certain that the NIO APIs offer an exciting new way to think about and handle various types of
operations.
So what more does NIO give us? A lot, but not everythingnative code is still required. Some things that could
be done only with native code are now provided in NIO.
Theres a lot coming up next: I/O is a huge topic in Java. Its time to turn to the Immediate Solutions section.
629
Chapter 18: Working with Streams File and I/O Handling
Immediate Solutions
Working with Streams
Generally, programs use the data from external sources, which can be from the remote machines or from the
local files on the same system. Java uses the concept of streams for reading data from the system and writing
data to it.
Stream sources include files, buffers, sockets, threads, and other streams. Stream destinations include the same
objects as stream sources and others as well, such as printers. There are generally two types of streams: input
stream and output stream. In case of input stream, a stream of data items flows from a source, whereas, in case
of output stream, the data items flow to a destination.
630
Immediate Solutions
Now that you have seen InputStream and OutputStream, its time to put these classes to work, starting in
the next solution.
631
Chapter 18: Working with Streams File and I/O Handling
Heres an example. In this case, we are just creating a memory buffer with the text Dreamtech Press in it and
then opening a ByteArrayInputStream object to that buffer, reading and displaying the text byte by byte:
import java.io.*;
class ByteArrayInputStreamDemo
{
public static void main(String args[]) throws IOException
{
byte data[] = "Dreamtech Press".getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(data);
int character;
while((character = in.read()) != -1) {
System.out.print((char) character); }
}
}
The output from this code is shown in Figure 18.2, showing a string stored in an array of bytes:
632
Immediate Solutions
Take the case of another example, where the reset() method is used to read the same input twice, i.e. the
string Dreamtech is read and printed once in lowercase and then again in uppercase:
import java.io.*;
class ResetDemo
{
public static void main(String args[]) throws IOException
{
String p = "Dreamtech";
byte B[] = p.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(B);
for (int j=0; j<2; j++)
{
int N;
while ((N = in.read()) != -1)
{
if (j == 0) { System.out.print((char) N); }
else {
System.out.print(Character.toUpperCase((char) N)); }
}
System.out.println();
in.reset(); }
}
}
The output is shown in Figure 18.3, showing the same input printed twice:
633
Chapter 18: Working with Streams File and I/O Handling
void reset() It resets the count field of this byte array output stream to zero
void write(byte[ ] b, int off, It writes len bytes from the given byte array starting at offset off
int len)
void write(int b) It writes the given byte to this byte array output stream
void writeTo(OutputStream out) It writes the complete contents of this byte array output stream to the
given output stream argument
Heres an example. In this case, we are writing bytes to a ByteArrayOutputStream object, writing bytes to a
memory buffer, and sending bytes to a file output stream:
import java.io.*;
class ByteArrayOutputStreamDemo
{
public static void main(String args[]) throws IOException
{
ByteArrayOutputStream bytearrayoutputstream = new
ByteArrayOutputStream();
byte data[] = " Welcome to Dreamtech Press ".getBytes();
bytearrayoutputstream.write(data);
System.out.println(bytearrayoutputstream.toString());
byte buffer[] = bytearrayoutputstream.toByteArray();
for (int loop_index = 0; loop_index < data.length; loop_index++)
{
System.out.print((char) buffer[loop_index]); }
OutputStream fileoutputstream = new FileOutputStream("file.txt");
bytearrayoutputstream.writeTo(fileoutputstream);
fileoutputstream.close(); }
}
The result can be seen in Figure 18.4, showing the bytes to be stored in the buffer:
634
Immediate Solutions
Heres an example. In this case, well remove comments from a ByteArrayInputStream object that are
delimited with the # character. That means when we encounter a # character, well just stop displaying bytes
until we encounter a closing #.
For the purposes of this example, well only use comments that dont include spaces. Note that sometimes the #
character is a valid character in text, so if we encounter a # and stop displaying text and then encounter a space
635
Chapter 18: Working with Streams File and I/O Handling
before seeing a closing #, the text was not a comment. Therefore, we have to move back to the first # and
redisplay the text up to the space.
Well write this example using the mark() and reset() methods; we mark a location, then, if needed, use the
reset() method to go back to that location. Heres what the code looks like (note that you pass a length, in
bytes, to the mark() method that indicates the maximum number of bytes youll read before possibly using
reset()):
import java.io.*;
class BufferedInputStreamDemo {
public static void main(String args[]) throws IOException {
byte data[] = "Welcome to Dreamtech Press.#comment_goes_here#".getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(data);
BufferedInputStream bufferedinputstream = new
BufferedInputStream(in);
int character;
boolean silentflag = false;
while ((character = bufferedinputstream.read()) != -1) {
switch(character) { case '#':
if (silentflag) { silentflag = false; }
else {
silentflag = true;
bufferedinputstream.mark(100); }
break;
case ' ':
if (silentflag) {
silentflag = false;
System.out.print("#");
bufferedinputstream.reset(); }
else
System.out.print((char) character);
break;
default:
if (!silentflag) System.out.print((char) character);
}
}
}
}
Heres the output of this code: E:\Java8\chapter18\>java BufferedInputStreamDemo
Welcome to Dreamtech Press.
636
Immediate Solutions
The idea behind BufferedOutputStream is that you dont have to write data to disk every time a byte is
written, because output is buffered. To force a write operation, you can use the flush() method.
637
Chapter 18: Working with Streams File and I/O Handling
All the constructors can throw a FileNotFoundException. To create a file input stream, you use the
FileInputStream classs constructor. The reading methods you use with this class are as follows:
int read()It reads a byte of data from this input stream and returns it.
int read(byte[] b)It reads up to b.length bytes of data from this input stream into an array of
bytes and returns the number of bytes read.
int read(byte[] b, int off, int len)It reads up to len bytes of data from this input stream
into an array of bytes and returns the number of bytes read.
Lets consider an example: We open the source code file of the application, read and display 50 bytes of code,
skip 50 bytes with the skip() method, and then read and display 50 more bytes (note that we can also
determine how many bytes are waiting there to be read using the available() method, and we can close the
stream at the end of the code):
import java.io.*;
class FileInputStreamDemo {
public static void main(String args[]) throws Exception {
int size;
FileInputStream fileinputstream = new
FileInputStream("FileInputStreamDemo.java");
System.out.println("Available bytes: " + (size
=fileinputstream.available()));
System.out.println("Reading 20 bytes....");
byte bytearray[] = new byte[20];
if (fileinputstream.read(bytearray) != 20) {
System.out.println("Could not get 20 bytes"); }
System.out.println(new String(bytearray, 0, 20));
System.out.println("Skipping 20 bytes...");
fileinputstream.skip(20);
System.out.println("Reading 20 bytes....");
if (fileinputstream.read(bytearray) != 20) {
System.out.println("Could not get 20 bytes"); }
System.out.println(new String(bytearray, 0, 20));
fileinputstream.close(); }
}
The output from this code is shown in Figure 18.5, showing the input to a file:
An untrusted applet is not allowed to read and write files at all. So, unless you make specific security arrangements, you should
not try to read or write files from applets. Therefore, for the sake of convenience, all the programs in this chapter are
applications.
638
Immediate Solutions
You can use the FileOutputStream class to write data, byte by byte, to a file. They can throw a
FileNotFoundException class or a SecurityException class. Remember that the creation of a
FileOutputStream class is not dependent on the file that already exists. In fact, the FileOutputStream class
will create the file before opening it for output. An IOException is thrown in case you try to open a read-only
file. All FileOutputStream methods have a void return type.
The inheritance diagram for that class, which is derived from the OutputStream class, is as follows:
java.lang.Object
|____java.io.OutputStream
|____java.io.FileOutputStream
The constructors of the FileOutputStream class are provided in Table 18.33 and its methods in Table 18.34:
Table 18.33: Constructors of the FileOutputStream class
Constructor Does this
FileOutputStream(File file) It constructs a file output stream to write to the given File object.
FileOutputStream(File file, It constructs a file output stream to write to the file represented by the
boolean append) specified File object.
FileOutputStream(FileDescriptor It constructs an output file stream to write to the given file descriptor.
fdObj)
FileOutputStream(String name) It constructs an output file stream to write to the file with the given name.
FileOutputStream(String name, It constructs an output file stream to append to the file with the given
boolean append) name.
The writing methods you use with this class are as follows:
void write(byte[] b)Writes b.length bytes from the given byte array to this file output stream.
void write(byte[] b, int off, int len)Writes len bytes from the given byte array, starting at
offset, to the file output stream.
void write(int b)Writes the given byte to the file output stream.
Heres an example in which we write the string of text This is a string of text. to a file in three waysbyte by
byte, all at once, and in part. Heres what the code looks like:
import java.io.*;
class FileOutputStreamDemo {
public static void main(String args[]) throws Exception {
byte data[] = "This is a string of text.".getBytes();
FileOutputStream fileoutputstream1 = new
FileOutputStream("file1.txt");
for (int loop_index = 0; loop_index < data.length; loop_index++) {
639
Chapter 18: Working with Streams File and I/O Handling
fileoutputstream1.write(data[loop_index]); }
FileOutputStream fileoutputstream2 = new
FileOutputStream("file2.txt");
fileoutputstream2.write(data);
FileOutputStream fileoutputstream3 = new
FileOutputStream("file3.txt");
fileoutputstream3.write(data, 5, 10);
fileoutputstream1.close();
fileoutputstream2.close();
fileoutputstream3.close(); }
}
Compile and execute this code and find three files-file1.txt, file2.txt, and file3.txt that are created.
640
Immediate Solutions
641
Chapter 18: Working with Streams File and I/O Handling
Youll find the constructors of the InputStreamReader class in Table 18.41 and its methods in Table 18.42:
Table 18.41: Constructors of the InputStreamReader class
Constructor Does this
InputStreamReader(InputStream It creates an InputStreamReader object.
in)
InputSreamReader(InputStream in, It creates an InputStreamReader that uses the given charset.
Charset cs)
InputSreamReader(InputStream in, It creates an InputStreamReader that uses the given charset decoder.
CharsetDecoder dec)
InputStreamReader(InputStream It creates an InputStreamReader object that uses the named character
in, String enc) encoding.
Heres an example: Well just read keys from the keyboard and echo them. Note that the input stream does not
become available until the user presses the Enter key. Heres what the code looks like:
import java.io.*;
class InputStreamReaderDemo
{
public static void main(String args[])
{
try {
String character;
InputStreamReader inputstreamreader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputstreamreader);
character = br.readLine();
System.out.print(character);
}
catch (IOException e) { }
}
}
The output of this code is shown in Figure 18.6, printing the string taken from the keyboard as an input:
642
Immediate Solutions
643
Chapter 18: Working with Streams File and I/O Handling
You can use the File class to determine a lot about files, such as their sizes; whether you can write to them;
whether an item is a file, directory, or named pipe; and a lot more for manipulating the information associated
with a disk file, such as permissions, time, date, and for navigating subdirectory hierarchies. Heres the
inheritance diagram for the File class:
java.lang.Object
|____java.io.File
A Java directory is considered to be an additional property, in which an array of filenames can be verified by
using the list() method. Youll find the fields for the File class in Table 18.45, its constructors in Table 18.46,
and its methods in Table 18.47:
Table 18.45: Fields of the File class
Field Does this
static String pathSeparator It is a system-dependent path-separator string.
static char pathSeparatorChar It is a system-dependent path-separator character.
static String separator It is a system-dependent default name-separator character, represented as
a string for convenience.
static char separatorChar It is a system-dependent default name-separator character.
644
Immediate Solutions
645
Chapter 18: Working with Streams File and I/O Handling
Note that you can use isFile() to determine whether an item is a true file or something else, such as a
directory (which you can check with isDirectory()) or a named pipe. In other words, the isFile()method
returns true if called on a file (and behaves like one) and false if called on a directory. Use toURL() to convert a
files path into a URL, rename files, and do more with the File class. The isAbsolute() method returns true
if the file has an absolute path and false if it is relative.
Lets look at an example. Here, we put several of the methods of the File class to work, getting some
information about a file named file.txt. Heres what the code looks like:
import java.io.File;
class FileDemo {
public static void main(String args[]) {
File file1 = new File("file.txt");
System.out.println("File: " + file1.getName() + (file1.isFile() ?
" is a file" : " is a named pipe or directory"));
System.out.println("Size: " + file1.length());
System.out.println("Path: " + file1.getPath());
System.out.println("Parent: " + file1.getParent());
System.out.println("Absolute Path: " + file1.getAbsolutePath());
System.out.println("File was last modified: " +
file1.lastModified());
System.out.println(file1.exists() ? "File exists" :
"File does not exist");
System.out.println(file1.canRead() ? "File can be read from" :
"File cannot be read from");
System.out.println(file1.canWrite() ? "File can be written to" :
"File cannot be written to");
System.out.println(file1.isDirectory() ? "File is a directory" :
"File is not a directory");
System.out.println(file1.isFile() ? "is a true file" :
"is a special file");
646
Immediate Solutions
647
Chapter 18: Working with Streams File and I/O Handling
648
Immediate Solutions
import java.io.*;
class FileWriterDemo {
public static void main(String args[]) throws Exception {
char data[] = {'T','h','i','s',' ','i','s',' ','a',
' ','s','t','r','i','n','g',' ','o','f',
' ','t','e','x','t','.' };
FileWriter filewriter1 = new FileWriter("f1.txt");
for (int loop_index = 0; loop_index < data.length; loop_index++) {
filewriter1.write(data[loop_index]); }
FileWriter filewriter2 = new FileWriter("f2.txt");
filewriter2.write(data);
FileWriter filewriter3 = new FileWriter("f3.txt");
filewriter3.write(data, 5, 10);
filewriter3.append("Dreamtech Press");
filewriter1.close();
filewriter2.close();
filewriter3.close(); }
}
After executing the code, three files named f1.txt, f2.txt and f3.txt will be created in the same location where you
have saved the .java file.
649
Chapter 18: Working with Streams File and I/O Handling
650
Immediate Solutions
Note that one of the attractions of the RandomAccessFile class is that you can both read and write using this
class, without having to break things up into input and output objects.
651
Chapter 18: Working with Streams File and I/O Handling
Heres an example. In this case, we just read characters from an array and print them out:
import java.io.*;
public class CharArrayReaderDemo {
public static void main(String args[]) throws IOException {
char data[] = {'T','h','i','s',' ','i','s',' ','a',
' ','s','t','r','i','n','g',' ','o','f',
' ','t','e','x','t','.' };
CharArrayReader chararrayreader = new CharArrayReader(data);
int character;
while((character = chararrayreader.read()) != -1) {
System.out.print((char)character); }
}
}
Heres the output of this code:
E:\Java8\chapter18\>java CharArrayReaderDemo
This is a string of text.
Take the case of this example which constructs one object using the entire sentence, while the other object has
only the first six letters:
import java.io.*;
public class CharArrayReaderDemo1 {
public static void main(String args[]) throws IOException {
String t = "The quick brown fox ran over the mount";
int l = t.length();
char w[] = new char[l];
t.getChars(0, l, w, 0);
CharArrayReader input1 = new CharArrayReader(w);
CharArrayReader input2 = new CharArrayReader(w, 0, 6);
int j;
System.out.println("All the characters:");
while((j = input1.read()) != -1) { System.out.print((char)j); }
System.out.println();
System.out.println("First 6 characters:");
while((j = input2.read()) != -1) { System.out.print((char)j); }
System.out.println(); }
}
The result of the code is shown in Figure 18.9:
652
Immediate Solutions
Lets concentrate on two constructors. In the first form, a buffer with a default size is created. In the second, a
buffer is created with a size equal to that specified by initialSize. The buf field of the CharArrayWriter
class stores the buffer, which will be increased automatically. The number of characters stored in the buffer is
contained in the count field of the CharArrayWriter class. Both buf and count are protected fields.
653
Chapter 18: Working with Streams File and I/O Handling
The BufferedReader class provides a buffered character reader class and the readLine() method. Heres the
inheritance diagram for BufferedReader:
java.lang.Object
|____java.io.Reader
|____java.io.BufferedReader
The BufferedReader class consists of two constructors. In the first one, a buffered character-stream uses a
default buffer size. In the second, the size of the buffer is passed in sz. Youll find the constructors of the
BufferedReader class in Table 18.58 and its methods in Table 18.59:
Table 18.58: Constructors of the BufferedReader class
Constructor Does this
BufferedReader(Reader in) It constructs a buffering character input stream.
BufferedReader(Reader in, int It constructs a buffering character input stream that uses an input buffer of
sz) the given size.
Heres another example using the BufferedReader class. In this case, we read the file file4.txt line by line
with the readLine() method. Heres the content of that file:
This is a wonderful program where you can find the capability of File() class.
Some streams provide data buffering.
And some do not.
Some are designed to work with data in memory buffers.
Some with files.
Heres the code:
import java.io.*;
class BufferedReaderDemo
{
public static void main(String args[]) throws Exception
{
FileReader filereader = new FileReader("file4.txt");
BufferedReader bufferedreader = new BufferedReader(filereader);
String instring;
while((instring = bufferedreader.readLine()) != null) {
System.out.println(instring); } filereader.close(); }
}
Heres the output of the code when its run:
E:\Java8\chapter18\>java BufferedReaderDemo
This is a wonderful program where you can find the capability of File() class.
Some streams provide data buffering.
And some do not.
Some are designed to work with data in memory buffers.
Some with files.
655
Chapter 18: Working with Streams File and I/O Handling
In Table 18.60, the first form of constructor creates a buffered stream with a default size and in the second
constructor, the size of the buffer is passed in sz.
656
Immediate Solutions
In Table 18.62, the first form of constructor creates a buffered stream that allows one character to be pushed back
at a time and in the second one, the size of the pushback buffer is passed in size.
657
Chapter 18: Working with Streams File and I/O Handling
The flushing of output buffer, whenever the println(), printf(), or format() method is called, is
controlled by the autoFlush parameter. If this parameter is true, the flushing automatically takes place.
Table 18.65: Methods of the PrintWriter class
Method Does this
PrintWriter append(char c) It appends the given character to the writer.
PrintWriter append(CharSequence It appends the given character sequence to the writer.
csq)
PrintWriter append(CharSequence It appends subsequence of given character sequence to the writer.
csq, int start, int end)
boolean checkError() It flushes the stream it not closed and checks its error states.
void clearError() It clears error state of the stream.
void close() It closes stream, returns system resources associated with stream.
void flush() It flushes the stream.
PrintWriter format(Locale l, It writes args according to the formatted string and let you specify
String format, Object args) locale.
PrintWriter format(String It writes args according to the formatted string with default locale.
format, Object args)
void print(boolean b) It prints a boolean value.
void print(char c) It prints a character.
void print(char[] c) It prints an array of characters.
void print(double d) It prints a double-precision floating-point number.
void print(float f) It prints a floating-point number.
void print(int i) It prints an integer.
void print(long l) It prints a long integer.
void print(Object ob) It prints an object
void print(String s) It prints a string
PrintWriter printf(Locale l, It writes arguments to this writer according to formatted string and let
String fmt, Object args) you specify Locale.
PrintWriter printf(String fmt, It writes arguments to this writer according to formatted string.
Object args)
void println() It terminates the current line by writing the line separator string.
void println(boolean x) It prints a boolean value and then terminates the line.
void println(char[] x) It prints an array of characters and then terminates the line.
void println(float x) It prints a floating-point number and then terminates the line.
void println(long x) It prints a long integer and then terminates the line.
658
Immediate Solutions
Similarly, we have set, of println() methods and write() methods of this class. The format() method is
also supported, which works exactly like the printf() method.
Here is an example:
import java.io.PrintWriter;
public class PrintWriterDemo
{
public static void main(String[] args)
{
PrintWriter out = new PrintWriter(System.out, true);
out.println("Dreamtech Press");
}
}
Compile and run the code, and the result is shown in Figure 18.11:
659
Chapter 18: Working with Streams File and I/O Handling
Youll find the fields of the StreamTokenizer class in Table 18.66, its constructors in Table 18.67, and its
methods in Table 18.68:
Table 18.66: Fields of the StreamTokenizer class
Field Does this
double nval The value of a number token.
String sval The string giving the characters of a word token.
static int TT_EOF A constant indicating that end of the stream is read.
static int TT_EOL A constant indicating that the end of the line has been read.
static int TT_NUMBER A constant indicating that a number token has been read.
static int TT_WORD A constant indicating that a word token has been read.
int ttype It contains the type of the token just read.
660
Immediate Solutions
Heres an example in which we use FileReader to read from a file, file.txt, whose content is the string
Welcome to Dreamtech Press. We divide that text into words, verify words with the TT_WORD field, and
retrieve the current value of token as a string using the sval field, which is as follows:
import java.io.*;
class StreamTokenizerDemo
{
public static void main(String args[]) throws Exception
{
FileReader filereader = new FileReader("file.txt");
StreamTokenizer streamtokenizer = new StreamTokenizer(filereader);
String instring;
while(streamtokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if(streamtokenizer.ttype == StreamTokenizer.TT_WORD)
System.out.println(streamtokenizer.sval); }
filereader.close(); }
}
The output of this example is shown in Figure 18.12 using the StreamTokenizer class:
661
Chapter 18: Working with Streams File and I/O Handling
Youll find the constructors of the ObjectInputStream class in Table 18.69 and its methods in Table 18.70:
Table 18.69: Constructors of the ObjectInputStream class
Constructor Does this
protected ObjectInputStream() It constructs an ObjectInputStream object.
ObjectInputStream It creates an ObjectInputStream object that reads from the given
(InputStream in) InputStream.
662
Immediate Solutions
663
Chapter 18: Working with Streams File and I/O Handling
Now we are back to serialization. Serialization is also required to implement Remote Method Invocation (RMI).
The RMI works in this way: RMI on one machine invokes a method of a Java object on a remote machine; an
object may be passed as an argument to that remote method; the sending machine serializes the object and
transfers it; and finally, the receiving machine deserializes it.
Heres an example showing how serialization works. In this case, we create a new serializable class named
NewString (file named as NewString.java). This class has a constructor that takes a string and one method
toString(), that returns that string (note that we implement the Serializable interface here):
import java.io.*;
class NewString implements Serializable {
664
Immediate Solutions
String data;
public NewString(String instring) { data = instring; }
public String toString() { return data; }
}
After creating a new object of the NewString class containing the text Dreamtech Press!, we use a
FileOutputStream stream as encapsulated by an ObjectOutputStream stream to write that object out to a
fileserialized.dat. Next, we use a FileInputStream stream encapsulated in an ObjectInputStream
stream to read that object back from the file and display its text. The code is as follows:
import java.io.*;
public class SerializationDemo {
public static void main(String args[]) {
NewString inobject, outobject;
inobject = new NewString("");
outobject = new NewString("Dreamtech Press!");
try {
FileOutputStream fileoutputstring = new
FileOutputStream("serialized.dat");
ObjectOutputStream objectoutputstream = new
ObjectOutputStream(fileoutputstring);
objectoutputstream.writeObject(outobject);
objectoutputstream.flush();
objectoutputstream.close();
FileInputStream fileinputstring = new
FileInputStream("serialized.dat");
ObjectInputStream objectinputstream = new
ObjectInputStream(fileinputstring);
inobject = (NewString)objectinputstream.readObject();
objectinputstream.close(); }
catch(Exception e){ }
System.out.println(inobject); }
}
Compile NewString.java and SerializationDemo.java. The output of this code is shown in
Figure 18.13:
665
Chapter 18: Working with Streams File and I/O Handling
With the end of console, the input stream read methods of this class return null. All methods throw
NullPointerException on passing a null argument to them.
Using this new console API, the formatted output can be written and read easily as it is integrated with
Formatter API. The readLine() methods are key methods for user input here. readLine(String fmt,
Object args) is a combination of formatted output with user input. A first time support to read password
from console has been introduced through the readPassword() methods.
Here is an example using the java.io.Console object:
import java.io.*;
public class ConsoleDemo{
public static void main(String args[]) {
int MIN_PASSWORD_LENGTH = 8;
char[] password;
Console console=System.console();
do {
password = console.readPassword( "Enter password (minimum
666
Immediate Solutions
667
Chapter 18: Working with Streams File and I/O Handling
Heres an example that draws a small graphics figure on a page and then prints it (note that we have to create an
object that has a toolkita Frame object hereto use getPrintJob()):
import java.awt.*;
import java.awt.event.*;
668
Immediate Solutions
{
public static void main(String[] argv)
{
String inls = "LKJ";
String cnt = "just because";
System.out.printf("reason: %s (noted by %s)", cnt, inls);
}
}
The output of the preceding code is as follows:
reason: just because (noted by LKJ)
In the previous printf() example, a format string with embedded format specifiers is passed to printf().
After this, pass a list of arguments corresponding to each format specifier. The previous example has two format
specifiers: %s and %s, and these correspond to the cnt argument and inls argument respectively.
The format specifier %s has some significance. The letter `s signifies a String conversion and % signifies the
start of a format specifier. Some characters that trigger the end of format are called conversions. A string
conversion signifies that Java calls toString() on the corresponding argument and substitutes the result for
the format specifier.
There are four arguments, each using same reference, i.e., you can supply a single argument if all are same and that will be
used more than once.
Following example shows how one can use the same argument more than once against a format string:
String str = String.format("char: %c integral: %<d octal: %<o hex: %<x %n", i);
In the preceding example, reference can be used only once. The less-than sign (<) is used very frequently and
bears some special significance. It signifies that the same argument must be used as the last format specifier.
669
Chapter 18: Working with Streams File and I/O Handling
int i = 65;
String str =String.format("%1$td %1$tb %1$ty", new Date());
System.out.println(str);
}
}
The preceding code produces a string with the value, as shown in Figure 18.16:
670
Immediate Solutions
671
Chapter 18: Working with Streams File and I/O Handling
The output of the preceding code is shown in Figure 18.18, taking input from the Scanner class.
Summary
In this chapter, you have learned the use of file class and to work with streams. Then, we have explored the
RandomAccessFile, Reader and Writer classes. Following that, we have discussed to input the value from the
keyboard with the InputStreamReader class and work with the OutputStreamWriter class. You have next
learned to work with files, character arrays, and buffers. Moving further, we have discussed how to work with
the StreamTokenizer class, Serializable interface, and Console class. You have also learned to work with printer
and clipboard. Lastly, you have learned to print with the Formatter class and scan input with the Scanner class.
In the next chapter, you will learn to work with multiple threads.
672
19
Working with
Multiple Threads
If you need an immediate solution to: See page:
Getting the Main Thread 678
Naming a Thread 678
Pausing a Thread 679
Creating a Thread with the Runnable Interface 681
Creating a Thread with the Thread Class 684
Creating Multiple Threads 686
Joining Threads 688
Checking if a Thread Is Alive 689
Setting Thread Priority and Stopping Threads 690
Synchronizing 692
Communicating between Threads 704
Suspending and Resuming Threads 705
Creating Graphics Animation with Threads 707
Eliminating Flicker in Graphics Animation Created Using Threads 710
Suspending and Resuming Graphics Animation 711
Using Double Buffering 713
Simplifying Producer-Consumer with the Queue Interface 715
Implementing Concurrent Programming 717
Simplifying Servers Using the Concurrency Utilities 718
Knowing Various Concurrency Utilities 719
Learning about the java.util.concurrent Package 719
Learning about the java.util.concurrent.locks Package 721
Learning about the java.util.concurrent.atomic Package 722
Chapter 19: Working with Multiple Threads
In Depth
In this chapter, we are going to take a look at multithreaded programming in Java and how it lets you support
graphics animation. A thread is a lightweight entity within a process. Multiple threads can occur within the same
process and share the memory. In fact, Java is one of the few programming languages that supports
multithreading. We can also say that multithreading is a specialized form of multitasking.
There are two types of multitaskingProcess-based and Thread-based. In process-based multitasking, the
computer is able to run two or more programs concurrently. For example, you can listen to music and use the
notepad at the same time. On the other hand, a thread-based multitasking involves a single program to perform
two or more tasks simultaneously. For example, a text editor can format text at the same time it is being printed.
With the use of multithreading, maximum usage of resources occurs in minimum time. By keeping the idle time
to minimum, efficient programs can be created that makes maximum utilization of the CPU.
Many components in Java, most Swing component methods notably, are not thread-safe.
674
In Depth
try {
for(int k = 10; k > 6; k--) {
System.out.println("Parent Thread: " + k);
Thread.sleep(1000); }
}
catch (InterruptedException e) {
System.out.println("Parent Interrupted."); }
System.out.println("Exiting Parent."); }
}
class NewThread implements Runnable{
Thread T;
NewThread() { //a new, second thread
T = new Thread(this, "Creating Thread");
System.out.println("Child Thread : " + T);
T.start(); } // Start the thread
// Point of entry for the second thread.
public void run() {
try {
for(int j = 10; j > 6; j--) {
System.out.println("Child Thread: " + j);
Thread.sleep(500); } }
catch (InterruptedException e) {
System.out.println("Child interrupted."); }
System.out.println("Exiting Child."); }
}
Heres the output of the code:
Child Thread: Thread[Creating Thread,5,main]
Parent Thread: 10
Child Thread:10
Child Thread: 9
Child Thread:8
Parent Thread: 9
Child Thread:7
Exiting Child.
Parent Thread: 8
Parent Thread: 7
Exiting Parent.
675
Chapter 19: Working with Multiple Threads
The diagrammatical representation of the life cycle of a thread is shown in Figure 19.1:
Synchronization of Threads
Thread synchronization, also known as serialization, is a mechanism to ensure that no two concurrently
executing threads possess the same parts of a program at the same time. If a thread holds some part of a process
to access, the other thread must wait till the execution of the first thread finishes.
Basically, the object accessed by a thread is locked by it so that no other thread can access it. Synchronization is
used to control access to the systems, such as multiprocessor systems, systems supporting multithreading, and
distributed systems, consisting of bulky data, such as database for colleges or hospitals and many more.
There are two synchronization techniques:
To control the order in which the code is executed to perform different tasks
To prevent the obstacles that can arise when two threads share the same resource at the same time
676
In Depth
677
Chapter 19: Working with Multiple Threads
Immediate Solutions
Getting the Main Thread
The NP appears and says, Threads? I have been programming Java for a while now, and I cant see any
threads. You smile and say, Every Java program has at least one thread, called the main thread, and you can
take a look at it with the currentThread() method.
The currentThread() method of the Thread class gets the current thread; if you are executing in the main
thread, this method gets the main thread. Heres an example in which we are getting the main thread of an
application and printing out its name by using the getName() method (note that you can set a threads name
with setName()see the next solution):
class MainThread
{
public static void main(String args[])
{
Thread thread = Thread.currentThread();
System.out.println("The name of main thread is \"" + thread.getName()+"\"");
}
}
The output of this code is shown in Figure 19.2, displaying the name of the main thread:
Naming a Thread
One way to distinguish threads is by name, and you can set the name of a thread with the setName() method.
Heres an example in which we rename the main thread in an application and display that name:
class SetThreadName
{
public static void main(String args[])
{
Thread thread = Thread.currentThread();
System.out.println("Main thread's original name is " +
thread.getName());
thread.setName("Kogent");
678
Immediate Solutions
Pausing a Thread
Sometimes, you want to pause a threads execution, and you can do that with the sleep() method. You pass
this method the amount of time to pause, in milliseconds (a millisecond is one-thousandth of a second), and the
thread will wait that amount of time before continuing. Heres an example in which we print out a message,
pausing for a second between words:
class SleepDemo
{
public static void main(String args[])
{
try
{
System.out.println("Welcome");
Thread.sleep(1000);
System.out.println("to");
Thread.sleep(1000);
System.out.println("Kogent Solutions.");
}
catch (InterruptedException e) { }
}
}
679
Chapter 19: Working with Multiple Threads
680
Immediate Solutions
Thread.sleep(1500);
ob2.t.resume();
System.out.println("Thread Two, waking up..."); }
catch (InterruptedException e) {
System.out.println("Main thread broken"); }
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join(); }
catch (InterruptedException e) {
System.out.println("Main thread broken"); }
System.out.println("Finishing Main thread"); }
}
681
Chapter 19: Working with Multiple Threads
try {
(Thread.currentThread()).setName("Child");
for(int loop_index = 0; loop_index < 10; loop_index++) {
System.out.println((Thread.currentThread()).getName()+
" thread here...\n");
Thread.sleep(1000); }
}
catch (InterruptedException e) { }
System.out.println("Second thread Ending."); }
}
Heres the application that will create a new thread of the SecondThread class and run it; note that we are also
having the main thread print out its name so that you can see the two threads alternatively:
class RunnableDemo {
public static void main(String args[]) {
System.out.println("Starting Parent Thread.");
SecondThread secondthread = new SecondThread();
try {
(Thread.currentThread()).setName("Parent");
for(int loop_index = 0; loop_index < 10; loop_index++) {
System.out.println((Thread.currentThread()).getName()+
" thread here...");
Thread.sleep(1000); }
}
catch (InterruptedException e) { }
System.out.println("Parent Thread Ending."); }
}
The result of this code is shown in Figure 19.6:
682
Immediate Solutions
683
Chapter 19: Working with Multiple Threads
STEADYStart engine!
T minus 5
T minus 4
T minus 3
T minus 2
T minus 1
GOLiftoff!
T minus 0
684
Immediate Solutions
Heres an example in which we create a thread and have it print out its name 10 times, once a second. Note that
in this case, we are calling the threads constructor and passing it a name for this thread, and then we are calling
the threads start() method to start execution of the code in the run method. The action takes place in the
run() method, thats where we have the thread print out its name every second. Heres the code:
685
Chapter 19: Working with Multiple Threads
686
Immediate Solutions
687
Chapter 19: Working with Multiple Threads
Joining Threads
I need more control over threads, the NP says. Say I need to be able to wait until a thread is done executing
before going on with the rest of the program. Any way to check that? Certainly. you say. You can use the
join() method to wait until a thread is done. Really? the NP asks excitedly.
The Thread classs join() method waits until a thread is finished executing (also called waiting for a thread to
die) before returning. Heres an example in which we create four new threads and wait for each one to finish
executing before ending the main application:
class CustomThread extends Thread
{
CustomThread(String name)
{
super(name);
start();
}
public void run()
{
688
Immediate Solutions
try {
for(int loop_index = 0; loop_index < 4; loop_index++) {
System.out.println((Thread.currentThread()).getName()+ "
thread here...");
Thread.sleep(1000); } }
catch (InterruptedException e) { }
System.out.println((Thread.currentThread()).getName()+" ending.");}
}
class JoinDemo {
public static void main(String args[]) {
CustomThread thread1 = new CustomThread("First");
CustomThread thread2 = new CustomThread("Second");
CustomThread thread3 = new CustomThread("Third");
CustomThread thread4 = new CustomThread("Fourth");
try {
thread1.join();
thread2.join();
thread3.join();
thread3.join(); }
catch (InterruptedException e) { }
}
}
The output of this code is shown below:
C:\src>java JoinDemo
Second thread here...
First thread here...
Third thread here...
Fourth thread here...
Fourth thread here...
Third thread here...
Second thread here...
First thread here...
Third thread here...
First thread here...
Second thread here...
Fourth thread here...
Second thread here...
First thread here...
Fourth thread here...
Third thread here...
First ending.
Third ending.
Fourth ending.
Second ending.
689
Chapter 19: Working with Multiple Threads
690
Immediate Solutions
691
Chapter 19: Working with Multiple Threads
Synchronizing
Well, says the NP, I guess I cant use threads anymore. I have one object that stores the data in my program,
and I cant have many different threads working with that same object at the same timewhat if one thread
changes part of the data object and then another thread changes the same part of the data object before the first
thread is finished? Chaos! Well, you smile, you can prevent new threads from working with objects like that
until the current thread is finished by synchronizing your threads. Wow! says the NP.
Excluding other threads from an operation until that operation has completed is called synchronization. Heres an
example that shows why synchronization is useful. In this case, we have four new threads, all working with one
shared data object. This object prints out a start message and an end message, and it completes a half-second task
between the messages. Ideally, the data object should start, perform its task, and end before the next thread
starts a new task but thats not the way it works hereeach thread grabs the data object for itself. Heres
the code:
class SynchronizeDemo
{
public static void main(String args[])
{
Shared shared = new Shared();
CustomThread thread1 = new CustomThread(shared, "one");
CustomThread thread2 = new CustomThread(shared, "two");
CustomThread thread3 = new CustomThread(shared, "three");
CustomThread thread4 = new CustomThread(shared, "four");
try {
thread1.join();
thread2.join();
thread3.join();
thread4.join(); }
catch(InterruptedException e) { }
}
}
class CustomThread extends Thread {
Shared shared;
public CustomThread(Shared shared, String string) {
super(string);
this.shared = shared;
start(); }
public void run() { shared.doWork(Thread.currentThread().getName()); }
}
class Shared {
692
Immediate Solutions
Shared shared;
public CustomThread(Shared shared, String string) {
super(string);
this.shared = shared;
start(); }
public void run() {
synchronized(shared) {
shared.doWork(Thread.currentThread().getName()); }
}
}
class Shared {
void doWork(String string) {
System.out.println("Stop " + string);
try { Thread.sleep((long) (Math.random() * 500)); }
catch (InterruptedException e) { }
}
}
The output of this code is shown in Figure 19.9, showing the synchronization between code blocks:
Synchronizing Methods
Besides synchronizing code blocks, you can also block access to other threads by synchronizing methods. In this
case, you use the synchronized keyword when defining a method. Heres how we modify the doWork()
method in the Shared class and synchronize the threads:
class SynchronizeDemo2 {
public static void main(String args[]) {
Shared shared = new Shared();
CustomThread thread1 = new CustomThread(shared, "one");
CustomThread thread2 = new CustomThread(shared, "two");
CustomThread thread3 = new CustomThread(shared, "three");
CustomThread thread4 = new CustomThread(shared, "four");
try {
thread1.join();
thread2.join();
thread3.join();
thread4.join(); }
catch(InterruptedException e) { }
}
}
class CustomThread extends Thread {
694
Immediate Solutions
Shared shared;
public CustomThread(Shared shared, String string) {
super(string);
this.shared = shared;
start(); }
public void run() { shared.doWork(Thread.currentThread().getName()); }
}
class Shared {
synchronized void doWork(String string) {
System.out.println("Starting " + string);
try { Thread.sleep((long) (Math.random() * 500)); }
catch (InterruptedException e) { }
System.out.println("Ending " + string); }
}
Now, only one thread at a time can enter the doWork() method. The output of this code is shown in
Figure 19.10:
Synchronizing Classes
Synchronization gives you the choice of adding the synchronized keyword to a method or wrapping a code
section in a synchronized block. Several mechanisms for coordinating between different threads in an
application have been added. Another useful category of classes in java.util.concurrent is the
synchronizers. This set of classes coordinates and controls the flow of execution for one or more threads.
The Semaphore, CyclicBarrier, CountdownLatch, and Exchanger classes are all examples of
synchronizers. These classes have methods that are called by threads, which may or may not block on the basis
of the state and rules of the specific synchronizer being used.
696
Immediate Solutions
The methods of the Semaphore class and their functions are listed in Table 19.5:
Table 19.5: Methods of the Semaphore class
Method Does this
void acquire() It acquires a permit from this semaphore, blocking until one is available,
or the thread is interrupted
void acquire(int permits) It acquires the given number of permits from this semaphore, blocking
until all are available, or the thread is interrupted
void acquireUninterruptibly() It acquires a permit from this semaphore, blocking until one is available
void It acquires the given number of permits from this semaphore, blocking
acquireUninterruptibly(int permits) until all are available
int availablePermits() It returns the current number of permits available in this semaphore
int drainPermits() It acquires and returns all permits that are immediately available
protectedCollection<thread> It returns a collection containing threads that may be waiting to acquire
getQueuedThreads()
int getQueueLength() It returns an estimate of the number of threads waiting to acquire
boolean hasQueuedThreads() It queries whether any threads are waiting to acquire
boolean isFair() It returns true if this semaphore has fairness set true
protectedvoid reducePermits It shrinks the number of available permits by the indicated reduction
(int reduction)
void release() It releases a permit, returning it to the semaphore
void release(int permits) It releases the given number of permits, returning them to the
semaphore
string toString() It returns a string identifying this semaphore as well as its state
boolean tryAcquire() It acquires a permit from this semaphore, only if one is available at the
time of invocation
booloean tryAcquire(int permits) It acquires the given number of permits from this semaphore, only if all
are available at the time of invocation
boolean tryAcquire(int permits, It acquires the given number of permits from this semaphore, if all
long timeout, TimeUnit unit) become available within the given waiting time, and the current thread
has not been interrupted
boolean tryAcquire(long timeout, It acquires a permit from this semaphore, if one becomes available
TimeUnit unit) within the given waiting time, and the current thread has not been
interrupted
The created semaphore has a non-fair setting. This means that First In First Out (FIFO) behavior is not
guaranteed. To prevent starvation (a thread never getting a resource), it is better to create a fair semaphore.
However, there are throughput advantages if you ignore fairness. To acquire a permit from a semaphore, the
following two methods are invoked:
acquire()
acquire(int permits)
The acquire() method gets a single permit.
The acquire(int permits) method gets the requested number of permits. The methods block until a permit
is available, or the waiting thread is interrupted. If the thread is interrupted, an InterruptedException is
thrown.
The next two methods we are going to discuss, too, acquire permits, but their threads are dormant and
uninterruptible until the required numbers of permits are available. If a thread is interrupted while waiting, it is
regained after the resource becomes available:
acquireUninterruptibly()
acquireUninterruptibly(int permits)
697
Chapter 19: Working with Multiple Threads
The tryAcquire() method does not block. If the required number of permits is available, the methods return
true. If the permits are not available, false is returned. All permits must be true to get available. The fairness
setting is ignored with these untimed tryAcquire() methods:
tryAcquire()
tryAcquire(int permits)
The timed versions work similar to the untimed version, but wait for the specified TimeUnit before returning. If
interrupted while waiting, the methods throw an InterruptedException:
tryAcquire(long timeout, TimeUnit unit)
tryAcquire(int permits, long timeout, TimeUnit unit)
The following line shows how to wait 40 seconds for one permit:
boolean acq = tryAcquire(40, TimeUnit.SECONDS)
Now, lets look at an example that uses the Semaphore class. The following program, TestingSemaphore,
matches with an auction house service system. The service allows customers to see multiple items available for
purchase and displays an average of the prices of these items. However, due to licensing limitations, only two
threads can access the service at a time. To simulate the price sampling and averaging, the TestingSemaphore
program waits 30 milliseconds and then returns a random number from 0 to 100. If the service is concurrently
accessed after the limit of two threads is reached, a second pricing scheme is used. This latter scheme doesnt
have the licensing restriction but returns a less-reliable price (in this example, $20). Here is the
TestingSemaphore program:
import java.util.concurrent.*;
import java.util.*;
public class TestingSemaphore {
private static final int COUNT_LOOP = 100;
private static final int MAX_AVAILABLE = 2;
private final static Semaphore sphore = new
Semaphore(MAX_AVAILABLE, true);
private static class Price {
private static final Random rnd = new Random();
public static int getPrice() {
int prc = rnd.nextInt(100);
try { Thread.sleep(30); }
catch (InterruptedException ex) { ex.printStackTrace(); }
return prc; }
public static int getunfavPrice() { return 20; }
}
public static void main(String args[]) {
for (int i=0; i< COUNT_LOOP; i++) {
final int count = i;
new Thread() {
public void run() {
int prc;
if (sphore.tryAcquire()) {
try { prc = Price.getPrice(); }
finally { sphore.release(); }
} else { prc = Price.getunfavPrice(); }
System.out.println(count + ": " + prc); }
}.start();
}
}
}
Depending on the speed of your machine, you might need to modify the 50 millisecond delay for getting
reasonable results. Reasonable results means that you get some random values generated and some $20 values.
One sample runs as shown in Figure 19.11:
698
Immediate Solutions
699
Chapter 19: Working with Multiple Threads
To demonstrate, the following code, App.java, performs a parallel summation of the elements of a triangular
matrix:
import java.util.concurrent.*;
public class App {
private static int matrices[][] = {
{1},
{2, 2},
{3, 3, 3},
{4, 4, 4, 4},
{5, 5, 5, 5, 5}
};
private static int res[];
private static class Summer extends Thread {
int row;
CyclicBarrier barrier;
Summer(CyclicBarrier barrier, int row) {
this.barrier = barrier;
this.row = row; }
public void run() {
int cols = matrices[row].length;
int sum = 0;
for (int i=0; i<cols; i++) { sum += matrices[row][i]; }
res[row] = sum;
System.out.println("Results for row " + row + " are : " +
sum);
try { barrier.await(); }
catch (InterruptedException ex) { ex.printStackTrace(); }
catch (BrokenBarrierException ex) { ex.printStackTrace(); }
}
}
public static void main(String args[]) {
final int rows = matrices.length;
res = new int[rows];
Runnable merger = new Runnable() {
public void run() {
int sum = 0;
for (int i=0; i<rows; i++) { sum += res[i]; }
System.out.println("Results are: " + sum); }
};
CyclicBarrier barrier = new CyclicBarrier(rows, merger);
for (int i=0; i<rows; i++) { new Summer(barrier, i).start(); }
System.out.println("Waiting..."); }
}
Compile and run the program. The result is shown in Figure 19.12:
Figure 19.12: Printing Rows and Columns by Using the CyclicBarrier Class
700
Immediate Solutions
Creating a new thread and scheduling it doesnt necessarily cause the system to pause the existing thread.
Multiple threads might be created, all with the same priority. The system simply picks one thread to schedule at
that priority level. If you wish to reuse a cyclic barrier, you can call the reset method of CyclicBarrier
between usages.
701
Chapter 19: Working with Multiple Threads
702
Immediate Solutions
703
Chapter 19: Working with Multiple Threads
704
Immediate Solutions
705
Chapter 19: Working with Multiple Threads
706
Immediate Solutions
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending One...");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming One...");
ob2.mysuspend();
System.out.println("Suspending Two...");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming Two..."); }
catch (InterruptedException e) {
System.out.println("Main thread Suspended..."); }
try {
System.out.println("Waiting for threads to finish.");
ob1.h.join();
ob2.h.join(); }
catch (InterruptedException e) {
System.out.println("Main thread Suspended"); }
System.out.println("Main thread exiting..."); }
}
The result is shown in Figure 19.16:
707
Chapter 19: Working with Multiple Threads
browser decides to unload it, you can place code in the stop() method yourself but that means you cant
base your code on the Thread class, because stop() has been deprecated there. Therefore, well write an
example by using the Runnable interface, which doesnt have a deprecated stop() method. Heres the code:
import java.awt.*;
import java.applet.Applet;
/*<APPLET
CODE = Whirll.class
WIDTH = 300
HEIGHT = 300>
</APPLET>*/
public class Whirll extends Applet implements Runnable {
Image whirlImages[] = new Image[4];
Image nowImage;
int whirlIndex = 0;
Thread whirlThread;
boolean animateFlag = true;
public void init() {
whirlImages[0] = getImage(getCodeBase(), "whirl1.gif");
whirlImages[1] = getImage(getCodeBase(), "whirl2.gif");
whirlImages[2] = getImage(getCodeBase(), "whirl3.gif");
whirlImages[3] = getImage(getCodeBase(), "whirl4.gif"); }
public void start() {
whirlThread = new Thread(this);
whirlThread.start(); }
public void stop() { animateFlag = false; }
public void run() {
while(animateFlag) {
nowImage = whirlImages[whirlIndex++];
if(whirlIndex > 3)whirlIndex = 0;
repaint();
try {Thread.sleep(200);}
catch(InterruptedException e) { }
}
}
public void paint (Graphics g) {
if(nowImage != null)
g.drawImage(nowImage, 10, 10, this); }
}
You can see the result of this code in Figure 19.17:
708
Immediate Solutions
This applet makes the image you see in that figure. It appears to whirl around.
Well create another example that would create a ball that travels across a componentstarting from the left side
of the component and moving toward the right:
import java.applet.*;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
/*<APPLET
CODE = MoveBall.class
WIDTH = 300
HEIGHT = 300>
</APPLET>*/
public class MoveBall extends JApplet {
709
Chapter 19: Working with Multiple Threads
You can see the result of this code in Figure 19.18, where the applet moves the ball acrossfrom left to right:
710
Immediate Solutions
{
whirlThread = new Thread(this);
whirlThread.start();
}
public void stop() { animateFlag = false; }
public void run()
{
while(animateFlag)
{
nowImage = whirlImages[whirlIndex++];
if(whirlIndex > 3)whirlIndex = 0;
repaint();
try { Thread.sleep(200); }
catch(InterruptedException e) { }
}
}
public void paint (Graphics g)
{
if(nowImage != null) g.drawImage(nowImage, 10, 10, this);
}
public void update(Graphics g) {
g.clipRect(100, 100, 280, 280);
paint(g); }
}
Now, the image shown in Figure 19.19 will rotate practically flicker-free:
711
Chapter 19: Working with Multiple Threads
CODE = Whirl3.class
WIDTH = 300
HEIGHT = 300 >
</APPLET>*/
public class Whirl3 extends Applet implements ActionListener, Runnable {
Image whirlImages[] = new Image[4];
Image nowImage;
int whirlIndex = 0;
Thread whirlThread;
Button suspendButton, resumeButton;
boolean animateFlag = true;
boolean goFlag = true;
public void init()
{
whirlImages[0] = getImage(getCodeBase(), "whirl1.gif");
whirlImages[1] = getImage(getCodeBase(), "whirl2.gif");
whirlImages[2] = getImage(getCodeBase(), "whirl3.gif");
whirlImages[3] = getImage(getCodeBase(), "whirl4.gif");
suspendButton = new Button("Suspend");
add(suspendButton);
suspendButton.addActionListener(this);
resumeButton = new Button("Resume");
add(resumeButton);
resumeButton.addActionListener(this);
}
public synchronized void actionPerformed(ActionEvent e)
{
if(e.getSource() == suspendButton){goFlag = false;}
if(e.getSource() == resumeButton) {
goFlag = true;
notify();
}
}
public void start()
{
whirlThread = new Thread(this);
whirlThread.start(); }
public void stop() { animateFlag = false; }
public void run() {
while(animateFlag) {
nowImage = whirlImages[whirlIndex++];
if(whirlIndex > 3)whirlIndex = 0;
repaint();
try {
Thread.sleep(200);
synchronized(this) {
while(!goFlag)
wait(); }
}
catch(InterruptedException e) { }
}
}
public void paint (Graphics g)
{
if(nowImage != null) g.drawImage(nowImage, 10, 10, this);
}
public void update(Graphics g)
{
g.clipRect(150,100,200,280);
paint(g);
}
}
712
Immediate Solutions
Figure 19.20: Displaying Graphics Animation with the Suspend and Resume Buttons
713
Chapter 19: Working with Multiple Threads
catch(InterruptedException e) { }
}
}
public void paint (Graphics g) {
loop_index += 5;
if(loop_index >= 100) loop_index = 5;
graphics.setColor(new Color(255, 255, 255));
graphics.fillRect(0, 0, 50, 50);
graphics.setColor(new Color(0, 255, 255));
graphics.drawRect(0, 0, loop_index, loop_index);
g.drawImage(image1, 10, 10, this); }
}
The result of the code is shown in Figure 19.21:
714
Immediate Solutions
715
Chapter 19: Working with Multiple Threads
waiting for a random amount of time (ranging from 100 500 milliseconds). The object put onto the queue is
simply a String object consisting of the timestamp when the message was produced.
The actual work of enqueuing the object is done by the statement:
blockingQueue.put("Enqueued at: " + time)
The put() method throws an InterruptedException. Accordingly, the put() operation catches the
operation thrown, which is surrounded by a try and a catch block. The messages that are thrown from the
producer belong to the Consumer object, which extends from the Thread object and, therefore, must implement
the run() method.
The Consumer class is very similar in design to the Producer class. The Consumer class makes use of the
take() method to dequeue messages from the queue rather than putting messages on the BlockingQueue.
As already stated, this occurs because the thread waits until something is actually on the queue. If, onto the
queue, queuing of objects is stopped by the Producer thread, the Consumer thread will have to wait till there is
an item available in the queue. The following code illustrates the TestBlockingQueue class that spawns four
consumer threads, which try and grab objects from the BlockingQueue:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Date;
import java.util.Random;
import java.io.PrintStream;
class Producer extends Thread
{
private BlockingQueue<String> blockQ;
private PrintStream prnStr;
public Producer(BlockingQueue<String> blockQ, PrintStream prnStr)
{
this.prnStr = prnStr;
this.blockQ = blockQ;
}
public void run()
{
try {
while(true)
{
String time = String.format("%tc",new Date());
prnStr.println("Putting item on BlockingQueue
at time: " + time);
blockQ.put("Enqueued at: " + time);
Random generate = new Random();
int randomSlp = generate.nextInt(5) + 1;
Thread.sleep(randomSlp * 100);
}
}
catch (InterruptedException e) { e.printStackTrace(); }
}
}
class Consumer extends Thread
{
private BlockingQueue blockQ;
private String consumName;
private PrintStream prnStr;
public Consumer(String consumName, BlockingQueue blockQ,
PrintStream prnStr)
{
consumName = this.consumName;
blockQ = this.blockQ; prnStr = this.prnStr; }
public void run()
{
while (true) {
try {
prnStr.println(this.consumName + blockQ.take());
}
716
Immediate Solutions
717
Chapter 19: Working with Multiple Threads
With J2SE 5, a new path to multithreading was provided in the Java programming language. The real processes
for coordinating threads with wait() and notify() are now elaborated with new and sophisticated
mechanisms for working with threads. Here, we will focus on concurrency mechanisms that are included in Java
SE 7.0. The new packages are now a part of the java.util.concurrent package.
}
finally { mutex.rel();
} catch(InterruptedException ie) { }
Developers can use the standardized classes that provide building blocks for creating various applications.
718
Immediate Solutions
719
Chapter 19: Working with Multiple Threads
720
Immediate Solutions
Reader/Writer Locks
When using a thread to read data from an object, you do not need to prevent another thread from reading data
at the same time. As long as threads are just reading the data and not making any modifications to it, there is
absolutely no reason to lock threads. The java.util.concurrent.locks package provides classes that
implement this type of locking.
The ReadWriteLock interface provides locks for read-only and for writing. Multiple reader threads can use
readLock()simultaneously till the time there are no writers. The writeLock() is exclusive. Using
721
Chapter 19: Working with Multiple Threads
reader/writer locks increases concurrency and results in better performance, rather than using a mutual
exclusion lock. However, such an improvement in the performance can be benefitted only on a multi-processor.
The interfaces and their description are mentioned in Table 19.8 and the classes in Table 19.9:
Table 19.8: Interfaces of the java.util.concurrent.locks package
Interface Does this
Condition Condition factors out the Object monitor methods (wait, notify and
notifyAll) into distinct objects to give the effect of having multiple
wait-sets per object, by combining them with the use of arbitrary Lock
implementations.
Lock Lock implementations provide more extensive locking operations than
can be obtained using synchronized methods and statements.
ReadWriteLock A ReadWriteLock maintains a pair of associated locks, one for read-only
operations and one for writing.
722
Immediate Solutions
Multiple operations are treated as atomic if using the classes that belong to this package. For instance, you
cannot use a volatile integer with the ++ operator as this operator has several instructions.
The AtomicInteger class contains a method using which the integer it holds can be incremented atomically
without synchronization. For complicated tasks, atomic classes can be used. These tasks include writing code
that needs no synchronization. The following code is a sample sequence number generator that uses the
AtomicLong class:
import java.util.concurrent.atomic.*;
public class SampleSequenceGenerator
{
private AtomicLong number = new AtomicLong(0);
public long next()
{
return number.getAndIncrement();
}
}
Objects belonging to the classes AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference
facilitate access and updates to a single variable of the corresponding type. Furthermore, all these classes have
their own utility methods for that type, e.g., atomic increment methods.
These classes also have the getAndSet() method that assigns a new value to the variable and returns the
previous value without using any synchronization locks. Methods such as compareAndSet() and
weakCompareAndSet()are conditional modifier methods that take two arguments. The first argument takes
the original value when the method starts, and the second argument takes a new value to assign the data to.
The java.util.concurrent package facilitates concurrency utilities. There are no new features added to the
classes that belong to this package; however, these classes are more efficient to use and provide more quality
implementations for data synchronization techniques. This package has provided all the functionalities for
concurrent programming what the collection framework has provided for data structures, thereby refraining the
developer from making any new inventions that might possibly lead to incorrect implementations.
The java.util.concurrent package also enables you to create applications that are shorter, cleaner, more
reliable, easy to read and write, and easy to maintain.
If developers are using this package, it does not mean that their task has reduced. They will still have to create
applications that should be able to handle any synchronization issues.
There can be overlap between the classes. For instance, a semaphore having a single permit can be utilized to
hold a lock. Therefore, prior to using a new package in an efficient and protected manner, there are several
details that must be explored and clearly understood. It is always a good practice to review the packages and
their classes before actually using them.
723
Chapter 19: Working with Multiple Threads
Summary
In this chapter, you have read about the Threads, including creating a thread and naming a thread. You have
learned how to use the Runnable interface. Further on, there was a comprehensive discussion on Double
Buffering, Synchronization, and the java.util.concurrent Package.
In the next chapter, youll read about performing Networking and Security with Java.
724
20
Networking and
Security with Java
If you need an immediate solution to: See page:
Understanding Networking Interfaces and Classes in the java.net Package 734
Understanding the InetAddresses 736
Caching InetAddress 736
Creating and Using Sockets 740
Creating TCP Clients and Servers 743
Understanding the Whois Example 746
Submitting an HTML Form from a Java Program 748
Handling URL 749
Using the URLConnection Objects 752
Working with Datagrams 756
Datagrams Server and Client 758
Working with BART 759
Learning about the java.security Package 761
Chapter 20: Networking and Security with Java
In Depth
Networking is a particularly important topic in Java. In this chapter, well take a look at the URL class, which is
how about Java handles URLs, the URLConnection class, which allows you to get information about Web
pages (including their content), and the Socket class, which you use to create sockets for communication across
the Internet and intranets. The Socket class is particularly powerfulusing it, you can write client/server
Internet programs in which the client is on one machine and the server is on another.
In this chapter, youll also come across with Security concepts in Java. These concepts basically tell you about the
various classes and policies required for providing security in Java.
As we all know that Java, is much more appropriate as the networking language than any other language like
C++ or FORTRAN for networking, which makes it be called programming for the Internet by its creators. In
light of the preceding fact, the support provided by the java.net package for networking will be the focus of
this chapter.
Basics of Networking
The systems connected over a network through the Internet connect to each other with the help of Transmission
Control Protocol (TCP) or User Datagram Protocol (UDP). In Java, programming is done on the application layer
that uses the concept of classes in the java.net package; these classes provide a system-independent network.
Consider an example of communication that occurs between two ends, such as a telephone conversation. TCP
ensures that the data send from one end to other goes in the same order as it was sent. Otherwise, error occurs.
The examples of applications that need a consistent communication network are Hypertext Transfer Protocol
(HTTP), File Transfer Protocol (FTP), and Telnet. The success of these applications depends on the sequence in
which the data is set and received over the network. To read the data from the Uniform Resource Locator (URL),
the data must be received in the same order it was sent. Otherwise, a corrupt zip file or an HTML file is
retrieved in the end.
The UDP is connectionless unlike TCP. It sends datagrams (independent packets of data) from one application to
another. Here, there is no significance of the order of delivery and cannot be guaranteed because each message is
not related to the other.
Basically, a computer has a single physical connection with a network, and all the other devices are associated
with it through this network. The data transmitted over the network is identified by its address that consists of
IP address and port number.
Ports are specified by 16-bit numbers and ranged from 0 to 65,535. However, the port numbers that are ranging
from 0 to 1023 are reserved to be used by the protocols, such as HTTP and FTP, and other services of system.
These ports are known as well-known ports.
In case of datagram-based communication, such as UDP, the port number of destination is contained by the
datagram, packet and UDP transfers the packet to the destination accordingly. On the other hand, in case of
connection-based communication, such as TCP, a socket with a particular port number encapsulates a server
application. This allows the registration of the server with the system to receive all data efficiently.
Java programs use the TCP or UDP protocols for communicating over the Internet by using the classes in
java.net. The URL, URLConnection, Socket, and ServerSocket classes, all use TCP for communicating over
the network. The DatagramPacket, DatagramSocket, and MulticastSocket classes use UDP for
communicating over the network.
Networking includes two types of programsclient programs and server programs. A server program is a
program that provides services to one or more users who run client programs to access those services. These
client and server computers interact with each other through well-established protocols, which define the nature
of the communications between clients and servers.
726
In Depth
In a multi-tenancy architecture, a software applications single instance is used for serving multiple customers.
Changes in the class HttpURLConnection. When a security manager is installed in this class, a method is
called, which will try to open a connection. For this, the caller must provide one of the following conditions:
a "connect" SocketPermission to the combination of host/port of the destination URL
a URLPermission that allows this request
In case automatic redirection is enabled, this request gets redirected to the other destination. But the caller must
have the permission for connecting to the host/URL that is redirected.
727
Chapter 20: Networking and Security with Java
Support for generation of 2048-bit DSA key pair and additional signature algorithms for 2048-bit DSA
keys such as SHA224withDSA and SHA256withDSA
Keysize limitation pncrease from 1024 to 2048 for Diffie-Hellman (DH)
Better support for high entropy random number generationThe SecureRandom class allows
cryptographically strong random numbers to be generated for private or public keys, ciphers, signed
messages, etc. The getInstanceStrong() method is provided in JDK 8 for returning an instance of the
strongest SecureRandom implementation. Other changes done in the SecureRandom class are as follows:
For UNIX-like platforms, two new implementations NativePRNGBlocking and
NativePRNGNonBlocking were introduced, which provide blocking and non-blocking, behavior,
respectively
SHA1PRNG and NativePRNG are fixed to follow the SecureRandom seed source properties in the
java.security file
Addition of a new PKIXRevocationChecker classThe PKIXRevocationChecker class uses the PKIX
algorithm for verifying the cancellation status of certificates. Moreover, the PKIXRevocationChecker class
supports end-entity certificate checking, best-effort checking, and mechanism-specific options and
parameters.
64-bit PKCS11 for WindowsIn JDK 8, the PKCS 11 provider support has been enhanced for Windows
from 32 bit to include 64 bit.
New rcache types in Kerberos 5 replay cachingKerberos 5 includes two new rcache types such as none
and dfl. The type none signifies no rcache at all, whereas the type dfl signifies the DFL style file-based
rcache. Moreover, the acceptor-requested subkey is also supported. The rcache and subkey are configured
by using the sun.security.krb5.rcache and sun.security.krb5.acceptor.subkey system properties.
Protocol transition and constrained delegation for Kerberos 5JDK 8 supports Kerberos 5 protocol
transition and constrained delegation.
Weak encryption disabled by defaultBy default, the DES-related Kerberos 5 encryption types are not
supported, but can be enabled by adding the allow_weak_crypto=true in the krb5.conf file.
Unbound SASL for the GSS-API/Kerberos 5 mechanismThe Krb5LoginModule principal value in a
JAAS configuration file is set to asterisk (*) on the acceptor side for denoting an unbound acceptor. This
means the server can be accessed by the initiator using any service principal name if the acceptor includes
the long-term secret keys to that service. Using the GSSContext.getTargName() method, the name can be
accessed by the acceptor after establishing the context.
SASL service for multiple host namesWhile building a SASL server, you can set the server name to null
for denoting an unbound server; therefore, a service can be requested by a client with the help of any server
name. After establishing a context, the server can access the name as a negotiated property by using the key
name SASL.BOUND_SERVER_NAME.
JNI bridge to native JGSS on Mac OS XJNI bridge to native JGSS is now supported on Mac OS X. You
can enable it by setting the system property sun.security.jgss.native to true.
Support stronger ephemeral DH keys in the SunJSSE providerDuring the handshaking of SSL/TLS in
the SunJSSE provider, make ephemeral DH key match with the length of the certificate key. A new system
property, jdk.tls.ephemeralDHKeySize, is defined for customizing the ephemeral DH key sizes. The
minimum acceptable DH key size is 1024 bits, except for exportable cipher suites or legacy mode.
Support cipher suites preference customization in JSSEThe SunJSSE provider allows the preference of
client's cipher suite by default. However, you can change the behavior of the server's cipher suite preference
by invoking SSLParameters.setUseCipherSuitesOrder(true) in the server.
Sockets in Java
An IP Port on a specific host machine is called a Socket. The emergence of sockets was first apparent in early Unix
systems in the 1970s and have now become the standard low-level communication primitive.
728
In Depth
There exists a close resemblance of a network socket with an electrical socket. The plugs have their own standard
way of delivering the payload. It is very easy to plug in the socket and communicate by anything that
understands the standard protocol.
Lets now understand the two types of socketsconnection-oriented sockets, almost always based on TCP, and
connectionless sockets, usually based on User Datagram Protocol (UDP). There are quite a few distinguishing
differences between the two of them as TCP-type sockets guarantee data arrival and in the correct order,
whereas UDP-type ones do not. The major point to note here is that despite the preceding reason, many
sophisticated users sometimes use UDP.
It may appear obvious that server sockets execute on servers and client sockets execute on clients. However, it may not be
true all the time- servers can be socket servers, and socket clients, and clients can judicially run server sockets.
Client-Server Networking
The relationship between two computer programs in which one program, the client, makes a service request
from another program, the server, which fulfills the request is self-explanatory to discriminate the server from
the client. A network architecture comprises clients and servers among which communication occurs. A server is
a powerful computer that manages disk drives (file servers), printers (print servers), or network traffic (network
servers), whereas clients are those computers on which users run their applications. Clients depend on servers for
various resources, such as files, devices, and even processing power.
For the programs running on a network, client server model is a better idea to be implemented compared with a
single computer. The client server model is preferred for distributed systems where the systems are at several
locations.
An example of cash withdrawal from an ATM machine uses the concept of client server model. The customer
requests to the ATM machine for cash from his/her account the ATM machine forwards the request from the
user to the bank and after verification (through its database) from the bank, the bank sends approval to the
ATM. Further, the ATM responds back by providing the cash according to the instructions given in the field of
amount. It automatically generates the receipt if the user asks for it and deducts the amount from the customers
account.
Proxy Servers
In simple words, a proxy server can be viewed as a bridge between the client application, such as a Web
browser, and a real server. It gets and gathers all requests from the real server to view if it can satisfy the
requests itself. If not, it forward the request to the real server. The following two main goals are served by proxy
servers:
Improve performanceTo improve the performance of all users, a proxy server is used. A proxy server
saves the response for all the requests for a limit of time. Consider an example where both user A and user
B access the World Wide Web through a proxy server. User A first requests for a webpage like a website of
Java called page 1. After some time, user B also requests for the same page; instead of iterating the request
to the server, it invokes page 1 from user A, which was already fetched by user A. It is a time-saving process
and proxy servers support hundreds and thousands of users. The major online services that establish an
array of proxy servers are Yahoo, America Online, MSN, and many others.
Filter requestsProxy servers can also be used to filter requests, which means to allow only those requests
that are appropriate for the organization. For example, a college might use a proxy server to prevent its
students from accessing a specific set of websites.
So we can conclude that a proxy server is a connection between a LAN and an external network such as the
Internet. These days, proxy servers are facing competition from NAT and firewalls. In order to remain in
demand, the role of proxy servers has been widened to content caching and authentication besides guard-dog
security and connection sharing.
729
Chapter 20: Networking and Security with Java
Internet Addressing
A computer accessing the Internet has a specific address which is a number that uniquely finds each computer
on the Internet. On the Internet, there is only one type of electronic address. Once we know someones Internet
address, we can send mail, transfer files, have a conversation, and even find out information about that person.
The word address on the Internet is always referred to as an electronic address which consists of the forma
string followed by a @ character (the at sign), which is further followed by the unique name of a computer.
The part of the address mentioned after @ character is known as domain. Each part of a domain is called a sub-
domain and they are separated by periods. For example, xyz@pccrrn.co.uk.
In the example, there are three sub-domainspccrrn, co, and uk. You can understand a domain name by looking
at the sub-domains, considering them from right to left. The name is created so that each sub-domain notifies the
user about the computer. Top-level domain is the rightmost sub-domain. As it is read to the left, the sub-
domains become more specific. The top-level domain uk, means the computer is in the United Kingdom. The
next sub-domain, co, refers to a company. Next, pccrrn tells the user that is the name of a specific computer.
Generally, only lowercase letters are used for Internet addresses. There is no need to mix in uppercase letters. If an address
has some of the letters in uppercase, it is always safe to change them to lowercase.
730
In Depth
There are two classes for socket addressing, namely, SocketAddress and InetSocketAddress, as
shown in Figure 20.2:
731
Chapter 20: Networking and Security with Java
URL manages the syntactic operation of resolution as well as the I/O functions of looking up for the host and
setting up the connection to the resource.
Scheme-specific-part String
Authority String
User-info String
Host String
Port int
Path String
Query String
Fragment String
At any given instance, a particular component remains undefined or defined by using a unique value. The
former are represented by null, while later are represented by -1. A String component is defined with the
empty string as its value.
The type of URI being represented decides whether any particular component would be defined or not. A
scheme component is present in an absolute URI. An opaque URI comprises a scheme-specific part and a
fragment, but contains no other components. A hierarchical URI always comprises a path that can be empty and
a scheme-specific-part that might contain any of the other components.
732
In Depth
On calling the server, BartS, the protocol (Bart) used by the client, BartC, to communicate with the Bart server
is called because it allows you to randomly retrieve blackboard assignments. Bart server, BartS, communicates
over port 1234. A supporting class is also required that helps in network programming. This class, BartQ, has a
single method named getQuote() that returns one of the 20 randomly selected blackboard sentences.
import java.util.ArrayList;
public class BartQuote {
ArrayList<String> q = new ArrayList<String>();
public BartQuote() {
q.add("I will not waste chalk.");
q.add("I will not skateboard in the halls.");
q.add("I will not burp in class.");
q.add("I will not instigate a revolution.");
q.add("It's potato, not potatoe.");
q.add("I will not encourage others to fly.");
q.add("Tar is not a plaything.");
q.add("I will not sell school property.");
q.add("I will not get very far with this attitude.");
q.add("I will not sell land in Florida.");
q.add("I will not grease the monkey bars.");
q.add("I will not hide behind the Fifth Amendment.");
q.add("I am not a dentist.");
q.add("I will finish what I sta");
q.add("Hamsters cannot fly.");
q.add("I will not aim for the head.");
q.add("I will not expose the ignorance of the faculty.");
q.add("I will not conduct my own fire drills.");
q.add("I will not fake seizures.");
q.add("This punishment is not boring and meaningless.");
}
public String getQuote() {
int i = (int)(Math.random() * q.size());
return q.get(i);
}
}
Just compile this program. Well look at a full-fledged program that shows us the communication between the
server and client using the class BartQuote in the Immediate Solutions section.
733
Chapter 20: Networking and Security with Java
Immediate Solutions
Understanding Networking Interfaces and Classes in the java.net
Package
Now lets understand how Java relates to all the network concepts. OK, says the NP. So does Java support the
functionality of networks? You smile and say, Java makes it easy to connect to other computers using classes
from the java.net package.
Java supports TCP/IP suite for networking by enhancing the already created I/O interface and adding the
required features for creating I/O objects. Java supports both TCP and UDP protocols. The former is used for
stream-based I/O across the network, and the latter supports point-to-point transfer of datagrams.
734
Immediate Solutions
735
Chapter 20: Networking and Security with Java
IP Addresses Scope
The IP address scope can be divided into:
Link-local addressesThese addresses are developed to address a single link for various requirements
such as configuration of auto-address for neighbor discovery.
Site-local addressesThese addresses are developed for addressing inside of a site despite the requirement
for a global prefix.
Global addressesThey are distinct across the Internet.
Caching InetAddress
The InetAddress class provides the efficiency of caching successful as well as unsuccessful resolutions of host
name. DNS spoofing attacks are guarded by the positive caching, while negative caching improves the
performance of the system, but for a very short period of time.
Under some conditions, where it can be predicted that DNS spoofing attacks (falsifying the data) are not
possible, a Java security property can be set to a different Time-To-Live value for positive caching. Similarly, an
admin can configure negative caching TTL value when required. The two properties of Java security that can
control the values of TTL for both positive and negative resolutions of host name are as follows:
networkaddress.cache.ttl (default: -1)Denotes the policy of caching for successful name
lookups from the name service. The value is mentioned as integer that signifies the number of seconds for
caching the successful lookup. A value of -1 indicates cache forever.
networkaddress.cache.negative.ttl (default: 10)Denotes the policy of caching for
unsuccessful name lookups from the name service. The value mentioned as integer signifies the number of
seconds for caching the failure of unsuccessful lookups.
736
Immediate Solutions
737
Chapter 20: Networking and Security with Java
Lets look at this program which prompts the user for a host name and then it looks up the IP addresses for the
host name and displays the results. Once done, it asks the user if he or she wants to look up another host:
import java.util.Scanner;
import java.net.*;
Figure 20.3: Searching for IP address from the given host name
738
Immediate Solutions
Factory() Method
Since the InetAddress class has no visible constructors, factory methods have to be used to create an
InetAddress object. Factory methods are those where static methods in a class return an instance of that class.
Instead of overloading a constructor with various parameter lists and cluttering the result, it is better to have
unique method names. The commonly used InetAddress factory methods are:
static InetAddress getbyName(Stringhost)
throws UnknownHostException
static InetAddress getLocalHost()
throws UnknownHostException
static InetAddress[] getAllbyName(Stringhost)
throws UnknownHostException
The InetAddress representing the local host object is returned by the getLocalHost() method. When the
host name is passed to the getByName() method, it returns an InetAddress. An UnknownHostException
is thrown by these methods if they are unable in finding the name of host.
A single name can be used for representing various machines on the Internet. An array of InetAddresses is
returned by the getAllByName() factory methods. This array displays all of the addresses that a particular
name resolves to. An UnknownHostException is thrown if it is not able to resolve the name to at least one
address.
InetAddress also involves the factory method getByAddress(), which retrieves an IP address and returns
an InetAddress object. You can use either an IPv4 or an IPv6 address. In the following example, address and
name of the local machine and two well-known Internet websites are printed:
import java.net.*;
class InetTest
{
System.out.println(Adr);
System.out.println("\nPrinting IP addresses for host
name www.google.com");
Instance() Method
The InetAddress class also contains the Instance methods, which you can use on the objects returned by the
methods discussed earlier. The most commonly used methods are:
boolean equals(Object obj)
byte[] getAddress()
String getHostAddress()
String getHostName()
boolean isMulticastAddress()
String toString()
Internet addresses are searched in a hierarchical series of cached servers. In other words, your local host machine
may know a specific name-to-IP-address mapping automatically. For other names, it may ask for a local DNS
server for IP address data. If that server does not have a particular address, it can go to a remote site and ask for
it. This can continue all the way up to the root server (top). This process might take a long time, so it is advisable
to structure your code so that you cache IP address information locally rather than viewing it repeatedly.
740
Immediate Solutions
741
Chapter 20: Networking and Security with Java
Heres an example. In this case, well connect to port 80 at sun.com, the HTTP port, and get the main Web page
at www.sun.com, index.html by writing an HTTP GET request to that port. To write to a socket, you can use
a PrintWriter object, and to read from it, you use a BufferedReader object. Heres what the code looks like
(note that we terminate the HTTP request with two newline characters):
import java.io.*;
import java.net.*;
public class SocketDemo
{
public static void main(String[] args)
{
try {
Socket s = new Socket("www.sun.com", 80);
BufferedReader in = new BufferedReader(new
InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream());
out.print("GET /index.html\n\n");
out.flush();
String line;
while ((line = in.readLine()) != null) {
System.out.println(line); }
}
catch (Exception e){ }
}
}
The output of this code is shown in Figure 20.5, which shows reading and writing to a socket:
742
Immediate Solutions
743
Chapter 20: Networking and Security with Java
To run these applications, youll need two console windows (for example, in Windows, open two DOS
windows). Run the server first in one window as shown in Figure 20.6(a) and then the client in the other. When
you do, the client reports as shown in Figure 20.6(b):
744
Immediate Solutions
Here arises the need to create an input stream using DataInputStream class to receive response from the
server that allows you to read lines of text and Java primitive data types in a portable way by having methods
such as read(), readChar(), readInt(), readDouble(), and readLine():
DataInputStream inputstr;
try { inputstr = new DataInputStream(MyClient.getInputStream()); }
catch (IOException e) { System.out.println(e); }
After creating the input stream, there arises the need to create an output stream on the client side to send
information to the server socket using the class PrintStream or DataOutputStream of java.io:
PrintStream output;
try { output = new PrintStream(MyClient.getOutputStream()); }
catch (IOException e) { System.out.println(e); }
The PrintStream class contains methods that are used to display textual representation of primitive data
types. Its Write() and println() methods need to be remembered here. Also, you may want to use the
DataOutputStream:
DataOutputStream out;
try { out = new DataOutputStream(MyClient.getOutputStream()); }
catch (IOException e) { System.out.println(e); }
The class DataOutputStream enables you to create primitive data types of Java and its various methods are
used to write a single Java primitive type to the output stream. The method writeBytes() is a useful one.
After creating the input stream and output stream, you need to close the sockets. The output and input streams
must always be closed before closing the socket on the client side:
try {
output.close();
inputstr.close();
MyClient.close();
}
catch (IOException e) { System.out.println(e); }
In this way, you can close the socket after creating the input stream and output stream. There are two
constructors which are used to create a Socket object in order to establish a connection between the client and
server:
Socket(String hostname, int port)
Socket(InetAddress Adr, int port)
A socket can be monitored any time for the address and the port information associated with it by using the
following methods:
InetAddress getInetAddress()
int getPort()
int getLocalPort()
With accomplishing this, the access to input and output streams can be easily gained. The getPort() and
getLocalPort() throw an IOException if the sockets get invalidated due to the loss of connection on the net. These
streams are used exactly like the I/O stream to send and receive the data, like:
InputStream getInputStream()
OutputStream getOutputStream()
Some points about the Socket class are as follows:
Even though the Socket class has constructors, the normal way to create a socket is to use the attach()
method of the ServerSocket class.
An object of the OutputStream class is returned by the getOutputStream() method. This is the same
class used by System.out. Therefore, the print() and println() methods can be used for sending data
to the socket.
Exceptions are thrown by all the constructors and methods of the Socket class. Only the methods
getInetAddress(), getPort(), isBound() and isClosed() of the Socket class do not throw exception.
Thus, you need to enclose calls to these methods in try/catch statement.
745
Chapter 20: Networking and Security with Java
class AppWhois
{
public static void main (String args[]) throws Exception
{
int c;
Socket sokt = null;
try{
sokt = new Socket("whois.internic.net", 43, true);
InputStream inputstr= sokt.getInputStream();
OutputStream outputstr = sokt.getOutputStream();
String st = (args.length == 0 ? "hotmail.com" : args[0]) + "\n";
byte buf[] = st.getBytes();
outputstr.write(buf);
while ((c = inputstr.read()) != -1) {
System.out.print((char) c); }
}
catch(IOException exc){
System.out.println(exc);
}
sokt.close();
}
}
If, for example, you obtain information about xxxxxxx site, youd get something similar to the following:
Whois Server Version 2.0
Domain names in the .com and .net domains can now be registered
with many different competing registrars. Go to http://www.internic.net
for detailed information.
HOTMAIL.COM.AU
HOTMAIL.COM.BR
HOTMAIL.COM.IS.HOSTED.ON.PROFITHOSTING.NET
HOTMAIL.COM.IS.N0T.AS.1337.AS.GULLI.COM
HOTMAIL.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM
HOTMAIL.COM
To single out one record, look it up with "xxx", where xxx is one of the
records displayed above. If the records are the same, look them up
with "=xxx" to receive a full display for each record.
. . .
746
Immediate Solutions
A Socket object must be created from the ServerSocket class for the implementation of the server to listen
for connections and accept them from clients:
Socket clientSocket = null;
try { serviceSocket = MyService.accept(); }
catch (IOException e) { System.out.println(e); }
Once the socket is opened in the server, DataInputStream can be used to receive input from the client through
the input stream on the server side:
DataInputStream input;
try { input = new DataInputStream(serviceSocket.getInputStream()); }
catch (IOException e) { System.out.println(e); }
Similarly, in order to create an Output stream on the server side, the class PrintStream is used to send
information to the client:
PrintStream output;
try { output = new PrintStream(serviceSocket.getOutputStream()); }
catch (IOException e) { System.out.println(e); }
You can use the class DataOutputStream as described in the Client Socket.
The important point to note here is that the output and input streams must be closed before closing the socket.
To close the socket on the server side:
try {
output.close();
input.close();
serviceSocket.close();
MyService.close();
}
catch (IOException e) { System.out.println(e); }
There exists a remarkable difference between a normal socket and a ServerSocket. While creating a
ServerSocket, it registers itself with the system for client connection. The constructors over here simply reflect
the port number indicating the length of time you would be in queue before it can refuse or leave the client
connection pending. The default is 50. Under adverse conditions, the constructors will throw an IOException.
Here are three of its constructors:
ServerSocket(int port)
ServerSocket(int port, int maxQueue)
ServerSocket(int port, int maxQueue, InetAddress localAddress)
ServerSocket has a method known as accept(), which acts as a blocking call and waits for a client to start
communication, and then return with a normal Socket that is then used for communication with the client.
Table 20.7 shows the list of constructors of ServerSocket and its methods are defined in Table 20.8:
Table 20.7: Constructors of the ServerSocket
Constructor Does this
ServerSocket() It creates an unbound server socket
ServerSocket(int port) It creates a server socket, bound to the specified port
ServerSocket(int port, int backlog) It creates a server socket and binds it to the specified local port
number, with the specified backlog
ServerSocket(int port, int backlog, It creates a server with the specified port, listen backlog, and local IP
InetAddress bindAddr) address to bind to
747
Chapter 20: Networking and Security with Java
748
Immediate Solutions
$! = 0;
open FILEHANDLE, ">>reg.log";
print FILEHANDLE "Date: " . `date`;
print FILEHANDLE "Name: " . $co->param('name') . "\n";
print FILEHANDLE "email: " . $co->param('email') . "\n";
close FILEHANDLE;
unless ($!) { print "Thanks for registering."; }
else { print "Sorry, there was an error: $!"; }
}
print $co->end_html;
We pass two parameters to this CGI script: name and email. We do that by appending a string beginning with a
question mark to the end of this scripts URL, giving those parameters like this:
?name=Steve&email=me@here
Note that you can handle spaces in the parameters values by using a plus sign (+) instead of a space. To pass
this string to reg.cgi, we use an HTTP GET request, like this:
import java.io.*;
import java.net.*;
public class reg
{
public static void main(String[] args)
{
try {
Socket s = new Socket("localhost", 80);
BufferedReader in = new BufferedReader(new
InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream());
out.print("GET " + "/yourname/cgi/reg.cgi?name
=Steve&email=me@here\n\n");
out.flush();
String line;
while ((line = in.readLine()) != null) {
System.out.println(line); }
}
catch (Exception e){ }
}
}
Thats all it takes. This effectively calls the URL http://localhost//yourname/cgi/
reg.cgi?name=Steve&email=me@here. This is how you send data to an HTML form. When you install
reg.cgi on the server (using your server name and the correct URL for the script) and run this program, youll
get a confirming Web page back from reg.cgi, which reg.java prints out:
C:\>java reg
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<TITLE>CGI Example</TITLE>
<LINK REV=MADE HREF="mailto:Steve">
<META NAME="keywords" CONTENT="CGI Perl">
</HEAD><BODY BGCOLOR="white" LINK="red">
Thanks for registering.
</BODY>
</HTML>
Thats it. Now you can submit an HTML form from Java.
Handling URL
In Java, you handle URLs with the URL classfor example, you can pass a URL object to the getImage()
method of the Applet class to load in images. Heres the inheritance diagram for the URL class:
java.lang.Object
|____java.net.URL
749
Chapter 20: Networking and Security with Java
URL, called Uniform Resource Locator, uniquely identifies or addresses information on the Internet. There are
many items of software (and Java classes) that work directly with URLs. Javas URL class has several
constructors (each can throw a MalformedURLException) and methods, which are listed in Table 20.9 and
Table 20.10, respectively:
Table 20.9: Constructor of the URL class
Constructors Does this
URL(String spec) It creates a URL object from the String representation
URL(String protocol, String host, It creates a URL object from the specified protocol, host, port number,
int port, String file) and file
URL(String protocol, String host, It creates a URL object from the specified protocol, host, port number,
int port, String file, file, and handler
URLStreamHandler handler)
URL(String protocol, String host, It creates a URL from the specified protocol name, host name, and file
String file) name
URL(URL context, String spec) It creates a URL by parsing the given spec within a specified context
URL(URL context, String spec, It creates a URL by parsing the given spec with the specified handler
URLStreamHandler handler) within a specified context
750
Immediate Solutions
The most common form used includes the specification of the URL with a String that is similar to what you see
in a browser:
URL(String spec)
The other two forms of constructors break up the URL into its component parts as:
URL(String protocol, String host, int port, String file)
URL(String protocol, String host, String file)
The constructors that allow you to use an existing URL as a reference context and then create a new URL from
that context are:
URL(URL Context, String spec)
Heres an example that puts the URL class to work. In this case, we create a URL object for the Web page
https://www.oracle.com/java/index.html and then use the URL classs methods to get various parts of
the URL:
import java.net.*;
class URLDemo {
public static void main (String args[]) throws MalformedURLException {
URL httpurl = new URL("https://www.oracle.com/java/index.html");
System.out.println("Protocol: "+ httpurl.getProtocol ());
System.out.println("Port: "+ httpurl.getPort ());
System.out.println("Host: "+ httpurl.getHost ());
System.out.println("File: "+ httpurl.getFile ());
System.out.println("Ext: "+ httpurl.toExternalForm ()); }
}
The result is shown in Figure 20.7:
752
Immediate Solutions
753
Chapter 20: Networking and Security with Java
class URLConnectionDemo
{
public static void main(String args[]) throws Exception
{
int character;
URL url = new
URL("http://www.oracle.com/technetwork/java/index.html");
URLConnection urlconnection = url.openConnection();
System.out.println("Content type: " +
urlconnection.getContentType());
System.out.println("Document date: " + new
Date(urlconnection.getDate()));
System.out.println("Last modified: " + new
Date(urlconnection.getLastModified()));
System.out.println("Document expires: " +
urlconnection.getExpiration());
int contentlength = urlconnection.getContentLength();
System.out.println("Content length: " + contentlength);
if (contentlength > 0)
{
InputStream in = urlconnection.getInputStream();
while ((character = in.read()) != -1)
{
System.out.print((char) character);
}
in.close();
}
}
}
754
Immediate Solutions
The output of the code is shown in Figure 20.8, showing the URL content:
class URLConn
{
public static void main (String args[]) throws Exception
{
int c;
URL httpurl = new
URL("http://www.oracle.com/technetwork/java/index.html");
URLConnection httpurlCon = httpurl.openConnection();
long d = httpurlCon.getDate();
if (len == -1)
System.out.println ("Content length unavailable.");
else { System.out.println ("Content-Length: " + len); }
if (len != 0) {
System.out.println ("=== Content ===");
InputStream input = httpurlCon.getInputStream();
int I = len;
755
Chapter 20: Networking and Security with Java
DatagramPacket
The information passed through one datagram packet is independent of the other. In this, each message is
routed from one machine to another based solely on information contained within that packet; different packets
can be routed differently even if they are sent from a single machine regardless of the order. This means that it
might arrive in any order and this delivery is not guaranteed. DatagramPacket defines several constructors,
which you can see in Table 20.14 and the methods in Table 20.15:
756
Immediate Solutions
The constructor DatagramPacket(byte[], int length) specifies a buffer that is used for receiving data
and the packets size. It is used for receiving data over a datagram socket. The other syntax of constructor
DatagramPacket(byte[], int offset, int length) also contains an offset into the buffer at which
data will be stored. The third syntax of the constructor DatagramPacket(byte[], int length,
InetAddress, ipAddress, int port) specifies a target address and a port in addition, which are used by
DatagramSocket for determining the location to which the data in the packet will be sent.
The next constructor DatagramPacket(byte[], int offset, int length, InetAddress, ipAddress,
int port) is used for transmitting packets starting at the particular offset into the data.
There are various methods for accessing the internal state of a DatagramPacket class, which are provided in
Table 20.15:
Table 20.15: Methods of the DatagramPacket class
Methods Does this
InetAddress getAddress() It returns the IP address of the machine to which this datagram is being
sent or from which the datagram was received
byte[] getData() It returns the data buffer
int getLength() It returns the length of the data to be sent or the length of the data received
int getOffset() It returns the offset of the data to be sent or the offset of the data received
int getPort() It returns the port number on the remote host to which this datagram is
being sent or from which the datagram was received
SocketAddress getSocketAddress() It gets the SocketAddress (usually IP address + port number) of the
remote host that this packet is being sent to or is coming from
void It sets the IP address of the machine to which this datagram is being sent
setAddress(InetAddress iaddr)
void setData(byte[] buf) It sets the data buffer for this packet
void setData(byte[] buf, It sets the data buffer for this packet
int offset, int length)
void setLength(int length) It sets the length for this packet
void setPort(int iport) It sets the port number on the remote host to which this datagram is being
sent
void It sets the SocketAddress (usually IP address + port number) of the
setSocketAddress(SocketAddress ad remote host to which this datagram is being sent
dress)
757
Chapter 20: Networking and Security with Java
class ClientApp
{
public static int servPort = 997;
public static int clntPort = 998;
758
Immediate Solutions
{
ds = new DatagramSocket (clntPort);
client();
}
}
The preceding programs are restricted by the DatagramSocket constructor to running between two ports on
the local machine. To run the programs, use:
java ServerApp
in one window; this will be the server. Then run:
java ClientApp
This will be the client. Data that is typed into the window at the server side will be written across the network to
the client-side, where it is displayed after a newline is received, as shown in Figure 20.10:
759
Chapter 20: Networking and Security with Java
760
Immediate Solutions
return s; }
catch (UnknownHostException e) {
System.out.println("The host is unknown."); }
catch (IOException e) {
System.out.println("Network error."); }
}
}
}
Compile and execute the preceding code. The result of the Bart program is as follows (it differs from system to
system):
C:\> Java BartClient
Welcome to the Bart Client
What server do you want to connect to?yahoo.com
The host is unknown.
What server do you want to connect to?//appl
The host is unknown.
What server do you want to connect to?server_dt
Network error.
What server do you want to connect to?allen
Connection established!
Connected on port 1234
Connected to /192.168.0.51
Serving /192.168.0.51
Closed connection to /192.168.0.51
I will not fake seizures.
I will not fake seizures.
I will not fake seizures.
I will not fake seizures.
I will not fake seizures.
Interactive Session Ended
The procedure to connect to the server is placed in the getSocket() method. This method prompts the user for
a host name. The host name is read from the console and the method returns with the user that the program can
connect to.
761
Chapter 20: Networking and Security with Java
762
Immediate Solutions
763
Chapter 20: Networking and Security with Java
764
Immediate Solutions
The nested classes of the java.security.Policy class are given in Table 20.20, the fields in Table 20.21, and
the methods in Table 20.22:
Table 20.20: Nested class of the java.security.Policy class
Class Description
static interface It represents a marker interface for Policy parameters
Policy.Parameters
Let us see the implementation of the Policy class in the following solution:
import java.security.*;
import java.util.Enumeration;
PermissionCollection pc = Policy.getPolicy().getPermissions(domain1);
Enumeration e1 = pc.elements();
for (; e1.hasMoreElements();) {
Permission per = (Permission) e1.nextElement();
765
Chapter 20: Networking and Security with Java
System.out.println(per);
}
}
}
The output of the preceding code is shown in Figure 20.11:
Summary
In this chapter, you have learned about networking interfaces and classes, the InetAddresses, and caching
InetAddresses. Then, we have explained how to create and use sockets, create TCP clients and servers. Then,
we have discussed the whois example, as well as how to submit an HTML form. Next, you have learned to use
the URL, URL connection objects. You have also come to know datagram packets, datagram server and client.
Toward the end, you have learned BART and java.security package.
In the next chapter, you will learn about the Collections framework.
766
21
21
Collections
If you need an immediate solution to: See page:
Using the Collection Interface 776
The Queue Interface 777
The List Interface 777
The Set Interface 778
The SortedSet Interface 779
Using the Collection Classes 779
Using the Comparator Interface 792
Using the Iterator Interface 793
Using the ListIterator Interface 793
Using the AbstractMap Class 795
Using the HashMap Class 796
Using the TreeMap Class 799
Using the Arrays Class 801
Learning the Fundamentals of Enumerations 804
The Legacy Classes and Interfaces 810
Using the Aggregate Operations 818
Using the java.util.function Package 819
Chapter 21: Collections
In Depth
In this chapter, well take a look at the collection classes in Java, which are supported by java.util. As
you can infer from the name, the collection classes let you group elements in various ways. They collection
classes also define several methods that provide easier way of working with items. These classes are
important, not just for their utility but because many other Java methods use or return objects of these
classes, such as the ArrayList and HashMap classes.
The original Java release did not introduce Collections within it. So Java used ad hoc classes, such as Dictionary,
Vector, Stack, and Properties. The drawback was that these classes lacked a unifying scheme and were not
designed to be easily extended or adapted. Collections were finally added by J2SE 1.2. Java SE 8 has significantly
increased the power and streamlined the use of collections framework.
Youll see the details in this chapter; in particular, theres a standard set of classes that implement the collection
interfacesthe collection classes.
768
In Depth
LinkedListIt extends AbstractSequentialList into a linked list, where each element knows where
the next element is.
ArrayListIt implements a dynamic (resizable) array.
ArrayDequeIt implements a dynamic double-ended queue by extending AbstractCollection and
implementing the Deque interface (added by Java SE 6).
AbstractSetIt extends AbstractCollection and implements the Set interface.
HashSetIt extends AbstractSet to be used with a hash.
TreeSetIt extends AbstractSet to implement a set stored in tree form.
Note the HashSet class, which implements a set using a hash internally. In Java, hash stores information using
hashing; this converts a key to a hashcode thats then used to access the corresponding value. You dont deal with
the hashcode yourselfits generated internally in Java.
769
Chapter 21: Collections
770
In Depth
771
Chapter 21: Collections
772
In Depth
Aggregate Operations
An operation that is performed on a data structure rather than on an individual element is known as an
aggregate operation. Aggregate operations, like forEach, give an impression that these are like iterators.
However, they are different from iterators in the following ways:
They use internal iterationAggregate operations perform internal iteration as they do not contain a
method like next, which enables them to iterate to the next element of the collection. With the help of
internal delegation, your application identifies the collection over which it iterates. But the JDK identifies
the iteration over the collection. On the other hand, with the help of external iteration, your application can
determine about the collection over which it iterates and the way it iterates. However, there is a limitation
with external iterators as they can only iterate sequentially over the elements of a collection. This limitation
does not exist with internal iterators. Moreover, the internal iteration takes benefits of parallel computing,
which involves breaking a problem into subproblems and then solving them simultaneously.
They process elements from a streamAggregate operations do not process elements directly from a
collection, but directly from a stream. Therefore, they are also called stream operations.
They support behavior as parametersThe lambda expressions can also be specified as parameters for
most of the aggregate operations which allow customization of the behavior of a specific aggregate
operation.
To better understand the concept of aggregate operations, consider a scenario in which you are developing a
social networking site. You want to provide the facility that allows an administrator to perform different actions,
such as sending a message to the members of the social networking application, which satisfy certain criteria.
Suppose the members of this social networking application are represented by the following SNMember class:
public class SNMember {
public enum Gender {
M, FM
}
String sname;
LocalDate mem_birthday;
Gender sex;
String email;
// ...
public int getMemage() {
// ...
}
public String getMemname() {
// ...
}
}
773
Chapter 21: Collections
Consider the following code snippet which prints the name of all members contained in the collection memlist
using the for-each loop:
for (SNMember sn : memlist) {
System.out.println(sn.getMemname());
}
Now, consider the following code snippet which prints all the members present in the collection memlist, but
with the use of aggregate operation forEach:
memlist
.stream()
.forEach(e -> System.out.println(e.getMemname());
In the previous code snippet, the aggregate operation for-each loop is used.
Pipelines and Streams
A pipeline refers to a sequence of aggregate operations. Consider the following code snippet that prints the male
members available in the collection memlist with a pipeline that comprises the aggregate operations such as
filter and forEach:
memlist
.stream()
.filter(e -> e.getsex() == SNMember.Gender.M)
.forEach(e -> System.out.println(e.getMemname()));
A pipeline consists of the following components:
SourceIt might be a collection, an array, a generator function, or an I/O channel. In the previous code
snippet, the example of a source is the collection memlist.
Zero or more intermediate operations An intermediate operation, such as filter, produces a new stream.
StreamA stream does not store elements; instead, it carries values from a source through a pipeline. In the
previous code snippet, a stream is created from the collection memlist by invoking the method stream.
PredicateA new stream is returned by the filter operation. This stream comprises those elements that
match its predicate. In the preceding code snippet, the predicate is the lambda expression e -> e.getsex() ==
SNMember.Gender.M, which gives the boolean value(true or false). It returns true if the sex field of object e
has the value SNMember.Gender.M. Subsequently, the filter operation returns a stream that comprises all
male members in the collection memlist.
Terminal operationA pipleline also comprises a terminal operation, such as forEach, which generates a
non-stream result, such as a primitive value, a collection, or no value at all. In the preceding code snippet,
the parameter of the forEach operation is the lambda expression e -> System.out.println(e.getMemname()),
which invokes the method getMemname on the object e.
774
In Depth
depending on the location of appearance of expression. For example, earlier, that is, in Java SE7, an assignment
statement's target type is used for type inference. However, in case of Java SE 8, the target type for type inference
is used. Consider the following code snippet in which a method invocation's target types are used for inferring
the data types of its arguments:
List<String> strLst = new ArrayList<>();
strLst.add("B");
strLst.addAll(Arrays.asList());
In the preceding code snippet, the method addAll is expecting a Collection object as its parameter and the
method Arrays.asList returns a List object. This will work as List in a subtype of Collection.
Now, consider the case of generics; the target type of addAll is Collection<? extends String>. On the
other hand, the Arrays.asList() method returns a List<T> instance. In Java SE 8, the compiler infers that
the value of the type variable T is String. The compiler can infer this by using the target type Collection<?
extends String>.
Thats it for the overview of whats in this chapter. Theres a lot coming up next the collection framework is
very large. Its time to turn to the Immediate Solutions section.
775
Chapter 21: Collections
Immediate Solutions
Using the Collection Interface
The Collection interface revolves around the objects to provide maximum generality. For example, all
general-purpose collection executions have a constructor that takes Collection parameter. This constructor,
known as a conversion constructor, initializes the new collection to hold all of the elements in the intended
location, whatever be the collections subinterface or implementation type. You can say that it permits you to
convert the collections type.
Consider an example that you have a Collection<String> co, which can be a List, a Set, or another kind of
Collection. It creates a new ArrayList (an implementation of the List interface), which consists of all the
elements in co. The code using the Collection<String> co is as follows:
List<String> list = new ArrayList<String>(co);
The foundation of the collection framework is the Collection interface, and because the collection classes
implement this interface, well take a look at its methods here for reference. Youll find the methods for the
Collection interface in Table 21.5:
Table 21.5: Methods of the Collection interface
Method Does this
boolean add(E e) It adds the given element.
boolean addAll It adds all the elements in the given collection.
(Collection c)
void clear() It removes all the elements from this collection.
boolean contains(E e) It returns True if this collection contains the given element.
boolean containsAll(Collection c) It returns True if this collection contains all the elements in the
given collection.
boolean equals(E e) It compares the given object with this collection for equality.
int hashCode() It gets the hashcode value for this collection.
boolean isEmpty() It returns True if this collection has no elements.
Iterator iterator() It gets an iterator over the elements in this collection.
boolean remove(E e) It removes a single instance of the given element.
boolean removeAll(Collection c) It removes all of this collections elements that are also contained
in the given collection (Optional Operation).
default boolean removeIf(Predicate<? It removes all the elements of this collection which satisfy the
super E> filter) given predicate.
boolean retainAll(Collection c) It keeps only the elements in this collection which are contained in
the given collection (Optional Operation).
int size() It gets the number of elements in this collection.
default Spliterator<E> HYPERLINK It creates a Spliterator over the elements in this collection.
"http://docs.oracle.com/javase/8/docs/api/java/util
/Collection.html" \l "spliterator--" spliterator()
default Stream<E> stream() It returns a sequential Stream with this collection as its source.
Object[] toArray() It gets an array containing all the elements in this collection.
<T> T[] toArray(T[ ] a) It gets an array containing all the elements in this collection whose
type is that of the given array.
776
Immediate Solutions
777
Chapter 21: Collections
778
Immediate Solutions
779
Chapter 21: Collections
java.lang.Object
|____java.util.AbstractCollection
Youll find the constructor for the AbstractCollection class in Table 21.10 and its methods in Table 21.11:
Table 21.10: The constructor of the AbstractCollection class
Constructor Does this
protected AbstractCollection() It constructs an AbstractCollection object.
780
Immediate Solutions
781
Chapter 21: Collections
782
Immediate Solutions
You can add elements to an ArrayList object with the add() method, get an element at a certain index with
the get() method, and remove elements with the remove() method.
Lets consider an example in which we add elements to an array at runtime. Remember we are using two forms
of the add() method: general form and the form that allows to add an element at a specific location(index). We
are also using the remove() method to remove one element. The Iterator interface is defined in the
java.util package. This Iterator interface has three methodshasNext(), next(), and remove().
These methods are all you need to access each element of a collection, as you see here:
import java.util.*;
class Arraylist
{
public static void main(String args[])
{
ArrayList<String> arraylist = new ArrayList<String>();
arraylist.add("Item 0");
arraylist.add("Item 2");
arraylist.add("Item 3");
arraylist.add("Item 4");
arraylist.add("Item 5");
arraylist.add("Item 6");
arraylist.add(1, "Item 1");
arraylist.remove("Item 5");
System.out.println(arraylist);
System.out.println("\nUsing the Iterator interface");
String s;
Iterator e = arraylist.iterator();
while (e.hasNext())
{
783
Chapter 21: Collections
s = (String)e.next();
System.out.println(s);
}
}
}
Heres the output of this example:
C:\>java Arraylist
Using the add method
[Item 0, Item 1, Item 2, Item 3, Item 4, Item 5, Item 6]
[Item 0, Item 1, Item 2, Item 3, Item 4, Item 6]
Generics is on the leading edge of Object-Oriented Programming. You can get by without knowing anything about generics, but
it is better to just have an idea about them so as to learn how ArrayList and LinkedList classes use the new generics feature.
784
Immediate Solutions
To build a linked list, you can use the add(), addFirst(), and addLast() methods; to get an element at a
certain index, you can use the get(), getFirst(), and getLast() methods; to set an elements value, you
can use the set method; and to remove an element, you can use the remove(), removeFirst(), and
removeLast() methods.
Heres an example which demonstrates ArrayDeque by using it to create a stack:
import java.util.*;
class ArrayDequeDemo { public static void main(String args[])
{
ArrayDeque<String> arrdeque= new ArrayDeque<String>();
arrdeque.push("Item 0"); arrdeque.push("Item 2");
arrdeque.push("Item 3");
arrdeque.push("Item 4");
arrdeque.push("Item 5");
arrdeque.push("Item 6");
785
Chapter 21: Collections
786
Immediate Solutions
To build a linked list, you can use the add(), addFirst(), and addLast() methods; to get an element at a
certain index, you can use the get(), getFirst(), and getLast() methods; to set an elements value, you
can use the set() method; and to remove an element, you can use the remove(), removeFirst(), and
removeLast() methods.
787
Chapter 21: Collections
Heres an example: We are simply building a linked list, adding some elements, and then removing some elements:
import java.util.*;
class Linkedlist
{
public static void main(String args[])
{
LinkedList<String> linkedlist1 = new LinkedList<String>();
linkedlist1.add("Item 2");
linkedlist1.add("Item 3");
linkedlist1.add("Item 4");
linkedlist1.add("Item 5");
linkedlist1.addFirst("Item 0");
linkedlist1.addLast("Item 6");
linkedlist1.add(1, "Item 1");
System.out.println(linkedlist1);
linkedlist1.remove("Item 6");
System.out.println(linkedlist1);
linkedlist1.removeLast();
System.out.println(linkedlist1);
System.out.println("\nUpdating linked list items");
linkedlist1.set(0, "Red");
linkedlist1.set(1, "Blue");
linkedlist1.set(2, "Green");
linkedlist1.set(3, "Yellow");
linkedlist1.set(4, "Purple");
System.out.println(linkedlist1);
}
}
Heres the output of this example:
[Item 0, Item 1, Item 2, Item 3, Item 4, Item 5, Item 6]
[Item 0, Item 1, Item 2, Item 3, Item 4, Item 5]
[Item 0, Item 1, Item 2, Item 3, Item 4]
Generics is on the leading edge of Object-Oriented Programming. You can move further without knowing much about generics,
but it is preferable to have an idea about them so as to get utter knowledge on how the ArrayList and LinkedList classes use the
new generic features.
788
Immediate Solutions
The formal type parameter <E> specifies the type of elements that are stored in the list. Compile the code now.
Now well make an example that works with the GenStack class:
import java.util.*;
The stack contains 4 items in the stack and the top item is Capsicum.
When the 4 items in the stack are Popped, they are displayed as:
Capsicum
Onion
Potato
Tomato
Now there are 0 item(s) in the stack and the top item is null.
789
Chapter 21: Collections
Heres an example in which we add elements to a set and then print out that set:
import java.util.*;
class Hashset
{
public static void main(String args[])
{
HashSet<String> hashset1 = new HashSet<String>();
hashset1.add("Item 0");
hashset1.add("Item 1");
hashset1.add("Item 2");
hashset1.add("Item 3");
hashset1.add("Item 4");
hashset1.add("Item 5");
hashset1.add("Item 6");
System.out.println(hashset1);
}
}
One thing to note about hashes is that you cant guarantee the order in which elements are stored internally. In
fact, when you print out this set, you can see that all elements are stored in exactly reverse order:
C:\>java Hashset
[Item 0, Item 4, Item 3, Item 2, Item 1, Item 6, Item 5]
790
Immediate Solutions
The TreeSet class just implements a set using a tree for internal storage. A difference from the HashSet class is
that elements in a TreeSet object are stored in sorted order. Heres the same example as the previous one,
where we stored elements in a HashSet object; however, this time we are using a TreeSet object:
import java.util.*;
class Treeset
{
public static void main(String args[])
791
Chapter 21: Collections
{
TreeSet<String> treeset1 = new TreeSet<String>();
treeset1.add("Item 0");
treeset1.add("Item 1");
treeset1.add("Item 2");
treeset1.add("Item 3");
treeset1.add("Item 4");
treeset1.add("Item 6");
treeset1.add("Item 5");
System.out.println(treeset1);
}
}
Heres the output of this example (note that, unlike the HashSet example in the previous solution, the TreeSet
elements are sorted in ascending order):
C:\>java Treeset
[Item 0, Item 1, Item 2, Item 3, Item 4, Item 5, Item 6]
In fact, you can specify the sorting order for the TreeSet objectssee the next solution for the details.
The compare() method compares two objects, obj1 and obj2, and returns -1 if obj1 is less than obj2; 0 if
they are equal; and 1 if obj1 is greater than obj2. By overriding this method, you can support a custom sorting
order.
Heres an example in which we sort a TreeSet object in ascending orderexcept for one element, Item 3, which
we always want to appear at the beginning of the set. Heres what this looks like in code:
import java.util.*;
class ComparatorDemo
{
@SuppressWarnings("unchecked")
public static void main(String args[])
{
TreeSet<String> treeset = new TreeSet<String>(new NewComparator());
treeset.add("Item 0");
treeset.add("Item 1");
treeset.add("Item 2");
treeset.add("Item 3");
treeset.add("Item 4");
treeset.add("Item 5");
treeset.add("Item 6");
Iterator iterator = treeset.iterator();
while(iterator.hasNext()) { System.out.println(iterator.next()); }
}
}
class NewComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
if (((String) obj1).equals("Item 3")) return -1;
792
Immediate Solutions
Heres an example in which we print out each element in a linked list from first to last using an iterator and the
methods next() and hasNext() (which returns True if the collection has a next element):
import java.util.*;
class IteratorDemo {
public static void main(String args[]) {
LinkedList<String> linkedlist = new LinkedList<String>();
linkedlist.add("Item 0");
linkedlist.add("Item 1");
linkedlist.add("Item 2");
linkedlist.add("Item 3");
linkedlist.add("Item 4");
linkedlist.add("Item 5");
linkedlist.add("Item 6");
Iterator<String> iterator = linkedlist.iterator();
while(iterator.hasNext()) { System.out.println(iterator.next()); }
}
}
Heres the output of this example:
C:\>java IteratorDemo
Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Besides iterators, you can also use list iterators. See the next solution.
Whereas iterators can only work forward through a list using the next() method, list iterators also support the
previous() method, so they can work backwards through lists. This is particularly useful for linked lists,
where each element often must know about the next and previous elements (called a bidirectional linked list). This
is handy, for example, when you are implementing a buffer that can grow or shrink. Youll find the methods of
the ListIterator interface in Table 21.29:
Table 21.29: Methods of the ListIterator interface
Method Does this
void add(E e) It inserts the given element into the list.
boolean hasNext() It returns True if this list iterator has more elements in the forward direction.
boolean hasPrevious() It returns True if this list iterator has more elements in the reverse direction.
E next() It gets the next element in the list.
int nextIndex() It gets the index of the element that would be returned by a subsequent call to
next().
E previous() It gets the previous element in the list.
int previousIndex() It gets the index of the element that would be returned by a subsequent call to
previous.
void remove() It removes from the list the last element that was returned by next or
previous.
void set(E e) It replaces the last element returned by next or previous with the given
element.
class Listiterator
{
public static void main(String args[])
{
LinkedList<String> linkedlist = new LinkedList<String>();
linkedlist.add("Item 0");
linkedlist.add("Item 1");
linkedlist.add("Item 2");
linkedlist.add("Item 3");
linkedlist.add("Item 4");
linkedlist.add("Item 5");
linkedlist.add("Item 6");
ListIterator<String> listiterator = linkedlist.listIterator();
while(listiterator.hasNext())
{
listiterator.set("This is " + listiterator.next()); }
while(listiterator.hasPrevious()) {
System.out.println(listiterator.previous()); }
}
}
Heres the output of this example:
C:\>java Listiterator
This is Item 6
This is Item 5
This is Item 4
This is Item 3
This is Item 2
This is Item 1
This is Item 0
Heres another example in which we modify and print an arraylist backwards:
import java.util.*;
class ListArray {
794
Immediate Solutions
795
Chapter 21: Collections
796
Immediate Solutions
The put() method is used to add a key/value pair to a map, and the get() method is used to retrieve a value,
given a key. For example, the string drink will be left holding the text root beer after this example executes:
hashmap.put("drink", "root beer");
String drink = hashmap.get("drink");
You can also get a set corresponding to the map with the entrySet() method, and you can iterate over that set
using the Map.Entry interface. Heres an example in which we create a map and then print out all the
key/value pairs in the map:
import java.util.*;
class Hashmap
{
public static void main(String args[])
{
HashMap<String, String> hashmap1 = new HashMap<String, String>();
hashmap1.put("Item 0", "Value 0");
hashmap1.put("Item 1", "Value 1");
hashmap1.put("Item 2", "Value 2");
hashmap1.put("Item 3", "Value 3");
hashmap1.put("Item 4", "Value 4");
hashmap1.put("Item 5", "Value 5");
hashmap1.put("Item 6", "Value 6");
Set set = hashmap1.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext())
{
Map.Entry mapentry = (Map.Entry) iterator.next();
System.out.println(mapentry.getKey() + "/" +
mapentry.getValue());
}
}
}
797
Chapter 21: Collections
798
Immediate Solutions
es\Java\jdk1.8.0_25\bin;;.
java.specification.name: Java Platform API Specification
java.class.version: 52.0
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
os.version: 6.3
user.home: C:\Users\Deepak Sharma
user.timezone:
java.awt.printerjob: sun.awt.windows.WPrinterJob
file.encoding: Cp1252
java.specification.version: 1.8
java.class.path: .
user.name: Deepak Sharma
java.vm.specification.version: 1.8
sun.java.command: SetEntry
java.home: C:\Program Files\Java\jre1.8.0_31
sun.arch.data.model: 64
user.language: en
java.specification.vendor: Oracle Corporation
awt.toolkit: sun.awt.windows.WToolkit
java.vm.info: mixed mode
java.version: 1.8.0_31
java.ext.dirs: C:\Program Files\Java\jre1.8.0_31\lib\ext;C:\Windows\Sun\Java\lib
\ext
sun.boot.class.path: C:\Program Files\Java\jre1.8.0_31\lib\resources.jar;C:\Prog
ram Files\Java\jre1.8.0_31\lib\rt.jar;C:\Program Files\Java\jre1.8.0_31\lib\sunr
sasign.jar;C:\Program Files\Java\jre1.8.0_31\lib\jsse.jar;C:\Program Files\Java\
jre1.8.0_31\lib\jce.jar;C:\Program Files\Java\jre1.8.0_31\lib\charsets.jar;C:\Pr
ogram Files\Java\jre1.8.0_31\lib\jfr.jar;C:\Program Files\Java\jre1.8.0_31\class
es
java.vendor: Oracle Corporation
sun.stderr.encoding: cp437
file.separator: \
java.vendor.url.bug: http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding: UnicodeLittle
sun.cpu.endian: little
sun.stdout.encoding: cp437
sun.desktop: windows
sun.cpu.isalist: amd64
799
Chapter 21: Collections
800
Immediate Solutions
801
Chapter 21: Collections
802
Immediate Solutions
803
Chapter 21: Collections
Heres an example in which we create an array, print it out, sort it, and then search for a particular element:
import java.util.*;
class ArrayDemo
{
public static void main(String args[])
{
int array[] = new int[10];
for(int loop_index = 9; loop_index > 0; loop_index--)
array[loop_index] = -loop_index;
for(int loop_index = 0; loop_index < array.length; loop_index++)
System.out.print(array[loop_index] + " ");
System.out.println();
Arrays.sort(array);
for(int loop_index = 0; loop_index < array.length; loop_index++)
System.out.print(array[loop_index] + " ");
System.out.println();
System.out.print("Found -5 at position " +
Arrays.binarySearch(array, -5));
}
}
Note that these are static methods and can be used without instantiating an object of this class.
Heres the output of this example:
C:\>java ArrayDemo
0 -1 -2 -3 -4 -5 -6 -7 -8 -9
-9 -8 -7 -6 -5 -4 -3 -2 -1 0
Found -5 at position 4
804
Immediate Solutions
features help the user in a great way. But what about Java? You say, No, you are wrong. The long felt need is
over. Now, there is an enumeration feature in Java too. But it functions a little different from other codes.
Lets talk about the basics of enumerations in detail. In the original version of Java, one feature is absent and
many programmers felt that this feature is one of the vital features in a code.
Many programmers felt that this was needed very much. This is known as Enumeration. In its simplest form,
you can define Enumeration as a list of named constants.
An Enumeration type can be considered to be a special form of class while defining an enumeration type at the
time of writing code. The specified enumeration constant gets created as objects of the class that contains the
enum class. This class is defined in the java.lang package as a superclass. The object corresponding to each
enumeration constants stores the constants name in a field. The toString() method is inherited by the
enumeration class type from the enum class.
Enumeration in Java is different in existence from other languages, though it seems to be similar. In C++,
enumeration is a list of named integer constants, while in Java, enumeration defines a class type. This concept is
elaborated by making enumeration into classes.
Using the new enum keywords, an Enumeration is created. For example, given here is a simple enumeration that
lists various Wheat varieties:
enum Wheat { Durum, Spelt, CommonWheat, Emmer }
Enumeration constants are the identifiers such as Durum, Spelt, and so on each of which is implicitly declared as
a public and static member of Wheat. In addition to this, their type is the type of enumeration in which they
are declared, which is Wheat in this case. These constants in Java are known as self-typed which self corresponds
to the enclosed enumeration.
You can create a variable of enumeration type once you have defined enumeration. However, it is found that,
even though enumeration defines a class type, you do not instantiate an enum by using a new. Instead, you
declare and use an enumeration variable in much the same way as you have done in the case of the primitive
types. For example, the code given here declares al as a variable of enumeration type Wheat:
Wheat al ;
The only values that al can assign are those defined by the enumeration, because al is of type Wheat. For
example, the value Emmer is assigned to al by this:
al= Wheat.Emmer;
The point to note here is that the symbol Emmer is preceded by Wheat. The == relational operator can be used
for comparing the two enumeration constants for equality.
For example, this statement compares the value in al with the Spelt constant:
if(al = = Wheat.Spelt) //.
An enumeration value can also be used for controlling a switch statement. Actually, it is very necessary that all
of the case statements must use constants from the same enum as that used by the switch expression. For
example, this switch is perfectly valid:
switch (al) {
case Spelt:
case CommonWheat :
In the case statements, you can note that the names of the enumeration constants can be used without being
qualified by the name of the enumeration type. For example, CommonWheat is used, but not
Wheat.CommonWheat. The reason behind this is that the type of the enumeration in the switch expression has
already implicitly declared the enum type of the case constants. So, for case statement, there is no requirement
for the constants to be passed with their enum type name. In fact, a compilation error will occur if you will do so.
When an enumeration constant is shown, such as in a println() statement, the result will be its name. For
example, in the given statement:
System.out.println(Wheat.Durum);
The name Durum is displayed as output. The code explained here will put together all the pieces and examine
the Wheat enumeration:
enum Wheat { Emmer,Durum, CommonWheat, Spelt }
class EnumDemo
805
Chapter 21: Collections
{
public static void main (String args[])
{
Wheat al;
al = Wheat.Emmer;
System.out.println("Value of al is : " + al);
System.out.println();
al = Wheat.Emmer;
if (al == Wheat.Spelt)
{
System.out.println ("al contains Spelt.\n");
}
switch(al) {
case Emmer:
System.out.println("It is ancient time wheat."); break;
case Durum:
System.out.println("It is second most widely cultivated wheat.");
break;
case CommonWheat:
System.out.println("It is most wildly cultivated wheat."); break;
case Spelt:
System.out.println("It is found in limited quantities."); break;
}
}
}
Heres the output is as follows:
Value of al is: Emmer
It is ancient time wheat.
806
Immediate Solutions
Spelt
al contains Durum
The point to be noted here is that this code uses a for-each style for loop to cycle through the array of
constants which can be obtained by calling values(). For better understanding, the variable allwheat was
formed and thus assigned a reference to the enumeration array. However, this step is not necessary to explain.
Because, by another way, the for could have been written as shown here by eliminating the need for the
allwheat variable:
for (Wheat a : Wheat.values()) { System.out.println(a); }
Now, you have to notice that, by calling valueOf(), the value corresponding to the name Durum is obtained:
al = Wheat.ValueOf (Durum);
We have discussed in the preceding topic that valueOf()returns the enumeration value related to the name of
the constant which is denoted as a string.
807
Chapter 21: Collections
When the variable ap is declared in main(), then the constructor for Mango is called once for each of the
constant which is specified. You have to notice how the argument to the constructor is specified, by putting them
inside parentheses after each constant, as shown here:
Brooks(10), Manilla(9), Alphanso(12), Kesar(15), Maya(8);
Here, these values are passed to the p parameter of Mango(), and after that, it assigns this value to price.
Again, for each of the constant, the constructor is called only once. The reason being that each enumeration
constant has its own copy of price. In order to obtain the price of a specified type of Mango, you can have it by
calling getPrice(). For example, in main(), the price of a Kesar is obtained by the following call:
Mango.Kesar.getPrice()
In order to obtain the prices of all varieties, you have to go by cycling through the enumeration using a for loop.
The reason is, there is a copy of price for each enumeration constant, and also the value associated with one
constant is separate and distinct from the value associated with another constant. As you have already noticed,
this is a powerful concept. This concept is only available when enumeration is implemented as classes, as Java
does.
In the preceding example, there is only one constructor, but an enum can provide multiple overloaded forms,
like it provides in any other class. For example, this version of Mango provides a default constructor that
initializes the price to 1, just to indicate that there is no price data available here:
enum Mango
{
Brooks(10), Manilla(9), Alphanso(), Kesar(15), Maya(8);
private int price;
Mango(int p) { price = p; }
Mango() {price = -1; }
int getPrice() { return price; }
}
However, please note that in this version, Alphanso is not given as an argument. This means that the default
constructor is called and the value 1 has been given to Alphansos price variable.
Lets mention about two different restrictions that apply to the enumeration. The first restriction to remember is
that an enumeration cant inherit another class. The second restriction is, an enum cannot be a superclass. To
make it simpler, an enum cant be extended.
808
Immediate Solutions
Questions that arise over here are what do you mean by ordinal value and how can you achieve it? You can
obtain a value that symbolizes an enumeration constants position in the list of constants. This is obtained by
calling the ordinal() method as follows:
final int ordinal()
The preceding statement returns the ordinal value of the invoking constant. Note that ordinal values begin at
Zero. Thus, Brooks has an ordinal value of Zero, Manilla has an ordinal value of 1, Alphanso has an ordinal
value of 2, and so on and so forth in the Mango enumeration.
You can perform comparison between the ordinal values of two constants of the similar enumeration by using
the compareTo() method. It has this general form:
final int compareTo(enum-type e)
where enum-type is the type of enumeration and e is the constant that is compared to the constant being
requested. Also keep in mind that both the requested constant and e must be of the same enumeration. If the
invoking constant has an ordinal value less than es, then compareTo()returns a negative value. Moreover, if
the two ordinal values are similar, then zero is returned, and if the value of the invoking constant is greater than
es, then compareTo() returns a positive value.
To obtain the equality, you can compare an enumeration constant with any other object by using equals(),
which overrides the equal() method defined by Object. Although equals() can compare an enumeration
constant to any other object, those two objects will remain equal if both of them refer to the same constant, that
too within the same enumeration. For better understanding, make a note that having ordinal values in common
will not cause equals() to return true if the two constants are from different enumerations.
As discussed earlier, you can perform the comparison between two enumeration references for equality by using
the == operator. You will get it by the following code which examines the ordinal(),compareTo(), and
equals() methods:
enum Mango { Brooks, Manilla, Alphanso, Kesar, Maya }
class Apple6
{
public static void main (String args[])
{
Mango ap, ap2, ap3;
System.out.println("Here are all mango constants" + " and their
ordinal values: ");
for (Mango a : Mango.values())
System.out.println(a +" " + a.ordinal());
ap = Mango.Alphanso;
ap2 = Mango.Manilla;
ap3 = Mango.Alphanso;
System.out.println();
if(ap.compareTo(ap2) < 0)
System.out.println(ap + " comes before " + ap2);
if(ap.compareTo(ap2) > 0)
System.out.println(ap2 + " comes before " + ap);
if(ap.compareTo(ap2) == 0)
System.out.println(ap + " equals " + ap3);
System.out.println();
if(ap.equals(ap2)) { System.out.println("Error"); }
if(ap.equals(ap3)) { System.out.println("Error"); }
809
Chapter 21: Collections
810
Immediate Solutions
811
Chapter 21: Collections
812
Immediate Solutions
Each vector has a capacity, which is the maximum size it can grow to. When you exceed that size, the capacity is
automatically increased. You can use the add() and addElement() methods to add elements to a vector, the
remove() and removeElement() methods to remove elements, and the contains() method to do a search.
Heres an example using the Vector class in which we create a vector, check its size and capacity, and search
for an element:
import java.util.*;
class VectorDemo
{
public static void main(String args[])
{
Vector<Number> vector = new Vector<Number>(5);
System.out.println("Capacity: " + vector.capacity());
vector.addElement(new Integer(0));
vector.addElement(new Integer(1));
vector.addElement(new Integer(2));
vector.addElement(new Integer(3));
vector.addElement(new Integer(4));
vector.addElement(new Integer(5));
vector.addElement(new Integer(6));
vector.addElement(new Double(3.14159));
vector.addElement(new Float(3.14159));
System.out.println("Capacity: " + vector.capacity());
System.out.println("Size: " + vector.size());
System.out.println("First item: " + (Integer)
vector.firstElement());
System.out.println("Last item: " + (Float) vector.lastElement());
if(vector.contains(new Integer(3)))
System.out.println("Found a 3.");
}
}
Heres the output of this example:
C:\>java VectorDemo
Capacity: 5
Capacity: 10
Size: 9
First item: 0
Last item: 3.14159
Found a 3.
813
Chapter 21: Collections
You use the push() method to add an element to a stack and the pop() method to retrieve it; note that
elements come off a stack in the reverse order in which they were added to it. Heres an example in which we
push and then pop elements on a stack:
import java.util.*;
class StackDemo
{
public static void main(String args[])
{
Stack<Integer> stack1 = new Stack<Integer>();
try {
stack1.push(new Integer(0));
stack1.push(new Integer(1));
stack1.push(new Integer(2));
stack1.push(new Integer(3));
stack1.push(new Integer(4));
stack1.push(new Integer(5));
stack1.push(new Integer(6));
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
System.out.println((Integer) stack1.pop());
}
catch (EmptyStackException e) { }
}
}
Heres the output of this example:
C:\>java StackDemo
6
5
4
3
2
1
0
814
Immediate Solutions
Youll find the constructor for Dictionary in Table 21.45 and its methods in Table 21.46:
Table 21.45: The constructor of the Dictionary class
Constructor Does this
Dictionary() It creates a dictionary.
815
Chapter 21: Collections
You store and retrieve key/value pairs in a hashtable using the put() and get() methods. You can get an
Enumeration object for the keys in a hashtable using the keys() method, and you can use that object to loop
over the elements of the hash. Heres an example in which we create a hashtable and then print out its
key/value pairs:
import java.util.*;
class HashTable
{
public static void main(String args[])
{
Hashtable<String, String> hashtable1 = new Hashtable<String, String>();
hashtable1.put("Item 0", "Value 0");
hashtable1.put("Item 1", "Value 1");
hashtable1.put("Item 2", "Value 2");
hashtable1.put("Item 3", "Value 3");
hashtable1.put("Item 4", "Value 4");
hashtable1.put("Item 5", "Value 5");
hashtable1.put("Item 6", "Value 6");
Enumeration keys = hashtable1.keys();
while(keys.hasMoreElements())
{
String key = (String) keys.nextElement();
System.out.println(key + "/" + hashtable1.get(key));
}
}
}
Heres the output of this example. Note that the hash determines the order in which elements are stored in a
hash, and you cant count on any specific order:
C:\>java HashTable
Item 0/Value 0
Item 6/Value 6
Item 5/Value 5
Item 4/Value 4
Item 3/Value 3
Item 2/Value 2
Item 1/Value 1
816
Immediate Solutions
You can put property values into a Properties object with the setProperty() method, and you can get
property values with the getProperty() method. Heres an example in which we create a Properties
object, add property values to it, and then retrieve a property value. Note, in particular, that you can supply a
default value to getProperty() that it will return if theres no property value matching the property you have
requested:
import java.util.*;
class PropertiesDemo
817
Chapter 21: Collections
{
public static void main(String args[])
{
Properties properties1 = new Properties();
Set states; String outString;
properties1.setProperty("Property 0", "Value 0");
properties1.setProperty("Property 1", "Value 1");
properties1.setProperty("Property 2", "Value 2");
properties1.setProperty("Property 3", "Value 3");
properties1.setProperty("Property 4", "Value 4");
properties1.setProperty("Property 5", "Value 5");
properties1.setProperty("Property 6", "Value 6");
outString = properties1.getProperty("Property 3", "Missing");
System.out.println(outString);
outString = properties1.getProperty("Property 7", "Missing");
System.out.println(outString);
}
}
Heres the output of this example:
C:\>java PropertiesDemo
Value 3
Missing
CountriesCapital() {}
CountriesCapital(int cCode, String cName, String capName, int states) {
this.CountryCode = cCode;
this.CountryName = cName;
this.CapitalName = capName;
this.States = states;
}
public String toString() {
return "" + CountryCode + ", " + CountryName + ", " + CapitalName + ", " + States;
}
}
Lets create a class with the name CountryCapitalDemo which uses the earlier created CountriesCapital class
in it:
import java.util.*;
import java.util.stream.*;
public class CountryCapitalDemo {
private static List<CountriesCapital> countriesCapital = Arrays.asList(
new CountriesCapital(91, "India", "Delhi", 36),
new CountriesCapital(1, "USA", "Washington", 50),
new CountriesCapital(43, "Austria", "Vienna", 40),
new CountriesCapital(86, "China", "Beijing", 55),
new CountriesCapital(81, "Japan", "Tokyo", 50),
new CountriesCapital(61, "Australia", "Canberra", 8),
new CountriesCapital(33, "France", "Paris", 27),
new CountriesCapital(64, "New Zealand", "Wellington", 53),
818
Immediate Solutions
String empName;
LocalDate empBirthday;
Sex empGender;
String empEmailAddress;
819
Chapter 21: Collections
return roster;
}
}
Lets now create a class with the name ReferenceMethodsDemo which uses the Employee class created earlier:
import java.util.*;
import java.util.function.Supplier;
820
Immediate Solutions
for (T tt : sCollection) {
res.add(tt);
}
return res;
}
Employee[] rstrArray =
roster.toArray(new Employee[roster.size()]);
class EmployeeAgeComparator
implements Comparator<Employee> {
public int compare(Employee e, Employee ee) {
return e.getBirthday().compareTo(ee.getBirthday());
}
}
Arrays.sort(rstrArray,
(Employee e, Employee ee) -> {
return e.getBirthday().compareTo(ee.getBirthday());
}
);
Arrays.sort(rstrArray, Employee::compareByAge);
class CmprsnProvider {
public int cmprByEmpName(Employee e, Employee ee) {
return e.getName().compareTo(ee.getName());
}
821
Chapter 21: Collections
Deepak, 27
Hari Narayan, 23
Puneet, 28
Nikhil, 23
Summary
In this chapter, you have read about the collections framework which included the Collection interface and
collection classes. You have also come across generics in Java.
In the next chapter, youll read about creating packages and interfaces. Youll also come across jar files and
annotations used in Java.
822
In Depth
22
Creating Packages,
Interfaces, JAR Files,
and Annotations
If you need an immediate solution to: See page:
Creating a Package 832
Creating Packages that have Subpackages 832
Creating an Interface 833
Implementing an Interface 834
Extending an Interface 835
Using Interfaces for Callbacks 835
Performing Operations on a JAR File 836
Marker Annotations 842
Single Member Annotations 843
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
In Depth
In this chapter, we are going to take a look at several important Java topicscreating packages, interfaces, JAR
files, and annotations. All these topics are popular and good to have under your belt.
JAR Files
To make it easier to download class files from the Web, Java supports Java Archive (JAR) files. The archives pack
files using the ZIP format, and youll see how to create JAR files and use them with the JAR tool that comes with
Java. In addition, JAR files are the foundation of other parts of Java, such as Java beans.
824
In Depth
825
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
826
In Depth
Basics of Annotation
The Java platform provides an annotation (also known as Metadata) facility that permits defining and use of
your own annotation types. It has specific syntaxes for declaring annotation types, for annotating declarations,
APIs for reading annotations, a class file representation for annotations, and an annotation-processing tool.
Although annotations do not affect the program semantics directly, they do affect the way used by tools and
libraries for treating programs, and that may affect the semantics of the running program. Annotations may be
reflected at runtime or may be read from the source files and/or class files. These also complement the use of
javadoc tags. A javadoc tag or an annotation is generally used for markup intended to produce or affect
documentation.
Annotation type declarations and normal interface declarations are quite similar. As in the interface keyword, an
at sign (@) precedes the annotation type declarations, which is further followed by a parenthesized list of
element-value pairs. Each method defined by the declaration defines an element of the annotation type. They
must not have any parameters or throws clause. Return types for this declaration are limited to String,
primitives, enums, Class, annotations, and arrays of the preceding types. Methods can have default
values. Shown here is an example of annotation type declaration:
public @interface RequestForEnhancement
{
int identification();
String abstract();
String operator() default "[unassigned]";
String date() default "[unimplemented]";
}
After defining an annotation type, the annotate declarations can be made. You can use annotation anywhere like
other modifiers, such as public, static, or final, as it is a special kind of modifier. Conventionally, other
modifiers are preceded by annotations. These values must be compile-time constants.
827
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Even though annotations cannot include the extends clause, they automatically extend the Annotation
interface. Thus, Annotation can be termed as the super-interface and is declared in the
java.lang.annotation package. Just look at this code:
@classic(txt = Know me, uni = 224)
public static void Classical() { . . . }
In the example, youll notice that within an annotation (@classic), its members are given values. This
annotation is linked with the method Classical().
@Retention Annotation
The @Retention annotation can only be used as an annotation to another annotation. Moreover, it provides
the retention policy for Java. A retention policy can determine the point with the help of which an annotation can
be discarded. The java.lang.annotation.RetentionPolicy class includes three such policies:
Retention policy of SOURCEAn annotation of this policy is not included during compilation and retained
only in the source file.
Retention policy of CLASSDuring compilation, an annotation of this policy gets stored in the class file
and does not have availability during runtime through the JVM.
Retention policy of RUNTIME In the class file, an annotation of this policy gets stored and is also available
at runtime through the JVM.
@Retentation (RetentionPolicy.RUNTIME)
@interface classica { }
In short, it can be said that the new Metadata facility lets you embed annotation into a program. Various
programming tools, in turn, process the annotations. For example, a tool might generate Java source code as
requested by an annotation. In the Metadata facility, a programmer describes an action, but relies on a tool in
actually providing the code. This type of approach reduces the amount of repetitious code that a programmer
may be required to enter manually resulting in considerable time saving.
@Documented Annotation
The @Documented annotation can be defined as a marker interface that informs a tool about the documentation
of an annotation. It can only be used as an annotation to an annotation declaration.
@Target Annotation
The @Target annotation defines the types of declaration to which an annotation can be applied. It is used as
annotation for other annotations as well. The @Target annotation takes on constant argument from the
828
In Depth
ElementType enumeration. This argument specifies the types of declaration to which the annotation can be
applied. Table 22.3 shows the constants along with the type of declaration to which they correspond:
Table 22.3: The Target constants and their type of declaration
Target constant Target annotation
ANNOTATION_TYPE Another annotation
CONSTRUCTOR Constructor
TYPE Class, interface, or enumeration
FIELD Field
LOCAL_VARIABLE Local variable
PARAMETER Parameter
PACKAGE Package
METHOD Method
In a @Target annotation, you can mention one or more of these values. You must specify multiple values inside
a braces-delimited list. For example, to specify that a @Target annotation applies only to fields and local
variables:
@Target ({ ElementType.FIELD, ElementType.LOCAL_VARIABLE })
@Native Annotation
The @Native annotation specifies a field that defines a constant value which can be referenced from native
code. This annotation can be used as a hint by tools that are used for generating native header files. These files
are used for determining whether a header file is needed or not, and if needed, then what declarations it should
have.
@Repeatable Annotation
The @Repeatable annotation is used for indicating that an annotation type whose declaration it (meta-) annotates
is repeatable. The value of the @Repeatable annotation specifies the stored annotation type for the repeatable
annotation type.
@Retention Annotation
The @Retention annotation specifies the time of retention of annotations having annotated type are to be
retained. The default value of the retention policy is RetentionPolicy.CLASS in case no Retention annotation
is available on as annotation type declaration.
The @Retention meta-annotation is affected only if you use the meta-annotated type directly for annotation.
@Inherited Annotation
The @Inherited annotation can be referred to as a marker annotation that can only be used on declaration of
another annotation. In addition to this, it only affects that annotation which is used on class declaration. The
@Inherited annotation allows the superclass annotation to be inherited by a subclass. Therefore, whenever a
request is made for a particular annotation to the subclass, the superclass is checked if the annotation for the
subclass is not available. Suppose that annotation is available in the superclass which is annotated with the
@inherited keyword, then an annotation is returned.
@Override Annotation
The @Override annotation is used only on methods and can be referred to as a marker annotation. A method
annotated with the @ Overdrive keyword needs to override a method from a superclass. If it does not
override a method, a compile-time error appears. This annotation can be used for ensuring overriding of a
superclass method.
829
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
@Deprecated Annotation
The @Deprecated annotation specifies that a declaration is removed and replaced by a newer form.
@SuppressWarnings Annotation
The @SuppressWarnings the annotation specifies suppressing of one or more notifications that might be
provided by the compiler. The suppressed notifications are required to be mentioned by names in the form of
string. You can apply this annotation to any type of declaration.
@FunctionalInterface
An informative annotation type is used for specifying an interface type declaration that is intended to be
a functional interface. Generally, a functional interface contains has exactlyonly one abstract method.
Since Default methods cannot be treated as abstract as they have an implementation.
You can create instances of functional interfaces by using lambda expressions, method references, or constructor
references.
Compilers must generat an error message, if a type is annotated with this annotation type, unless the following
conditions are satisfied:
The type is an interface type and not an annotation type, enum, or class.
The annotated type fulfills the need of a functional interface.
The compiler treats any interface satisfying the definition of a functional interface as a functional interface
sirrespective of whether or not a @FunctionalInterface annotation is available on the interface declaration.
@ SafeVarargs
Application of the @SafeVarargs annotation to a method or constructor suppresses unchecked notifications
about a non-reifiable variable arity (vararg) type and creation of parameterized array creation at call sites.
In addition to the imposing of usage restrictionsconstraints imposed applied by its HYPERLINK
"http://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Target.html" \o "annotation in
java.lang.annotation" @Target meta-annotation, compilers are need to implement more usage constraints on this
annotation type. It is a compile-time error in case of declaration of a method or a constructor annotated with
a @SafeVarargs annotation, and either:
the declaration is a fixed arity method or constructor, or
the declaration is a variable arity method neither static nor final.
Compilers issue notifications when this annotation type is used for to a method or constructor declaration,
where the following conditions hold:
The element type of the variable arity parameter is reifiable which includes primitive types: Object,
and String.
Unsafe operations are performed by the body of the method or constructor. Array Sometimes, unchecked
warnings are not generated by some unsafe operations. For example, consider the following code snippet:
@SafeVarargs // Not actually safe!
static void m(List<String>... stringLists) {
Object[] array = stringLists;
List<Integer> tmpLlist = Arrays.asList(42);
array[0] = tmpLlist; // Semantically invalid, but compiles without warnings
String str = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}
The aliasing in the preceding code snippet leads to the ClassCastException exception at runtime. The
statement arr[0]=tmplst is semantically invalid, but will execute without warnings. However, the statement
String str=stringLists[0].get(0) gets executed and will give the ClassCastException exception.
830
In Depth
Repeating Annotations
In Java SE8, you can use repeating annotations in situations where you want to apply the same annotation to a
declaration or type use. Suppose you want to use a timer service which allows you to execute a method at a
specified time like the UNIX cron service. For creating this timer service, you need to write a code. Using the
code, you can set a timer for executing a method, doPeriodicCleanup, on every months last day and on every
Saturday at 10:00 p.m. Now, in order to set the timer for execution, you need to write an @Schedule annotation
and use it twice for the doPeriodicCleanup method: first for specifying the last day of the month and the
second for specifying Saturday at 10 p.m., as shown in the following statements:
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Sat", hour="23")
public void doPeriodicCleanup() { ... }
In the preceding statements, an annotation to a method is applied. Now, you can repeat an annotation anywhere
so that you will be able to use a standard annotation. The repeating annotations are stored in a container
annotation that is generated automatically by the Java compiler for compatibility reasons. For making the
compiler to do this, the following two declarations are needed in your code:
The annotation type must be specified with the @Repeatable meta-annotation
The containing annotation type must contain a value element with an array type
Retrieving Annotations
Reflection API provides various methods that can be used for retrieving annotations. The behavior of these
methods remains unchanged, which return a single annotation, such as
AnnotatedElement.getAnnotationByType(Class<T>), if there is availability of one annotation of the requested
type. In case there is availability of more than one annotation of the requested type, you can retrieve them by
getting their container annotation first. In this way, legacy code functions continuously. Other methods were
also introduced in Java SE 8 for scanning through the container annotation for returning multiple annotations
together, such as AnnotatedElement.getAnnotations(Class<T>).
Thats it for the overview of what is in this chapter. Theres a great deal coming up, so its time to turn to the
Immediate Solutions section.
831
Immediate Solutions
Immediate Solutions
Creating a Package
Good Lord! says the Novice Programmer, I have so many classes that things are getting pretty cluttered now.
How can I wade through all this mess? Well, you say, why not divide your classes into packages? That will
let you arrange your class files in a directory structure much like youd arrange files when you have too many of
them. Problem solved. Great, says the NP, tell me how it works.
When you have a number of class files, its often a good idea to arrange them on disk by using a directory
hierarchy. In fact, Java packages were originally designed to reflect such a file organization. You can arrange
class files into a directory hierarchy and let Java know whats going on with the packages. For example, if you
have a package named package1 with one class in it, app.class, the class file would go into a directory
named package1, like this:
package1
|____app
Multiple class files in the same package go into the same directory:
package1
|____app1
|____app2
|____app3
As long as the package1 directory is in a location that Java will search (see Chapter 1 for more information on
where Java will search for class files and how to use the CLASSPATH environment variable), Java will look for
the class files you list as part of that package in that directory.
You need to indicate what package a class file is part of by using the package statement in your code. Heres an
example where we are creating app.class and indicating that its part of package1 by using the package
statement:
package package1;
public class app {
public static void main(String[] args) {
System.out.println("Hello from Java!"); }
}
After we have compiled app.class and stored it in the package1 directory, we can import the app class into
my code with statements such as the following, just as we would with any other Java package:
import package1.*;
or
import package1.app;
The Java runtime tool also knows about packages; since app.class is itself an application, we can run this
class with a command line that specifies the app classs package by using a dot (.) for the directory separator:
E:\Java8\chapter22>java package1.app
Hello from Java!
In fact, the dot package separator comes in handy when you create subpackages of packagestake a look at the
next solution for the details.
832
Immediate Solutions
package1
|____package2
|____app
To create this package structure in code, you just use the dot package separator. Heres an example:
package package1.package2;
Creating an Interface
Well, the NP says, I want to derive a new class from two base classes, but I know that Java doesnt support
multiple inheritance, so.... So you have to use interfaces, you say.
We have used interfaces throughout the book, and well take a look at how to create one here. When you create
an interface, you specify the methods for the interface, and when you implement the interface, you provide code
for those methods. Interfaces have two advantages over inheritance:
A class can extend to only one other class, but as many interfaces as you need.
They are easier to work with than interfaces because you dont have to provide any implementation details
in the interface.
Heres an example in which we create an interface named Printem that has one method: printText(). We
implement this interface in a class named class1. To create an interface, we simply use the interface
statement and list the prototypes (declarations without bodies) of the methods we want in the interface, like this:
interface Printem { void printText(); }
Now we can implement this interface in class1:
interface Printem { void printText(); }
class interfaces
{
public static void main(String[] args)
{
class1 object1 = new class1();
object1.printText();
}
}
class class1 implements Printem
{
public void printText() { System.out.println("Dreamtech Press"); }
}
833
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Implementing an Interface
You can create classes that partly implement an interface, but these classes must be declared abstract because
they are only partial implementations and therefore cannot be instantiated into objects. Heres an example in
which we create an interface with two methods: printText1() and printText2():
interface Printem { void printText1(); void printText2(); }
Next, we create a new class, Class1, that implements the interface but only defines one method,
printText1() (note that we must declare this class abstract as it is not a full implementation of the interface):
interface Printem { void printText1(); void printText2(); }
abstract class Class1 implements Printem
{
public void printText1() { System.out.println("Hello from Java!"); }
}
Finally, we can create a new class, Class2, that extends Class1 and defines the printText2() method,
which means we can instantiate objects of Class2 as shown here:
interface Printem { void printText1(); void printText2(); }
834
Immediate Solutions
Extending an Interface
Interfaces are extended with the use of extends keyword. An interface that is getting extended is known as the
superinterface; on the other hand, the interface which is extending an existing interface is known as the
subinterface.
public interface color
{
void blue();
void red();
}
public interface shirt
{
void sz1();
void sz2();
}
public interface combination extends color, shirt { void combin1(); }
When the extends keyword is used with interfaces, all the fields of the superinterface are copied into the
subinterface. In other words, three interfaces are declaredthe first defines two methods blue() and red();
the second defines two methods sz1() and sz2(); and the third extends color and shirt, and adds a
method of its own called combin1().
835
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Lets look at this example where we have implemented callbacks. In this example, a timer is implemented in the
class Ticking. This timer generates events after regular intervals and sets up a listener object for handling these
events:
import java.awt.event.*;
import javax.swing.*;
}
Here we have used the ActionListener interface that consists of a single method named
actionPerformed(). A parameter of type ActionEvent is received by the actionPerformed() method.
The result displays the messages Tick and Tock. on the console, as shown in Figure 22.3:
836
Immediate Solutions
Use an argument beginning with the character @ to specify a file containing additional arguments, one argument per line. The
arguments are inserted into the command line at the position of @filename argument.
837
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
838
Immediate Solutions
The JarFile class is built on the ZipFile class. Heres the inheritance diagram for the JarFile class:
java.lang.Object
|____java.util.zip.ZipFile
|____java.util.jar.JarFile
Youll find the field of the JarFile class in Table 22.6, its constructors in Table 22.7, and its methods in
Table 22.8:
Table 22.6: The field of the JarFile class
Field Does this
static String MANIFEST_NAME It holds the name of the manifest
You actually handle the items in a JAR file as JarEntry objects, and the JarEntry class is derived from the
ZipEntry class. Heres the inheritance diagram for ZipEntry:
java.lang.Object
|____java.util.zip.ZipEntry
839
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Youll find the fields of the ZipEntry class in Table 22.9, its constructors in Table 22.10, and its methods in
Table 22.11:
Table 22.9: Fields of the ZipEntry class
Field Does this
static int DEFLATED Specifies the compression method for compressed entries
static int STORED Specifies compression method for uncompressed entries
840
Immediate Solutions
841
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Next, we delete applett.class and open applett.java by using the Oracle appletviewer:
E:\Java8\chapter22>appletviewer applett.java
The result appears as shown in Figure 22.4:
Marker Annotations
A marker annotation is a special kind of annotation that is used for marking a declaration, and it does not
contain any members. The AnnotedElement interface defines the isAnnotationPresent() method,
which denotes whether the marker annotation is present. Since a marker interface contains no members, simply
determining whether it is present or not is sufficient. The code to implement the marker annotations is as
follows:
import java.lang.annotation.*;
import java.lang.reflect.*;
@Retention(RetentionPolicy.RUNTIME)
@interface Mark {}
class Marker
{
@Mark
public static void Meth ()
{
Marker obj = new Marker();
try {
Method mt = obj.getClass () .getMethod ("Meth");
if (mt.isAnnotationPresent (Mark.class))
System.out.println ("Here is the marker of that application");
System.out.println ("Welcome to DreamTech Press");
}
catch (NoSuchMethodException exc) {
System.out.println ("Method Not Found.");
}
}
public static void main (String args[])
{
Meth();
}
}
842
Immediate Solutions
@Retention(RetentionPolicy.RUNTIME)
@interface Sngle { int value(); }
class Single
{
@Sngle(100)
public static void Meth()
{
Single obj = new Single();
try { Method mt = obj.getClass().getMethod("Meth");
Sngle sng = mt.getAnnotation(Sngle.class);
System.out.println(sng.value()); }
catch (NoSuchMethodException exc)
{
System.out.println ("Method Not Found.");
}
}
public static void main(String args[]) { Meth(); }
}
As expected, the result of this program gets displayed as 100. In the program, @Sngle is used to annotate
Meth() as @Single(100). Notice the way a value is inserted. There is no need for value = .
843
Chapter 22: Creating Packages, Interfaces, JAR Files, and Annotations
Summary
In this chapter, You have learned about the concept of packages, interfaces, and JAR files. Then, you have
learned core Java API package and the java.lang package. We explored how to create a package, a
subpackage; create and implement an interface; and use interfaces for callbacks. Lastly, we have discussed how
to perform operations on a JAR file and use annotations.
The next chapter discusses working with Java Beans.
844
23
Working with Java Beans
If you need an immediate solution to: See page:
Understanding Java Beans 850
Designing Programs Using Java Beans 850
Creating Applets that Use Java Beans 853
Creating a Java Bean 853
Creating a Bean Manifest File 855
Creating a Bean JAR File 855
Creating a New Bean 855
Adding Controls to Beans 855
Giving a Bean Properties 856
Design Patterns for Properties 862
Using Simple Properties 862
Designing Patterns for Events 864
Learning Methods and Design Patterns 865
Creating Bound Properties 865
Giving a Bean Methods 866
Giving a Bean an Icon 867
Creating a BeanInfo Class 867
Setting Bound and Constrained Properties 868
Implementing Persistence 870
Using the Java Beans API 870
Learning the Basics of an Event 872
Using the Java Beans Conventions 873
Using the Remote Notification and Distributed Notification 873
Using Beans with JSP 873
845
Chapter 23: Working with Java Beans
In Depth
Sun provides the JavaBeans Bridge for ActiveX components. Beans are reusable components written in Java that
you can use in a variety of programming environments, including third-party programming environments. In
fact, they work much like ActiveX controls, exposing properties, methods, and events to other code components.
Using beans, you can create your own new Java controls, such as buttons that turn colors when you click them
or stock tickers that download information from the Internet.
Java Beans is designed to be used in application builder tools, which are programming environments that let you
configure beans. One such tool, the BeanBox, comes with the Sun Bean Development Kit (BDK), which you can
download and install from http://www.ecst.csuchico.edu/~amk/foo/csci611/notes/beans/BDK/.
Well use the BDK in this chapter to construct and use beans. As reusable code components that you can create
applications from, beans represent a powerful new way of looking at programmingyou can create your own
applications on the fly from pre-written components by adding just what you needand nothing more.
Java Beans has a very important part for the Java users. This part is very important. The reason for their
importance is they allow you to build complex systems from software components. Usually, there are different
vendors who supply these components, and sometimes, these components are also made available by you. Java
Beans defines the structural design that shows how the different building units work together.
While using a component-based approach, the software components can be easily reused and interoperability
between the components can also be made possible. This approach allows the programs to be collected from
software building blocks provided by different vendors to use the benefits. It is necessary for a designer to select
a component, understand it, and also check for its availability. Then, it becomes easy to implement its operation
into the existing code. Such kind of architecture is provided by Java Beans.
Oracle supports Java Beans in the java.beans package. We will discuss about the interfaces and classes under
this package in the Immediate Solutions section.
In this chapter, well create a number of Java Beansfrom simple ones to ones that support properties and
methods and let users embed other controls inside them.
The way you create beans varies a little among operating systems because the BDK differs a little among operating systems.
We use the BDK for Windows in this chapter.
846
In Depth
It provides support by explicitly providing property, method, and event information with a related Bean
information class. This Bean information class executes the BeanInfo interface. Also, the Bean
information class explicitly records the Bean features that are to be used for application builder tools.
Properties are the Beans look and its behavior, which can be modified at design time. Builder tools look
into a Bean to discover its properties and expose those properties for calculation.
The properties of Beans are customized at design time. Here, customization is achieved through two
methods, that is, by using property editors and by using more technical Bean customizers.
Beans use events in order to communicate with other Beans. Beans are of two types, namely, listener Bean
and source Bean. Listener Bean is a Bean that shows its interest in receiving events and registers its interest
with the source Bean. The source Bean is the Bean that fires the event. A Bean is monitored by Builder tools
to ascertain which events are sent and which events can be handled by the bean. Persistence enables Beans to
save and restore their state. Once we modify the properties of Beans, we can save the Beans state and
resume it later. Remember that property changes remain intact. Java Beans use Java Object Serialization to
support persistence. A Beans method can be invoked from other Beans or a scripting environment. The
methods are similar to Javas methods. Beans are created to be understood by builder tools and all key APIs,
including properties, events, and persistence, meant to be easily understandable by programmers. The
component technology is brought to the Java platform by the Java Beans. You can create reusable, platform-
independent components with the Java Beans API. All the components can be combined with the use of
Java Beans-compliant application builder tools into applets, applications, or composite components. Beans
are known as Java Bean components.
Introspection
Introspection is present at the core of Java Beans. It is defined as looking up or examining a Bean to determine its
functionalities. It allows another application, such as a design tool, to obtain information about a component;
therefore, it is an essential feature of the Java Bean API. The Java Bean technology cannot operate without
introspection.
There are two methods through which the developer can specify the properties, methods, and events needed to
be explored by an application builder tool. The first method uses the naming conventions that allow ways to
inspect the information about the Bean. In the second method, an additional class that extends the BeanInfo
interface is provided, which explicitly provides this information.
847
Chapter 23: Working with Java Beans
interactions taking place between classes or objects without showing the final application classes or objects that
are added.
Each design pattern consists of the following parts:
1. Problem/RequirementTo create a design pattern, the first step is to determine the requirements of the
problem to solve and the mini analysis of design followed by coding to test. This is usually a common
problem that will arise in more than one application.
2. ForcesForces indicate the technical boundaries that direct toward the solution of a problem.
3. SolutionThis section tells how to write the code to solve a problem. This is the design part of the design
pattern. It may contain class diagrams, sequence diagrams, and others to indicate how to write the code for
the solution.
A property represents a subgroup of a Beans state. The properties of a component are assigned some values that
represent its behavior and appearance. Properties can be of three types: simple, Boolean, and indexed.
Simple Properties
A simple property contains a single value. The following design patterns are used to identify it:
public K getName();
public void setName(K arg);
where Name is the name of the property and K is its type.
A read/write property contains both the get() and set() methods to access the values. A read-only property
contains a get() method and a write-only property contains a set() method.
Boolean Properties
A Boolean property consists of only two values, either true or false. It can be identified by the following design
patterns:
public boolean isN();
public boolean getN();
public void setN(boolean value);
where N is the name of the property.
Indexed Properties
An indexed property can have multiple values. The following design patterns are used to identify an indexed
property:
public K getName(int index);
public void setName(int index, K value);
public void setName(K values[]);
where Name is the name of the property and K is its type.
We will discuss these properties in Immediate Solutions section in detail.
848
In Depth
Persistence
Persistence means saving the current position, properties, and instance variables of a Bean. Basically, it means
restoring the current position of a Bean with the values of its properties and instance variables to nonvolatile
storage. One way to serialize a Bean is to implement the java.io.Serializable interface, which acts like a
marker interface. Implementing the java.io.Serializable interface makes serialization automatic.
We will discuss it in Immediate Solutions section in detail.
Customizers
The role of the customizer, which is provided by a Bean developer, is to help another developer configure
the Bean.
A customizer provides step-by-step information about the process to be followed to use a component in a
specific context.
To develop a customizer, a Bean developer has greater flexibility to differentiate his or her product in the
marketplace.
849
Chapter 23: Working with Java Beans
Immediate Solutions
Understanding Java Beans
The Novice Programmer appears and says, Hmm!! The user of Java seems to be a little confused about Java
Bean and its relation to Java class. Moreover, they ask about the different processes related to it and how these
processes function and help them. Java has described and solved these queries quite simply. You need not
worry about this. Since, a Java Bean can be any other Java class, both of these can be manipulated in a visual
builder tool and composed into any application as per the requirement of the user. There are certain other
advantages with regard to it, you say.
A Java Bean is any Java class that has limited conventions related to property and event interface definitions. It
can be calculated in a visual builder tool and formed into applications.
Introspection is the method by which a builder tool examines how a Bean operates and also discriminates Beans
from the Java classes. Beans have their predefined patterns for their method parameters and class definitions;
tools that identify these patterns can view inside a Bean and specify its properties and behavior.
Moreover, introspection calculates Beans state at design time, that is, the time it is gathered as a part from a
larger application. The parameters supplied to a method within Beans must follow a specific pattern so as to
help the introspection tools in identifying how Beans can be manipulated at runtime and design time.
850
Immediate Solutions
851
Chapter 23: Working with Java Beans
First, click the button bean in the BeanBox. The Properties window will display the properties you can set for
this bean, including its labelif you want to enter a new label for this button (such as Click Me), you can do it
in the Properties window (youll see how to set the properties of your own beans this way later). To make the
button do something when you click it, select the Edit | Events | action | actionPerformed menu item now.
When you do, a red line appears between the mouse location and the button. Stretch that line to the Juggler bean
now and click the Juggler bean, as shown in Figure 23.3. This connects the button and the Juggler bean.
852
Immediate Solutions
For this example, choose the stopJuggling() method to make the juggler stop juggling; then, click the OK
button to close the EventTargetDialog box.
Now, when you click the button in the BeanBox, the juggler will stop juggling. Congratulations, you have
connected two beans, thus creating a new program.
How do you actually run this program outside the BeanBox? Take a look at the next solution.
If you want to use any of the beans that come with the BDK in an applet JAR file, youll have to compile them first and make
sure the java compiler can find their class files. Youll find those beans in the demo\sunw\demo directory. In addition, youll need
to compile the AppletSupport.java file in the beanbox\sunw\beanbox directory and make sure the java compiler can find the
resulting class files.
The myApplet.jar file can be used with Web browsers and the Oracle appletviewer. Heres the HTML page
that well use with the myApplet.jar file:
<HTML>
<HEAD>
<TITLE>Beans applet example</TITLE>
</HEAD>
<BODY>
<APPLET>
CODE=MyApplet.class
WIDTH=200
HEIGHT=200>
<PARAM NAME=archive VALUE="myApplet.jar">
</APPLET>
</BODY>
</HTML>
After running the code, you can see the applet in the appletviewer.
853
Chapter 23: Working with Java Beans
Well place this bean in the BDKs demo directory, so we create a directory named bean
demo\sunw\demo\beanand store the class files for this bean in that directory. Well start the code,
bean.java, by indicating that this bean is part of a package named sunw.demo.bean:
package sunw.demo.bean;
import java.awt.*;
import java.awt.event.*;
. . .
As far as the actual bean class goes, we use the Canvas class to draw the bean itself (you can also use other
classes, such as the Panel class, which well cover in this chapter). The rest of the code is pretty ordinary; we
just add a mouse listener to the canvas to record mouse clicks and set the size of the canvas (thus setting the size
of the bean):
package sunw.demo.bean;
import java.awt.*;
import java.awt.event.*;
public class bean extends Canvas
{
int count;
public bean()
{
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent me) { clicked(); }
});
count = 0; setSize(200, 100);
}
. . .
}
Finally, we implement the method that handles mouse clicks, and we draw the bean, including the click count,
in the paint() method:
package sunw.demo.bean;
import java.awt.*;
import java.awt.event.*;
854
Immediate Solutions
855
Chapter 23: Working with Java Beans
import java.awt.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
856
Immediate Solutions
In fact, most beans dont implement the BeanInfo interface directly. Instead, they extend the
SimpleBeanInfo class, which implements BeanInfo. Heres the inheritance diagram for SimpleBeanInfo:
java.lang.Object
|____java.beans.SimpleBeanInfo
Youll find the constructor of the SimpleBeanInfo class in Table 23.3 and its methods in Table 23.4:
Table 23.3: The constructor of the SimpleBeanInfo class
Constructor Does this
SimpleBeanInfo() It constructs a BeanInfo object.
857
Chapter 23: Working with Java Beans
To actually describe a property, you use the PropertyDescriptor class, which in turn is derived from the
FeatureDescriptor class. Heres the inheritance diagram for the FeatureDescriptor class:
java.lang.Object
|____java.beans.FeatureDescriptor
Youll find the constructor of the FeatureDescriptor class in Table 23.5 and its methods in Table 23.6:
Table 23.5: The constructor of the FeatureDescriptor class
Constructor Does this
FeatureDescriptor() It constructs a feature descriptor
858
Immediate Solutions
Lets look at an example that implements a property in a Java Bean. In this case, well add a property named
filled to the click-counting operation developed in this chapter. This property is a Boolean property that,
when True, makes sure the bean will be filled in with color. Well call this new bean Bean2.
859
Chapter 23: Working with Java Beans
To keep track of the new filled property, well add a private Boolean variable of that name to the Bean2 class:
package sunw.demo.bean2;
import java.awt.*;
import java.awt.event.*;
public class Bean2 extends Canvas {
private boolean filled;
. . .
We initialize this property to False when the bean is created:
package sunw.demo.bean2;
import java.awt.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
860
Immediate Solutions
All thats left is to put the filled property to use. If its True, the bean should be filled in with color, so heres
the code we add to the paint() method:
public void paint(Graphics g)
{
Dimension dimension = getSize();
int height = dimension.height;
int width = dimension.width;
if(filled)
{
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, --width, --height);
}
g.setColor(new Color(0, 0, 0));
g.drawString("Click count = " + count, 50, 50);
}
Now we have to create a new class, Bean2BeanInfo, which will return information about this new bean
property. This class will go into the same package as the bean itself, but its based on the SimpleBeanInfo
class:
package sunw.demo.bean2;
import java.beans.*;
public class Bean2BeanInfo extends SimpleBeanInfo { . . . }
To let Java know about properties, you implement the getPropertyDescriptors() method, which returns
an array of PropertyDescriptor objects. Each PropertyDescriptor object holds the name of a property
and points to the class that supports that property. Heres how we create a PropertyDescriptor object for
the filled property:
package sunw.demo.bean2;
import java.beans.*;
public class Bean2BeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor filled = new
PropertyDescriptor("filled", Bean2BeanInfo.class);
. . . }
catch(Exception e) { }
return null; }
}
This is the only property in Bean2, so we add the new PropertyDescriptor object to an array and return it,
like this:
package sunw.demo.bean2;
import java.beans.*;
public class Bean2BeanInfo extends SimpleBeanInfo
{
public PropertyDescriptor[] getPropertyDescriptors()
{
try {
PropertyDescriptor filled = new
PropertyDescriptor("filled", Bean2BeanInfo.class);
PropertyDescriptor propertydescriptor[] = {filled};
return propertydescriptor;
}
catch(Exception e) {}
return null;
}
}
861
Chapter 23: Working with Java Beans
After compiling this new class (Bean2BeanInfo.java), we place Bean2BeanInfo.class in the directory
demo\sunw\demo\bean2, along with the classes created when we compiled Bean2.java. Well need a new
manifest file that includes the Bean2BeanInfo class. Heres what bean2.mft looks like:
Name: sunw/demo/bean2/Bean2.class
Java-Bean: True
Name: sunw/demo/bean2/Bean2BeanInfo.class
Java-Bean: True
We place this new manifest file in the demo directory. Finally, heres how we create the new bean2.jar file
and install it:
C:\...\demo>jar cfm ..\jars\bean2.jar bean2.mft .
Now when we run the BeanBox and add a new bean2 bean to the BeanBox, the new filled property will
appear in the Properties window. Setting filled to True causes the bean to be filled with color, which is also
shown in the figure.
862
Immediate Solutions
g.setColor(color);
g.fillRect(20, 5, 20, 30);
}
Compile, load in the Toolbox, and create an instance of the Bean. The following results are discussed here:
SimpleBean is shown with a green-centered rectangle.
Consequently, the Properties window will include a new color property. Simultaneously, the introspection
process will also look for a color property editor. A color property editor is one of the default editors
supplied with the BeanBox class, and is defined as SimpleBean's color property editor. To execute
this editor, click on the color property in the Properties window.
In simple language, Figure 23.6 shows the new SimpleBean instance within the BeanBox; SimpleBean's
new color property within the Properties window and the color property editor loaded with the BeanBox.
By menu or by RGB value, you can change the color property. Therefore, you can try to change colors. The
following is the complete SimpleBeanapp source code that has been revised to add a color property:
import java.awt.*;
import java.io.Serializable;
public class SimpleBeanapp extends Canvas implements Serializable {
private Color clr = Color.green;
public Color getColor() { return clr; }
public void setColor(Color newclr) {
clr = newclr;
repaint(); }
public void paint(Graphics g) {
g.setColor(clr);
g.fillRect(20, 5, 20, 30); }
public SimpleBeanapp() {
setSize(60,40);
setBackground(Color.red); }
}
The result is as shown in Figure 23.6:
863
Chapter 23: Working with Java Beans
864
Immediate Solutions
865
Chapter 23: Working with Java Beans
Many beans, however, dont bother to use MethodDescriptor objects, because any public bean method is
accessible from other beans. Heres an example in which we create a new bean based on the ones we have
developed in this chapter. This bean, Bean3, will count the number of times its been clicked and will also
support a method named increment() that, when invoked, will increment the click count.
Heres the code for Bean3, including the public increment() method:
package sunw.demo.bean3;
import java.awt.*;
import java.awt.event.*;
public class Bean3 extends Canvas {
int count;
public Bean3() {
addMouseListener(new MouseAdapter() {
866
Immediate Solutions
867
Chapter 23: Working with Java Beans
PropertyDescriptor foreground =
new PropertyDescriptor("foreground", beanClass);
PropertyDescriptor font =
new PropertyDescriptor("font", beanClass);
PropertyDescriptor label =
new PropertyDescriptor("label", beanClass);
background.setBound(true);
foreground.setBound(true);
font.setBound(true);
label.setBound(true);
PropertyDescriptor rv[] =
{background, foreground, font, label};
return rv; }
catch (IntrospectionException e) { throw new Error(e.toString()); }
}
If overriding is not done on the SimpleBeanInfo default method, which returns null, low-level reflection is
used for that characteristic. After overriding the appropriate method, associate an icon with the target Bean as
follows:
public java.awt.Image getIcon(int icontype)
{
if (icontype == BeanInfo.ICON_MONO_16x16 ||
icontype == BeanInfo.ICON_COLOR_16x16 ) {
java.awt.Image img = loadImage("tom.gif");
return img; }
if (icontype == BeanInfo.ICON_MONO_32x32 ||
icontype == BeanInfo.ICON_COLOR_32x32 ) {
java.awt.Image img = loadImage("ExplicitButtonIcon32.gif");
return img; }
return null;
}
The BeanBox then presents this icon next to the Bean name in the ToolBox. You can expect the builder tools to
do the same. Specify the target Bean class, and if the Bean has a customizer, specify it too as follows:
public BeanDescriptor getBeanDescriptor() {
return new BeanDescriptor(beanClass, customizerClass);
}
. . .
resulting,private final static Class beanClass = ExplicitButton.class;
private final static Class customizerClass = OurButtonCustomizer.class;
In the previous steps, locate the BeanInfo class in the same directory as its target class. Firstly, the BeanBox
searches for a target Beans BeanInfo class in the target Beans package path. If no BeanInfo is found, then
secondly the Bean information package searches path (maintained by the Introspector). The default Bean
information search path is sun.beans.infos. Again, if no BeanInfo class is found, then low-level reflection
is used to discover a Beans features.
868
Immediate Solutions
The task of the bound properties is to provide the registration and notification of parties whenever there is
modification in the values. The constrained properties take this notification model to a step ahead by allowing
the notified party to perform a veto in order to prevent the property change. Different from event handling, Java
Beans handle the bound and constrained properties.
To whom are the Bound properties useful? Bound properties are useful for Beans that want to allow instances of
the same Bean class or some other Bean class to monitor a property value and subsequently change their values
accordingly (i.e. to match the trend setting Bean). Lets cite an example. Consider a GUI Bean that wants to
allow other GUI Beans to keep a check on change in background color to update their backgrounds accordingly.
However, note that implementation of a bound property is quite easy because of the user-friendly underlying
framework provided by the Java Beans architecture. Bean class supports a bound property. In order to provide
a bound property, the Bean class must instantiate an object in the Java Beans framework, which provides a lot
of this functionality, and implements registration and unregistration methods that simply invoke the
appropriate methods in the Java Beans framework:
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener p) {
changes.addPropertyChangeListener(p);
}
public void removePropertyChangeListener(PropertyChangeListener p) {
changes.removePropertyChangeListener(p);
}
Each bound property must then invoke the firePropertyChange() method from its set() method:
public void setMood(int mood) {
int old = this.mood;
this.mood = mood;
repaint();
changes.firePropertyChange("mood",
new Integer(old), new Integer(mood));
}
At this level, the PropertyChangeSupport object handles the notification of all registered targets. You have to
keep in mind that the PropertyChangeSupport object provides a general-purpose functionality following a
prescribed protocol. Particularly, the method invocation for firePropertyChange() must provide the
property name as well as the old and new values, which are passed along to notified targets.
Moreover, the listener (i.e., target object) must provide a propertyChange() method to receive the property-
related notifications:
public void propertyChange(PropertyChangeEvent e) { } // . . .
Here, constrained properties add the functionality, which might be the notified listener that can object to the
property change and execute a veto. Additionally, the Bean class must instantiate the Java Beans object that
provides this service, namely, VetoableChangeSupport, and executes the corresponding registration-related
methods:
private VetoableChangeSupport veto = new VetoableChangeSupport(this);
public void addVetoableChangeListener(VetoableChangeListener vetolisten) {
veto.addVetoableChangeListener(vetolisten);
}
public void removeVetoableChangeListener(VetoableChangeListener vetolisten) {
veto.removeVetoableChangeListener(vetolisten);
}
Keep in mind that a Bean could provide one or more bound and one or more constrained properties. In this case,
it must instantiate both PropertyChangeSupport and VetoableChangeSupport and provide both sets of
registration-related methods. Also, constrained properties tend to be bound, but that is not an absolute
requirement. The set() method for bound-constrained properties is slightly more complicated:
public void setMood(int md)
throws PropertyVetoException {
vetoes.fireVetoableChange("mood",
new Integer(this.md), new Integer(md));
869
Chapter 23: Working with Java Beans
Implementing Persistence
As we have discussed in the In Depth section persistence is the process of restoring the current state of a Bean
and its properties with its instance variables also being restored at later stage. What helps to provide persistence
to Beans? The object serialization capabilities provided by the Java class libraries provide persistence to Beans.
Among the different methods available, the easiest way to serialize a Bean is to have it implement the
java.io.Serializable interface, which is nothing but a marker interface. Implementing
java.io.Serializable makes serialization automatic. Your Bean need not take any other action in this
regard. Moreover, remember that automatic serialization can also be inherited. So, if any superclass of a Bean
executes java.io.Serializable, then automatic serialization is achieved. But, the only restriction is that any
class that implements java.io.Serializable must supply a parameter-less constructor.
When the user is using automatic serialization, they can optionally avoid a field from being saved by the use of
the transient keyword. As a result, data members of a Bean specified as transient will not be serialized.
If a Bean does not implement java.io.Serializable, then we must provide serialization ourselves. This can
be done by implementing java.io.Externalizable. Else, the configuration of your component cannot be
saved by containers.
870
Immediate Solutions
Table 23.11 lists the interfaces in java.beans and provides description of their functionality, whereas Table
23.12 lists the classes in java.beans:
Table 23.11: The interfaces of java.beans
Interface Description
AppletInitializer This interface is used to initialize the Applet with Java Bean.
BeanInfo Any class that implements the BeanInfo interface provides explicit
information about the methods, properties, events, etc. of their bean.
Customizer This interface is used to customize a target Java Bean.
DesignMode This interface is used to define the notation of design time as a mode in
which JavaBean instances should function.
ExceptionListener This exception is thrown during any problem in listening.
PropertyChangeListener This interface is used to change the property of listener.
PropertyEditor This interface provides the methods that is used to edit the property.
VetoableChangeListener This interface is used to notify the any changes made in constrained
property.
Visibility This interface determines that bean needs GUI or not and whether GUI is
available.
871
Chapter 23: Working with Java Beans
872
Immediate Solutions
Remember that any Java class can be a Java Beans component if it follows specific design conventions.
The role of JavaServer Pages technology is also to provide direct supports using Java Beans components with JSP
language elements. Here, you can easily build and initialize beans and get and set the values of their properties.
873
Chapter 23: Working with Java Beans
Summary
In this chapter, you have learned about beans, using beans, adding control to beans, giving a bean properties,
simple properties, and design pattern for properties. Then, you have learned designing pattern and methods for
events. We also explained how to create bound properties, giving a bean methods, and give a bean an icon.
Then, we explored the BeanInfo class, set bound & constrained properties, and implement persistence. Toward
the end, we taught the basics of an event, Java Beans convention, use of remote notification and distributed
notification, and use of beans with JSP.
In the next chapter, we will introduce you with JDBC.
874
24
Introducing JDBC
If you need an immediate solution to: See page:
Learning about the Driver Interface 892
Learning about the DriverManager Class 892
The Connection Interface 893
The Statement Interface 896
The PreparedStatement Interface 899
Using the PreparedStatement Interface 902
The ResultSet Interface 904
Using ResultSet 907
The ResultSetMetaData Interface 908
Using the ResultSetMetaData Interface 910
Implementing JDBC Processes with java.sql Package 911
Processing the ResultSet 914
Closing the Statement 923
Closing the Connection 923
Using a Loop to Set Values in PreparedStatement Object 924
Using the Interactive SQL Tool 926
Chapter 24: Introducing JDBC
In Depth
Enterprise applications that are created using the Java EE technology need to interact with databases to store
application-specific information. For example, search engines use databases to store information about the Web
pages and job portals use databases to store information about the candidates and employers who access the
Web sites to search and advertise jobs on the Internet. Interacting with database requires database connectivity,
which can be achieved by using the Open Database Connectivity (ODBC) driver. This driver is used with Java
Database Connectivity (JDBC) to interact with various types of databases, such as Oracle, MS Access, My SQL,
and SQL Server. JDBC is an Application Programming Interface (API), which is used in Java programming to
interact with databases. JDBC works with different database drivers to connect to different databases.
This chapter focuses on JDBC, which is used to provide database connectivity to enterprise applications. In this
chapter, you first learn about JDBC drivers as well as the features of JDBC. You then learn about the JDBC APIs
that provide various classes and interfaces to develop a JDBC application. Next, the use of java.sql and javax.sql
packages in JDBC implementation is described in detail. Toward the end, you learn to work with transactions in
the JDBC application.
Components of JDBC
JDBC has four main components through which it can communicate with a database. These components are as
follows:
The JDBC APIProvides various methods and interfaces for easy and effective communication with the
databases. It also provides a standard to connect a database to a client application. The application-specific
user processes the SQL commands according to their need and retrieves the result in the ResultSet object.
The JDBC API provides two main packages, java.sql and javax.sql, to interact with databases.
These packages contain the Java SE and Java EE platforms, which conform to the Write Once Run
Anywhere (WORA) capabilities of Java.
The JDBC DriverManagerLoads database-specific drivers in an application to establish a connection with
the database. It is also used to select the most appropriate database-specific driver from the previously
loaded drivers when a new connection to the database is established. In addition, it is used to make
database-specific calls to the database to process the user requests.
The JDBC test suiteEvaluates the JDBC driver for its compatibility with Java EE. The JDBC test suite is
used to test the operations being performed by JDBC drivers.
The JDBC-ODBC bridgeConnects database drivers to the database. This bridge translates JDBC method
calls to ODBC function calls, and is used to implement JDBC for any database for which an ODBC driver is
available. The bridge for an application can be availed by importing the sun.jdbc.odbc package, which
contains a native library to access the ODBC features. The JDBC-ODBC bridge driver has been removed
from JDBC 4.2 API.
876
In Depth
JDBC Specification
With the emergence of JDBC 4.2, various changes, such as support for the REF_CURSOR data type and various
other features, have been introduced in JDBC API.
The specifications that are available in different versions of JDBC are as follows:
JDBC 1.0Provides basic functionality of JDBC.
JDBC 2.0Provides JDBC API in two sections: the JDBC 2.0 Core API and the JDBC 2.0 Optional Package
API.
JDBC 3.0Provides classes and interfaces in two Java packages: java.sql and javax.sql. JDBC 3.0 is a
combination of the JDBC 2.1 core API and the JDBC 2.0 Optional Package API. The JDBC 3.0 specification
provides performance optimization features and improves the features of connection pooling and
statement.
JDBC 4.0Provides the following advanced features:
Auto loading of the Driver interface
Connection management
ROWID data type support
Annotation in SQL queries
National Character Set Conversion Support
Enhancement to exception handling
Enhanced support for large objects
JDBC 4.1Introduces the following features:
It provides try-with-resources statement, which has the ability to close resources of type Connection,
ResultSet, and Statement automatically.
It has also introduced the RowSetFactory interface and the RowSetProvider class, which allow building
of all types of row sets that are supported by your JDBC driver.
JDBC 4.2Introduces the following features:
Provides support for REF_CURSOR data type that is supported by various databases
Includes the java.sql.DriverAction interface
Includes the java.sql.SQLType interface
Includes the java.sql.JDBCType enum
Includes support for large update count by returing a long value for it
JDBC Architecture
A JDBC driver is required to process the SQL requests and generate results. JDBC API provides classes and
interfaces to handle database-specific calls from users. Some of the important classes and interfaces defined in
JDBC API are as follows:
DriverManager
Driver
Connection
Statement
PreparedStatement
CallableStatement
ResultSet
DatabaseMetaData
ResultSetMetaData
SqlData
877
Chapter 24: Introducing JDBC
Blob
Clob
DriverAction
SQLType
JDBCType enum
In the JDBC architecture, the DriverManager class plays a significant role and is present in the JDBC API. It
uses some database-specific drivers to effectively connect enterprise applications to databases.
Figure 24.1 demonstrates the simple JDBC architecture:
878
In Depth
java.sql
javax.sql
The JDBC API includes both the java.sql package, called the JDBC core API, and the javax.sql package, called the
JDBC Optional Package API. Lets discuss them in detail in the following subsections.
Connection Management
The connection management category contains the classes and interfaces used to establish a connection with a
database.
Table 24.1 describes the classes and interfaces of the connection management category:
Table 24.1: Classes and interfaces of connection management
Class/Interface Description
java.sql.Connection Creates a connection with a specific database. You can use SQL statements to retrieve
interface the desired results within the context of a connection.
java.sql.Driver interface Creates and registers an instance of a driver with the DriverManager object.
java.sql.DriverManager Provides the functionality to manage database drivers.
class
java.sql.DriverPropertyInfo Retrieves the properties required to obtain a connection.
class
java.sql.SQLPermission Sets up logging stream with the DriverManager object.
class
Database Access
SQL queries are executed to access the application-specific data after a connection is established with a database.
The interfaces listed in Table 24.2 allow you to send SQL statements to the database for execution and read the
results from the respective database:
Table 24.2: Interfaces of the database access category
Interface Description
java.sql.CallableStatement Executes stored procedures.
java.sql.PreparedStatement Allows the programmer to create parameterized SQL statements.
java.sql.ResultSet Abstracts the results of executing the SELECT statements. This interface provides
methods to access the results row by row.
java.sql.Statement Executes SQL statements over the underlying connection and access the results.
java.sql.Savepoint Specifies a Savepoint in a transaction.
879
Chapter 24: Introducing JDBC
Data Types
In the JDBC API, various interfaces and classes are defined to hold specific types of data to be stored in a
database. For example, to store the BLOB type values, the Blob interface is declared in the java.sql package.
Table 24.3 describes the classes and interfaces of various data types in the java.sql package:
Table 24.3: Classes and interfaces for data types in the java.sql package
Class/Interface Description
java.sql.Array interface Provides mapping for ARRAY of a collection.
java.sql.Blob interface Provides mapping for the BLOB SQL type.
java.sql.Clob interface Provides mapping for the CLOB SQL type.
java.sql.Date class Provides mapping for the SQL type DATE. Although the java.util.Date class
provides a general-purpose representation of date, the java.sql.Date class is
preferable for representing dates in database-centric applications, as the type maps
directly to the SQL DATE type. Note that the java.sql.Date class extends the
java.util.Date class.
java.sql.NClob interface Provides mapping of the Java language and the National Character Large
Object types. The NClob interface allows you to store the values of the character
string up to the maximum length.
java.sql.Ref interface Provides mapping for SQL type REF.
java.sql.RowId interface Provides mapping for Java with the SQL ROWID value.
java.sql.Struct Provides mapping for the SQL structured types.
interface
java.sql.SQLXML Provides mapping for the SQL XML types available in the JDBC API.
interface
java.sql.Time class Provides mapping for the SQL type TIME and extends the java.util.Date class.
java.sql.Timestamp class Provides mapping for the SQL type TIMESTAMP and extends the java.util.Date
class.
java.sql.Types class Holds a set of constant integers, each corresponding to a SQL type.
The JDBC API provides certain User-Defined Data Types (UDT) available in JDBC API. The UDTs available in
the java.sql package are listed in Table 24.4:
Table 24.4: Interfaces for UDT in the java.sql package
Interface Description
java.sql.SQLData Provides a mapping between the SQL UDTs and a specific class in Java.
java.sql.SQLInput Provides methods to read the UDT attributes from a specific input stream. The input
stream contains a stream of values depicting the instance of the SQL structured or SQL
distinct type.
java.sql.SQLOutput Writes the attributes of the output stream back to the database.
JDBC API also provides some default data types that are associated with a database. The default types include
the DISTINCT and DATALINK types. The DISTINCT data type maps to the base type to which the base type
value is mapped. For instance, a DISTINCT value based on an SQL NUMERIC type can be mapped to a
java.math.BigDecimal type. A DATALINK type always represents a java.net.URL object of the URL class
defined in the java.net package.
880
In Depth
Database Metadata
The metadata interface is used to retrieve information about the database used in an application. JDBC API
provides certain interfaces to access the information about the database used in the application. These metadata
interfaces are described in Table 24.5:
Table 24.5: Interfaces of database metadata
Interface Description
java.sql.DatabaseMetaData This interface provides the comprehensive information about the database.
java.sql.ParameterMetaData The object of this interface is used to retrieve information about the types and
properties for each parameter provided in a PreparedStatement object .
java.sql.ResultSetMetaData The object of this interface is used to fetch the information about the types
and properties of the columns specified in a ResultSet object .
Lets now briefly discuss the JDBC extension APIs (javax.sql) available in JDBC API.
DataSource
The javax.sql.DataSource interface represents the data sources related to the Java application.
Table 24.7 describes the interfaces of the DataSource provided by the javax.sql package:
Table 24.7: Interfaces for DataSource
Interface Description
javax.sql.DataSource Represents the DataSource interface used in an application.
javax.sql.CommonDataSource Provides the methods that are common between the DataSource,
XADataSource and ConnectionPoolDataSource interfaces.
881
Chapter 24: Introducing JDBC
Distributed Transaction
The distributed transaction mechanism allows an application to use the data sources on multiple servers in a
single transaction. JDBC API provides certain classes and interfaces to handle distributed transactions over the
middle-tier architecture, as listed in Table 24.9:
Table 24.9: Interfaces for distributed transaction
Interface Description
javax.sql.XAConnection Provides the object that supports distributed transaction over middle-tier
architecture.
Rowsets Object
A RowSet object is used to retrieve data in a network. In addition, the RowSet object is able to transmit data
over a network. JDBC API provides the RowSet interface, with its numerous classes and interfaces, to work with
tabular data, as described in Table 24.10:
Table 24.10: Classes and interfaces for RowSet
Class/Interface Description
javax.sql.RowSetListener Receives notification from the RowSet object on the occurrence of an event.
interface
javax.sql.RowSetEvent class Provides the Event object, which is generated on the occurrence of an event on
the RowSet object.
javax.sql.RowSetMetaData Contains information about the columns specified in a RowSet object.
interface
javax.sql.RowSetReader Populates the disconnected RowSet object with rows of data.
interface
882
In Depth
Class/Interface Description
javax.sql.RowSetWriter Implements the RowSetWriter object, which is also called RowSet
interface writer.
javax.sql.RowSet interface Adds support to the JDBC API for the JavaBeansTM component model.
Figure 24.2: Application components using the JDBC API to interact with databases
883
Chapter 24: Introducing JDBC
Table 24.11: Showing the components for JDBC and ODBC with description
Component Description
Driver It translates API calls into operation for a specific data source.
Connection It is a session between an application and a database.
Statement It is a SQL statement to perform a query or update operation.
MetaData It gives information about returned data, the database, and the driver.
ResultSet It is the logical set of columns and rows of data returned by executing a
statement.
884
In Depth
Figure 24.3 shows the following steps that are involved in establishing connection between a Java application
and data source through the Type-1 driver:
1. The Java application makes the JDBC call to the JDBC-ODBC bridge driver to access a data source.
2. The JDBC-ODBC bridge driver resolves the JDBC call and makes an equivalent ODBC call to the ODBC
driver.
3. The ODBC driver completes the request and sends responses to the JDBC-ODBC bridge driver.
4. The JDBC-ODBC bridge driver converts the response into JDBC standards and displays the result to the
requesting Java application.
The Type-1 driver is generally used in the development and testing phases of Java applications.
885
Chapter 24: Introducing JDBC
As shown in Figure 24.4, the Java application that needs to communicate with the database is programmed using
JDBC API. In the client machine, the JDBC calls (programs created by using JDBC API) are then transformed into
database-specific native calls and the request is then sent to the database-specific native libraries. These libraries
present in the client are intelligent enough to send the request to the database server by using native protocol.
This type of driver is implemented for a specific database and usually delivered by a DBMS vendor. However, it
is not mandatory that Type-2 drivers have to be implemented by DBMS vendors only. An example of Type-2
driver is the Weblogic driver implemented by BEA Weblogic. Type-2 drivers can be used with server-side
applications. It is not recommended to use Type-2 drivers with client-side applications, since the database
specific native libraries should be installed on the client machines.
886
In Depth
The Type-3 drivers follow the 3-tier architecture model, as shown in Figure 24.5:
887
Chapter 24: Introducing JDBC
The three JDBC product components provided by JavaSoft as a part of the Java Development Kit (JDK) are as
follows:
The JDBC Driver Manager
The JDBC Driver Test Suite
The JDBC-ODBC Bridge
The JDBC driver manager is the backbone of the JDBC architecture. It is very small and simple. The basic
function of this is to connect Java applications to the correct JDBC driver and subsequently get out of the way.
The second one, i.e., JDBC driver test suite, enables the JDBC drivers to run your program. The designation
JDBC ComplaintTM should only be used by the drivers that have passed the JDBC driver test suite.
The third one, i.e., the JDBC-ODBC Bridge, allows ODBC drivers to be used as JDBC drivers. The javasoft
framework is shown in Figure 24.7:
In the three-tier model, a middle tier exists, which acts as a bridge between the Java application and the data
source. Then, when responding back, the data source sends the result to the middle-tier, which then transmits it
to the user. Management Information System directories find the three-tier model useful because the middle tier
allows control over access. Another benefit is that it simplifies the deployment of applications. Also, three-tier
architecture has a better performance than two-tier architecture. Earlier, languages such as C and C++ are used
for creating the middle tier which provides fast performance in accessing data from database. Using optimizing
compilers for translating Java bytecode into machine-specific code and technologies such as Enterprise Java
Beans, the Java platform is used as the standard platform for middle-tier development. It provides Java with
robustness, multithreading, and security features. The three-tier architecture is shown in Figure 24.9:
The UPDATE annotationUpdates the queries used in database tables. The UPDATE annotation must
include the SQL annotation type to update the fields of a table.
890
In Depth
There are certain enhancements in the SQLException class, which are as follows:
New exception subclassesProvide new classes as enhancement to SQLException. The new classes that
are added to the SQLException exception class include SQL non-transient exception and SQL transient
exception. The SQL non-transient exception class is called when an already performed JDBC operation fails
to run unless the cause of the SQLException exception is corrected. On the other hand, the SQL transient
exception class is called when a previously failed JDBC operation succeeds after retry.
Casual relationshipsSupport the mechanism of Java SE chained exception by the SQLException class
(also called Casual facility). It allows handling multiple SQL exceptions raised in the JDBC operation.
Support for the for-each loopImplements the chain of exceptions in a chain of groups by the
SQLException class. The for-each loop is used to iterate on these groups.
SQL XML supportIntroduces the concept of XML support in SQL DataStore. Some additional APIs have
been added to JDBC 4.0 to provide this support.
891
Chapter 24: Introducing JDBC
Immediate Solutions
Learning about the Driver Interface
The Driver interface is used to create connection objects that provide an entry point for database connectivity.
Generally, all drivers provide the DriverManager class that implements the Driver interface and helps to
load the driver in a JDBC application. The drivers are loaded for any given connection request with the help of
the DriverManager class. After the driver class is loaded, its instance is created and registered with the
DriverManager class.
Table 24.14 describes all the methods provided in the Driver interface:
Table 24.14: Methods of the Driver interface
Method Description
boolean acceptsURL(String url) Checks whether or not the specified URL format is acceptable by the
driver.
Connection connect(String url, Establishes the connection with the database by using the given URL.
Properties info)
int getMajorVersion() Accesses the major version number of the driver.
int getMinorVersion() Retrieves the minor version number of the driver.
DriverPropertyInfo[] Retrieves the properties of the driver on the basis of the given URL.
getPropertyInfo(String url,
Properties info)
boolean jdbcCompliant() Reports whether the current driver is a genuine JDBC CompliantTM
driver.
Logger getParentLogger() Returns the parent Logger of all the Loggers used by this driver.
892
Immediate Solutions
893
Chapter 24: Introducing JDBC
Statement createStatement Creates an object with the mentioned type, concurrency, and
(int resultSetType, holdability.
int resultSetConcurrency,
int resultSetHoldability)
boolean getAutoCommit() Retrieves the auto-commit mode for the current Connection object.
String getCatalog() Gets the name of the current catalog used in the current Connection
object.
int getHoldability() Gets the current holdability of the ResultSet object created by using
a Connection object.
int getTransactionIsolation() Provides the transaction isolation level of the Connection object
related to a database.
Map getTypeMap() Gets a map object related to a Connection object.
String nativeSQL(String sql) Allows you to convert the SQL statements passed to the Connection
object into the systems native SQL grammar.
894
Immediate Solutions
void setCatalog(String catalog) Sets the given catalog name for the current Connection objects
database.
void setHoldability(int holdability) Changes the holdability of the current Connection object.
void setReadOnly(boolean readOnly) Sets the connection to the read-only mode to optimize the specified
database.
Savepoint setSavepoint() Creates an unnamed savepoint in the current transaction and returns
the savepoint associated with the previous transactions.
Savepoint setSavepoint(String name) Creates a savepoint with the name specified in the current transaction.
It returns the new savepoint object
void Checks the transaction isolation level of the specified Connection
setTransactionIsolation(int level) object.
void setTypeMap(Map<String, Installs the TypeMap object as the current type map for the current
Class<?>> map) connection.
Array createArrayOf(String typeName, Refers to a Factory method used to create Array objects.
Object[] elements)
Blob createBlob() Creates an object implementing the Blob interface.
Clob createClob() Creates an object implementing the Clob interface.
NClob createNClob() Creates an object implementing the NClob interface.
SQLXML createSQLXML() Creates an object implementing the SQLXML interface.
Struct createStruct(String typeName, Refers to the factory method that creates Struct objects.
Object[] attributes)
The Connection interface also provides certain fields that can be used to handle connection transactions.
895
Chapter 24: Introducing JDBC
896
Immediate Solutions
897
Chapter 24: Introducing JDBC
void setCursorName(String name) Sets the cursor name to the given string. The cursor name is used by
the Statement objects to execute this method.
void setEscapeProcessing(boolean Sets the escape processing on or off.
enable)
void Sets the direction for the driver to process the rows in the ResultSet
setFetchDirection(int direction) object.
void setFetchSize(int rows) Sets the number of rows that should be fetched from the database.
void setMaxFieldSize(int max) Sets the maximum number of bytes for the ResultSet object to store
binary values.
void setMaxRows(int max) Sets the maximum number of rows that a ResultSet object can contain.
void setQueryTimeout(int seconds) Sets the number of seconds a driver needs to wait for executing the
Statement object.
The Statement interface also comprises few fields. Table 24.19 describes the fields available in the Statement
interface:
Table 24.19: Fields of the Statement interface
Field Description
static int CLOSE_ALL_RESULTS Closes all the open ResultSet objects. All the ResultSet objects
should be closed before calling the getMoreResults() method.
static int CLOSE_CURRENT_RESULT Indicates that the current ResultSet connected with the specified
database must be closed before calling the getMoreResults()
method.
static int EXECUTE_FAILED Indicates the occurrence of errors while executing a batch statement.
static int KEEP_CURRENT_RESULT Indicates that the current Resultset should not be closed before
calling the getMoreResults() method.
static int NO_GENERATED_KEYS Indicates that the generated keys should not be made available for
retrieval.
static int RETURN_GENERATED_KEYS Indicates that the generated keys should be made available for
retrieval.
static int SUCCESS_NO_INFO Indicates that a batch statement has been executed successfully.
Table 24.18 shows all the required fields in the Statement interface. These are used by a database to
communicate with an application.
898
Immediate Solutions
The Statement object is created after the connection to the specified database is made. You can create this
object with the help of the createStatement()method provided by the Connection interface, as shown in
the following code snippet:
Connection con = DriverManager.getConnection (url, "username", "password");
Statement stmt = con.createStatement();
899
Chapter 24: Introducing JDBC
statements are known as pre-compiled SQL statements. DBMS intelligently maintains the compiled queries and
provides a unique identity for the prepared execution plan, which the client uses to execute the same query next
time. JDBC specifications support the use of this feature provided by DBMS. The PreparedStatement
interface is designed specifically to support this feature.
The execution of pre-compiled PreparedStatement is much faster in comparison to the Statement objects
included in an application. The PreparedStatement interface inherits all the properties of the Statement
interface. The execute methods do not take any parameter while using the PreparedStatement object.
You should keep in mind the following points while using the PreparedStatement interface:
A PreparedStatement object must be associated with one connection
A PreparedStatement object specifies the running plan of a query, which is then passed as argument
during the creation of the PreparedStatement object
After the connection on which the PreparedStatement object was created is closed,
PreparedStatement is implicitly closed
When a PreparedStatement object is used to execute a query (that is, calling any one of the execute
methods), the query is processed as follows:
The prepareStatement() method of the connection object is used to get the object of the
PreparedStatement interface.
The connection object submits the given SQL statement to the database.
The database compiles the given SQL statement.
An execution plan is prepared by the database to execute the SQL statements.
The database stores the execution plan with a unique ID and returns the identity to the Connection
object.
The Connection object prepares a PreparedStatement object, initializes it with the execution plan
identity, and returns the reference of the PreparedStatement object to the Java application.
The setXXX() methods of the PreparedStatement object are used to set the parameters of the SQL
statement it is representing .
The executeXXX() method of the PreparedStatement object is invoked to execute the SQL statement
with the parameters set to the PreparedStatement object
The PreparedStatement object delegates the request sent by a client to the database.
The database locates and executes the execution plan with the given parameters.
Finally, the result of the SQL statements is sent to the Java application in the form of ResultSet.
Figure 24.11 explains the flow of execution when PreparedStatement is used to execute SQL statements:
900
Immediate Solutions
In Figure 24.11, the con and ps elements represent the references of the Connection and
PreparedStatement objects, respectively.
901
Chapter 24: Introducing JDBC
902
Immediate Solutions
PreparedStatement is used to increase the efficiency and reduce the execution time of a query. An instance of
PreparedStatement must be created to execute a precompiled SQL statement. Follow these broad-level steps
to use the PreparedStatement interface:
1. Create a PreparedStatement object
2. Provide the values of the PreparedStatement parameters
3. Execute the SQL statements
Lets discuss each of these steps in detail.
903
Chapter 24: Introducing JDBC
"jdbc:oracle:thin:@localhost:1521:XE","scott","tiger");
String query="insert into mytable values (?,?,?)";
//Step1: Get PreparedStatement
PreparedStatement ps=con.prepareStatement (query);
//Step2: set parameters
ps.setString(1,"abc1");
ps.setInt(2,38);
ps.setDouble(3,158.75);
//Step3: execute the query
int i=ps.executeUpdate();
System.out.println("record inserted count:"+i);
//To execute the query once again
ps.setString(1,"abc2");
ps.setInt(2,39);
ps.setDouble(3,158.75);
i=ps.executeUpdate();
System.out.println("query executed for the second time count: "+i);
con.close();
}//main
}//class
The preceding code uses the PreparedStatement object along with the connection object. The setXXX()
methods are used to set the values of the arguments. The preceding example sets the values of the integer, string,
and double data types. The executeUpdate() method is used to retrieve the number of rows affected by
executing the SQL statement.
The output of the PreparedStatementEx1.java is shown in Figure 24.12:
904
Immediate Solutions
void cancelRowUpdates() Cancels all the changes made to the rows in the ResultSet object.
void clearWarnings() Clears all warning messages on a ResultSet object.
void close() Closes the ResultSet object and releases all the JDBC resources connected
to it.
void deleteRow() Deletes the specified row from the ResultSet object and the database.
boolean first() Moves the cursor to the first row in the ResultSet object.
Array getArray(int columnIndex) Retrieves the value of the specified column from the ResultSet object.
InputStream getAsciiStream(int Retrieves a specified column in the current row as a stream of ASCII
columnIndex) characters.
Date getDate(int columnIndex) Retrieves the column values of the specified types from the current row.
The type can be any of the Java predefined data types, such as int, long,
byte, character, string, double, or large object types.
Date getDate(String columnLabel) Retrieves the specified column from the current row in the ResultSet
object. The object retrieved is of the java.sql.Date type in the Java
programming language.
Date getDate(String columnName, Retrieves the specified column from the current row in the ResultSet
Calendar cal) object. The object retrieved is of the java.sql.Date type.
int getFetchDirection() Specifies the direction (forward or reverse) in which the ResultSet object
retrieves the row from a database.
int getFetchSize() Retrieves the size of the associated ResultSet object.
ResultSetMetaData getMetaData() Retrieves the number, type, and properties of the ResultSet object.
Object getObject(int columnIndex) Retrieves a specified column in the current row as an object in the Java
programming language on the basis of the column index value passed as
a parameter.
Object getObject(int columnIndex, Retrieves a specified column as an object on the basis of the column
Map <String, Class<?>>map) number and Map instance passed as parameters.
Object Retrieves a specified column in the current row as an object on the basis of
getObject(String columnLabel) the column name passed as a parameter.
Object Retrieves a specified column in the current row as an object on the basis of
getObject(String columnLabel, the column name and Map instance passed as parameters.
Map<String,Class<?>> map)
int getRow() Retrieves the current row number associated with the ResultSet object.
Statement getStatement() Retrieves the Statement object associated with the ResultSet object.
Time getTime(int columnIndex) Retrieves the column values as a java.sql.Time object on the basis of
column index passed as an integer parameter.
Time getTime(int columnIndex, Retrieves the column values as a java.sql.Time object on the basis of
Calendar cal) column index as well as the cal object of the Calendar class passed as
parameters.
Time getTime(String columnName) Retrieves the column values as a java.sql.Time object on the basis of
column name passed as a String value.
Time getTime(String columnName, Retrieves the column values as a java.sql.Time object on the basis of
Calendar cal) String value of column name as well Calendar object cal as parameters.
905
Chapter 24: Introducing JDBC
906
Immediate Solutions
Using ResultSet
After obtaining a ResultSet object, you can use a ResultSet to read the data (ResultSet content) encapsulated in it.
Figure 24.13 shows the process flow involved in getting ResultSet from the Statement object and reading the data
from the ResultSet object. The st and rs parameters represent the Statement and ResultSet object references,
respectively.
Figure 24.13 shows the ResultSet operations:
907
Chapter 24: Introducing JDBC
JDBC 2.0 also introduces some other methods in ResultSet to move the cursor position, provided the ResultSet is of the
scrollable type. The ResultSet generated is forwarded by default; therefore, you can iterate through it only in the forward
direction from the first to the last row.
908
Immediate Solutions
JDBC API provides two interfaces, ResultSetMetaData and DatabaseMetaData, to provide the metadata
information of a database. The ResultSetMetaData interface offers information about the columns in a
ResultSet object, such as the column name, column data type, and length of the columns. The DatabaseMetaData
interface provides information about the database structure, table names, views, constraints used in the
database, and data types.
909
Chapter 24: Introducing JDBC
After having the theoretical knowledge about the ResultSetMetaData interface, lets create an application to
demonstrate the implementation of this interface.
Driver d=(Driver)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
Properties p= new Properties ();
p.put ("user", "scott");
p.put ("password", "tiger");
Connection con=d.connect ("jdbc:oracle:thin:@192.168.1.123:1521:XE ",p);
// Creating a Statement object
Statement st = con.createStatement ();
int colcount=rsmd.getColumnCount();
910
Immediate Solutions
The preceding code is used to access the properties of the ResultSet object by using the object of
ResultSetMetaData. The ResultSet object invokes the getMetaData() method, which returns the
ResultSetMetaData object that is further used to retrieve the column name, types, and length for a specific
ResultSet. In ResultSetMDEx, the table for the ResultSet object is given as an argument in the command line. The
ResultSetMDEx.java application retrieves the columns of the designated table along with the column types and
displays it to the user. The user can then put any of the existing tables as a command line argument to retrieve
the MetaData information about that table. The output of ResultSetMDEx.java is shown in Figure 24.15(a),
24.15(b), and 24.15(c), which displays various tables, such as mytable, dept, and emp, respectively, used as
arguments:
Figure 24.16: Showing the exception while accessing table that is not available in a database
Figure 24.16 shows the output while accessing a table not present in the database.
Obtaining a Connection
To obtain an object of the Connection interface, you need to first register a driver with the DriverManager class
by invoking the registerDriver() method, setting the System property, or invoking the Class.forName()
method. Then the connection is obtained by using the java.sql.DriverManager class.
You need to perform the following steps to obtain a connection using the DriverManager class:
a. Register a Driver object with DriverManager.
b. Establish a connection using DriverManager.
Now, lets discuss each of these steps in detail.
Register a Driver object with DriverManager
Registering a driver with the DriverManager class makes the registered driver available to the DriverManager
class so that the DriverManager object can use it to establish a connection with the database. When a driver is
registered with the DriverManager class, it creates the DriverInfo object to maintain the driver details and
stores these details in a class variable of the java.util.Vector type.
912
Immediate Solutions
//oracleURL = jdbc:oracle:oci8:@kogent
913
Chapter 24: Introducing JDBC
If the statement produces a ResultSet object after executing the SQL statements, the ResultSet instance is used to
retrieve the result. The next() method is invoked on the ResultSet object to navigate through a row at a time.
The following code snippet shows the use of the ResultSet object within a connection:
while(results.next())
{
System.out.println(results.getString(1) + " " +
results.getString(2) + " " +
results.getString(3));
}
Connection con=d.connect(jdbc:oracle:thin:@localhost:1521:XE,p);
Statement st= con.createStatement (
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
System.out.println("EmpNo\tName");
while (rs.next()) {
914
Immediate Solutions
System.out.print(rs.getInt(1)+"\t");
System.out.println(rs.getString(2));
}//while
//Now the cursor of ResultSet will at afterLast
System.out.println(
"Reading Data, moving the cursor in backward direction\n");
while (rs.previous()){
System.out.print(rs.getInt(1)+"\t");
System.out.println(rs.getString(2));
}//while
con.close();
}//main
}//class
In the preceding code, the Connection.createStatement(int, int) method is used to create a Statement
object that can produce scrollable ResultSet. Here we have used ResultSet.TYPE_SCROLL_INSENSITIVE
to specify the ResultSet type, which indicates that ResultSet is only scrollable and insensitive to any
changes made to the data in the associated database. In addition, we have used
ResultSet.CONCUR_READ_ONLY to specify the concurrency type, which describes that the ResultSet object
does not allow you to make changes. It also uses the cursor movement methods, such as ResultSet.next()
and ResultSet.previous(). The ResultSet.next() method is used to move the ResultSet cursor to
the next record in the forward direction, whereas the ResultSet.previous() method is used to move the
ResultSet cursor to the previous record in the backward direction from the current cursor position. The output
of ScrollableRSEx1 is shown in Figure 24.18:
Driver d= (Driver)(Class.forName(
"oracle.jdbc.driver.OracleDriver").newInstance());
915
Chapter 24: Introducing JDBC
System.out.println ("Index\tEmpNo\tName");
int i=1;
while (rs.next()){
System.out.print ((i++)+"\t");
System.out.print (rs.getInt(1)+"\t");
System.out.println (rs.getString(2));
}//while
System.out.println ();
rs.absolute(3);
/*
To move the cursor to first record we can use
rs.first(); or with reference to the current row we can use
*/
rs.relative(-2);
916
Immediate Solutions
ResultSet.absolute(3) method. The integer argument passed to the method specifies the record position to
which the cursor is to be moved. The ResultSet.relative(int n) method is used to jump to n rows
forward or backward within the ResultSet, depending on the sign of n. The negative values allow the cursor
to move backward from the current position; however, the positive values move the cursor forward from the
current position. If the new position is located before the first row or after the last row of data, false is returned;
otherwise, true is returned. In the ScrollableRSEx2, we use ResultSet.relative(-2), where the current
cursor position is at third row; therefore, the cursor has moved to the first row. We can use the
ResultSet.last() method to move the cursor to the last row. However, we used the
ResultSet.afterLast() method to move the cursor to a position after the last record and then move the
cursor one position backward, that is, to the last record using the ResultSet.previous() method.
So far we have discussed examples about how to work with different types of ResultSet created by using
different Statement objects and cursor movement methods. Lets now take an example that shows the
difference between using ResultSet types such as TYPE_SCROLL_SENSITIVE and
TYPE_SCROLL_INSENSITIVE. We have learned earlier that the TYPE_SCROLL_SENSITIVE type is scrollable
as well as sensitive to all the changes, whereas the TYPE_SCROLL_INSENSITIVE type is only scrollable. The
following code shows the difference in using both the scroll types:
import java.sql.*;
import java.util.*;
import java.io.*;
public class ScrollableRSEx3 {
public static void main(String s[]) throws Exception {
Driver d= (Driver) (
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
Connection con1=d.connect("jdbc:oracle:thin:@localhost:1521:XE",p);
Connection con2=d.connect("jdbc:oracle:thin:@localhost:1521:XE",p);
917
Chapter 24: Introducing JDBC
rs.beforeFirst();
while (rs.next()){
System.out.print(rs.getInt(1)+"\t");
System.out.println(rs.getString(2));
}//while
con1.close();
con2.close();
}//main
}//class
The preceding code uses the TYPE_SCROLL_INSENSITIVE type of ResultSet object, which indicates that the
changes made to the data in the database after obtaining ResultSet does not update the ResultSet object
(Figure 24.19). Figure 24.20 shows that modifying the name of the employee, having EmpNo 1020, from Nikhil to
kumar does not modify the records in ResultSet:
918
Immediate Solutions
You should remember that selecting an improper ResultSet type may result into performance issues and in
some cases, the data may get corrupted.
Till now we have learned about the types of ResultSets based on the cursor movement and concurrency. The
following section explains the ability of ResultSets to manipulate the results.
You must note the following points while updating the data by using the ResultSet object:
The changes are not updated in the underlying data source until the ResultSet.updateRow() method is invoked.
In order to roll back the changes done to the row, the ResultSet.cancelRowUpdate() method can be invoked. In case the
ResultSet.updateRow() method has been invoked already or no updates were made to this row, then this method will
have no effect on the data.
The ResultSet.updateRow() method must be invoked without moving the cursor position from the current row.
While accessing data from ResultSet or iterating through it for multiple times, we may want to identify whether
the current row was updated using the ResultSet object. An application can use the
ResultSet.rowUpdated() method to find whether the current data is updated or not.
As we have understood how to use the ResultSet object to update the database, lets create an example that
can put this discussion into action. Lets understand how to update the data using the ResultSet object. To
understand this, lets display all the employee details and increase the salary of the employeesing who draw
more than Rs 2000 by 10%:
import java.sql.*;
import java.util.*;
public class IncrementSalary {
919
Chapter 24: Introducing JDBC
Connection con=d.connect("jdbc:oracle:thin:@localhost:1521:XE",p);
Statement st=con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
System.out.println("Empno\tName\tSalary\tDeptno");
System.out.println("------------------------------");
while (rs.next()) {
System.out.print(rs.getInt(1)+"\t");
System.out.print(rs.getString(2)+"\t");
System.out.print(rs.getDouble(3)+"\t");
System.out.print(rs.getInt(4)+"\t");
if (rs.getDouble(3)>10000) {
double amt=rs.getDouble(3)*1.1;
rs.updateDouble(3,amt);
rs.updateRow();
System.out.print("Salary Incremented");
}//if
System.out.println ();
}//while
con.close();
}//main
}//class
The preceding code shows how to update the emp table in the database by using the ResultSet object. The listing
uses the ResultSet.CONCUR_UPDATABLE concurrency to create a Statement object so that the queried data can
be updated by using the ResultSet object produced by the Statement object. Here, we have selected all the rows
of the emp table while iterating through the ResultSet; the application identifies whether the salary of the
employee is greater than 10000, if so, it uses the updateDouble() method. The updateRow() method is used
to commit the changes made to the database by using the ResultSet object. The output of Listing 24.8 is shown in
Figure 24.22:
920
Immediate Solutions
After the row is deleted in the underlying data source, the deletion may or may not be visible in the open
ResultSet object, depending on the driver implementation. An application can use the
ownDeletesAreVisible(int type) method of DatabaseMetaData to find whether the deletion is visible as
a change or not. The ownDeletesAreVisible() method returns true if the deleted row is removed or
replaced with an empty row in the ResultSet object of the given type. The ResultSet object returns false if it still
has the deleted row. In other words, the deletion of a row is not reflected as a change to the ResultSet object. An
application can use the rs.deleteRow() method to find whether the current row has been deleted or not. Note
that the rs.deleteRow()method of the ResultSet object returns true only if the current row was deleted;
otherwise, the method returns false.
Lets understand the code to delete a row by using the deleteRow() method of the ResultSet object:
import java.sql.*;
import java.util.*;
public class RemoveEmployee {
Connection con=d.connect("jdbc:oracle:thin:@localhost:1521:XE",p);
Statement st=con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
if(dbmd.ownDeletesAreVisible (ResultSet.TYPE_SCROLL_SENSITIVE))
System.out.println(
"Deletions are visible as a change for this
ResultSet object");
else
System.out.println(
"Deletions are not visible as a change for this ResultSet object");
System.out.println();
System.out.println("RowNo\tEmpno\tName\tSalary\tDeptno");
System.out.println("------------------------------");
while (rs.next()) {
System.out.print(rs.getRow()+"\t");
System.out.print(rs.getInt(1)+"\t");
System.out.print(rs.getString(2)+"\t");
System.out.print(rs.getDouble(3)+"\t");
System.out.print(rs.getInt(4)+"\t");
if (rs.getInt(1)==Integer.parseInt(s[0])) {
rs.deleteRow();
System.out.print("Employee Removed");
}//if
System.out.println();
921
Chapter 24: Introducing JDBC
}//while
con.close();
}//main
}//class
The code given above removes a record from the database using the ResultSet object. It uses the
ResultSet.deleteRow() method to delete a specific row using the ResultSet object. Here, we have even used
the DatabaseMetaData object to find whether the deletions are visible to ResultSet or not. Figure 24.23 shows the
output of RemoveEmployee.java, which deletes a record from the database:
A record is not inserted into the underlying data source until the ResultSet.insertRow() method is invoked.
The ResultSet.insertRow() method must be invoked without moving the cursor position from the current row.
As we have learned how to insert a row using a ResultSet object, lets create an example that can demonstrate
this. The code given below shows how to insert a new row into a database by using the ResultSet object:
import java.sql.*;
import java.util.*;
Driver d= (Driver)(Class.forName(
"oracle.jdbc.driver.OracleDriver").newInstance());
922
Immediate Solutions
p.put("user","scott");
p.put("password","tiger");
Connection con=d.connect("jdbc:oracle:thin:@localhost:1521:XE",p);
Statement st=con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
rs.moveToInsertRow();
rs.updateInt(1,1002);
rs.updateString(2,"Hari");
rs.updateDouble(3,13000);
rs.updateInt(1,3);
rs.insertRow();
System.out.print("Employee Inserted");
con.close();
}//main
}//class
On execution of the preceding code, an employee record is inserted into the database by using the ResultSet
object. The moveToInsertRow() method is used to specify the cursor position to insert a new empty row. The
updateXXX() methods are used to insert the column values for the record to be inserted and then the
insertRow() method is called by using the ResultSet object to insert the row into the database. Figure 24.24
shows the output of AddEmployee.java:
923
Chapter 24: Introducing JDBC
The database automatically cleans unused sessions; however, it may take a long time to clear the session.
Therefore, using the Connection.close() method at proper location in our application is necessary to close
the unused session; otherwise, the session represented by the connection would be remained open (active) for a
long time without any use.
The database sessions that are identified as unused are automatically closed by the database. The database uses
the session timeout to identify the unused sessions. An unused session is the one which is not getting a request
for a long time (>session timeout period). Moreover, databases have their own strategies to decide when to find
for the unused sessions, such as at regular intervals, or when the numbers of active sessions limit reaches the
configured load factor. Therefore, it can be understood that leaving the responsibility of closing the database
session to DBMS would block the resources for a long time, which affects the availability of resources and
increases the cost of using the system.
Opening and closing the database session is a costlier job. Therefore, we need to look for a good design of our application that
can utilize the opened connection to the maximum.
The Connection.close() method closes the database session associated with a connection that even results
to close the Statement and ResultSet (CURSORs) built on this connection. However, with few drivers, the
Statement and ResultSet would remain open even after closing the connection. In such a situation, although
ResultSet would not be used to read the data, we need to explicitly close the statement and ResultSet. The
following section describes closing Statement and ResultSet.
924
Immediate Solutions
The table COFFEES gets updated by having the value 25 replaced by the value present in the column SALES in
the row for Espresso. This update will affect one row in the table; therefore, the value of n will be equal to 1.
Again, at the time the method executeUpdate()is used to execute a DDL statement, such as in creating a table,
it returns the int 0. Consider the following code fragment:
int n = executeUpdate(createTableCoffees); // n = 0
The preceding code fragment executes the DDL statement which is used for creating the COFFEES table and n is
assigned a value of 0.
When the executeUpdate()method returns the 0 value , it can mean one of the following:
An update statement that affected zero rows was executed or
A DDL statement was executed.
After going through the program in snippets form, the complete functional program for better understanding is
as follows:
import java.sql.*;
public class DemoJDBC {
public static void main (String [] args) throws Exception {
int count = 0;
double payroll = 0.0;
ResultSet rslset1=null;
String names;
double salaries;
Driver d= (Driver)(Class.forName(
"oracle.jdbc.driver.OracleDriver").newInstance());
Properties p=new Properties ();
p.put("user","scott");
p.put("password","tiger");
Connection con=d.connect(" jdbc:oracle:thin:@localhost:1521:XE",p);
System.out.println ("*** Connected to the database ***");
Statement smnt = conn.createStatement ();
rslset1 = smnt.executeQuery ("select e.Name, e.Salary" + " " +
"from Employee e" + " " +
"where e.Dept = 'Toys' ");
System.out.println ( );
System.out.println ("Name Salary");
System.out.println ("---- ------");
while(rslset1.next()) {
names = rslset1.getString (1);
salaries = rslset1.getInt (2);
System.out.println (names + " " + salaries);
count = count + 1;
payroll = payroll + salaries; }
System.out.println ( );
System.out.println ( );
System.out.println ("Number of employees in Toys
Department " + count);
System.out.println ("Total payroll for Toys
Department " + payroll);
smnt.close ();
PreparedStatement stmt2 = conn.prepareStatement
("update Employee" + " " + "set Dept=?, Salary=?" + " " +
"where Name = ? " );
stmt2.setString(1,"Debit");
stmt2.setDouble(2,65000.0);
stmt2.setString(3,"Hari");
stmt2.executeUpdate();
stmt2.setString(1,"Credit");
stmt2.setDouble(2,75000.0);
stmt2.setString(3,"Leu");
stmt2.executeUpdate();
925
Chapter 24: Introducing JDBC
stmt2.close ();
conn.commit();
conn.close ();
}
}
Summary
In this chapter, you have learned the basics of JDBC, its architecture, packages, and events. You have gained
knowledge on driver interface, the DriverManager class. You have also learned to create a basic JDBC
program. We have explained the use of PreparedStatement object, interactive SQL tool, and tables.
In the next chapter, you will learn about images and animation.
926
25
Images and Animation
If you need an immediate solution to: See page:
Using the Image Class 930
Using the MediaTracker Class 937
Using the ImageIcon Class in an Applet 938
Using ImageObserver Interface 942
Creating a Game Using the java.awt.geom Package 943
927
Chapter 25: Images and Animation
In Depth
In this chapter, we are going to cover some important topics related to images and animations in detail, along
with an understanding of the java.awt.geom package. It will also give you knowledge about using
ImageIcon in an Applet. Different stages of animations Will be an added attraction of this chapter.
Images
As its name suggests, the ImageIcon class helps to get as well as draw images in Java applets. There are
provisions in Java for handling images as Java provides extensive support for imaging. In Java, basic image
handling is easy because the Image class in the java.awt package provides abstract methods to represent
common image behavior. The special methods defined in Applet and Graphics classes give you everything
you need to load and display images in your applet as easily as drawing a rectangle.
An image can be referred to as a rectangular graphical object. Images play an important part in Web design. In
fact, the breakthrough is the inclusion of the <img> tag in the mosaic browser at the National Center for
Supercomputing Applications (NCSA). This is what caused to the Web explosive growth in the year 1993. This
tag was used to include an image inline with HTML. Java provides extensive support for imaging because it
expands upon this basic concept of allowing images to be managed under program control.
928
In Depth
The classes that implement the Shape interface are CubicCurve2D, Ellipse2D, Line2D, Rectangle2D, and
QuadCurve2D. The mechanisms for operations such as add (union), subtract, intersect, and exclusiveOR that
are performed on other Shape objects are carried out with the help of the Area class.
Thats it for the overview of this chapter. Theres a lot coming up. So its time to turn to the Immediate
Solutions section.
929
Chapter 25: Images and Animation
Immediate Solutions
Using the Image Class
The Novice Programmer appears and says, What about the different types of operations for images? What is the
source for loading images? You say, Image class provides all the answers.
While working with images, we come across three common operations, namely, creating an image, loading an
image, and displaying an image. The images are taken from the external sources according to the requirements.
Thus, Java provides not only ways for you to create a new object and load one but also a means by which an
image can be displayed. For example, with Java 1.4, you were able to load and draw image files encoded as
JPEG, GIF, and PNG. From Java 5.0 onward, you could also load bitmap formatsBMP and WBMP.
Creating an Image
There are two methods of creating an image. They are discussed as follows:
Image createImage (ImageProducer iePr)This method returns an image produced by iePr. An
ImageProducer object is present in each image. Its main function is to reconstruct the image whenever
needed. For example, reconstructing an image during the modification of its size.
Image createImage(int wid, int hgt)You can also create an image just to draw on it by using
the createImage() method from the Component class as in the following code:
Image image = createImage(width, height);
Graphics g = image.getGraphics();
paint(g);
Loading an Image
There are two methods to load an image, which are explained as follows:
Image getImage(URL url)Refers to the method used for returning an Image object that can then be
painted on the screen. When an applet draws the image, the data will be loaded on the screen. Then the
graphics primitives, which are used for drawing the image, will paint on the screen in an incremental order.
Image getImage(URL url, String imgNme)Refers to the version which returns an Image object
that encapsulates the image found at the Uniform Resource Locator (URL) and the name specified by
imgNme.
Image is an abstract class, so you are actually loading an instance of a concrete subclass of Image with the getImage()
methods above. However, you always treat the object as an instance of Image, i.e., you can only have access to its methods.
Displaying an Image
An image can be displayed using drawImage(). This can be done using two forms:
drawImage(Image img, int x, int y, ImageObserver observer)It returns Fill with a given
image at a given location (upper left corner specified by x and y). Here, observer refers to the class that
implements the ImageObserver interface, which in turn receives the image information notifications as
the image is constructed. In other words, it monitors the image while the image is being loaded.
drawImage(BufferedImage image, BufferedImageOp op, int x, int y)It filters an image. The
filter is implemented by the BufferedImageOp parameter. The fields and methods of the abstract Image
class are given in Table 25.1 and Table 25.2 respectively.
930
Immediate Solutions
931
Chapter 25: Images and Animation
configurable to cater the needs of image processing. The interface and classes included in java.awt.image
package are enlisted in Table 25.3 and Table 25.4.
Table 25.3: The Interfaces of the java.awt.image package
Interface Does this
BufferedImageOp This interface describes single-input/single-output operations
performed on BufferedImage objects
ImageConsumer The interface for objects expressing interest in image data through the
ImageProducer interfaces
ImageObserver An asynchronous update interface for receiving notifications about
Image information as the Image is constructed
ImageProducer The interface for objects, which can produce the image data for
Images
RasterOp This interface describes single-input/single-output operations
performed on Raster objects
RenderedImage RenderedImage is a common interface for objects, which contain or
can produce image data in the form of Raster
TileObserver An interface for objects that wish to be informed when tiles of a
WritableRenderedImage become modifiable by some writer via a
call to getWritableTile() method, and when they become
unmodifiable via the last call to releaseWritableTile() method
WritableRenderedImage WriteableRenderedImage is a common interface for objects
which contain or can produce image data in the form of Rasters
and can be modified and/or written over
932
Immediate Solutions
933
Chapter 25: Images and Animation
934
Immediate Solutions
You can draw on an image just as you would draw on a component by obtaining the graphics context object via
the Image class method:
Graphics getGraphics()
You then invoke the usual drawing methods in the Graphics object to draw on the image.
935
Chapter 25: Images and Animation
When info != ALLBITS, the method returns true. When info == ALLBITS, the flag doneloading is set to
true, which signifies that the loop in the run() method will terminate and the thread will die. The
imageUpdate() will then return false and will no longer be invoked. The code is as follows:
import javax.swing.*;
import java.awt.*;
/* <APPLET
CODE=ImageApp.class
WIDTH=500
HEIGHT=270 >
</APPLET> */
public class ImageApp extends JApplet implements Runnable {
DrawPanel drawPanel;
Image image;
int imagenum = 0;
String message ="Loading...";
boolean doneloading = false;
public void init () {
Container conpane = getContentPane ();
drawPanel = new DrawPanel (this);
conpane.add (drawPanel);
image = getImage (getCodeBase (), "logo.jpg" ); }
public void start () {
Thread thrd = new Thread (this);
thrd.start (); }
public void run () {
int width = image.getWidth (this);
if (width >= 0) {
doneloading = true;
repaint ();
return; }
while (!doneloading) {
try { Thread.sleep (500); }
catch (InterruptedException ie) { }
repaint (); }
}
public boolean imageUpdate (Image img, int info, int x,
int y, int w, int h) {
if (info != ALLBITS) { return true; }
else {
doneloading = true;
return false; }
}
}
class DrawPanel extends JPanel {
ImageApp imgparent = null;
DrawPanel (ImageApp parent) { imgparent = parent; }
public void paintComponent (Graphics g) {
super.paintComponent (g);
if (imgparent.doneloading) {
g.drawImage (imgparent.image,10,10,this);
}
else { g.drawString (imgparent.message, 10,10); }
}
}
936
Immediate Solutions
The result of having an ImageObserver interface for monitoring the image loading is shown in Figure 25.1:
937
Chapter 25: Images and Animation
938
Immediate Solutions
Basic image handling in Java is easy. The Image class in the java.awt package provides abstract methods to
indicate the common behavior among the images. Special methods defined in Applet and Graphics provide
us everything we need to load and display images in our applet as easily as drawing a triangle. In this section,
well understand how to get and draw images in our Java applets.
Getting Images
Firstly, we need to load an image in our Java program before it gets displayed. The images are stored as separate
files from our Java class files; therefore, we have to indicate Java where to find those files.
The getImage() method loads an image and automatically creates an instance of the Image class for us. To
use it, all we need to do is to import the java.awt.Image class into our Java program and then give URL of
the image to the getImage() method. This can be done in two ways:
The first one is the getImage() method with a single argument; getImage(an object of type URL)
retrieves the image at that URL.
The second one is the getImage() method with two arguments. The first argument is the base URL (also
a URL object), while the second is a String representing the path or the filename of the actual image
(relative to the base).
The first way may appear to be easier (just plug in the URL as a URL object), and the second way is more flexible.
However, as a matter of fact, if hard-coded URL of an image is included during the compilation of Java files and
then moved to a different location, then all the Java files must be recompiled. The latter form, therefore, is more
preferred to use.
The Applet class also provides two methods that will help with the base URL argument to getImage():
The first method is the getDocumentBase() method: Refers to the method that returns a URL object
representing the directory of the HTML file containing the applet. Therefore, if the address of the HTML file
is http://www.myserver.com/htmlfiles/javahtml/, then the getDocumentBase() method
returns a URL pointing to that path.
The second method is the getCodeBase() method: Refers to the method that returns a String
representing the directory containing the applet (regardless of the fact that it may or may not be the same
directory as the HTML file) and depending on whether the CODEBASE attribute in <APPLET> is set or not.
The use of either getDocumentBase() or getCodeBase() depends on whether your images are relative to
your HTML files or Java class files. You can use either of them depending upon the prevailing situation or one
that suits the situation better.
Either of these methods is more flexible to use than write a URL or pathname into the getImage() method.
The getDocumentBase() or getCodeBase() methods are used to move HTML files and applets while a
Java can still find your images. This assumes that you move the class files and images around together. If you
move the images and class files at different places, then youll have to edit and recompile your source.
The following form of the getImage() method shows that the image.gif file and the HTML files are in the
same directory that refers to this applet:
Image img = getImage(getDocumentBase(), "image.gif");
The following form shows that the file image.gif and the applet itself are in the same directory:
Image img = getImage(getCodeBase(), "image.gif");
If you have lots of image files, its common to put them into their own subdirectory. This type of getImage()
method resembles the file image.gif in the directory images which share the same directory as that of the
Java applet:
Image img = getImage(getCodeBase(), "images/image.gif");
When the getImage() method is unable to search the indicated file, it returns null. In case the drawImage()
is present on a null image, it will not draw anything. A probable error will be caused if a null image is used
in any other way.
939
Chapter 25: Images and Animation
Drawing Images
The getImage() method retrieves an image and stuffs it into an instance of the Image class. When we are
provided with the methods that can load images, we have to display them so as to give an eye-catching content
with images as we would do while drawing a rectangle or writing some text. In order to do this, the Graphics
class has two methods, both of which are known as drawImage().
The drawImage()method takes four argumentsthe image to be displayed, the x and y positions of the top
left corner, and this:
public void paint() { g.drawImage(img, 20, 20, this); }
This first form draws the image in its original dimensions with the top-left corner at the given x and y positions.
Lets take a look at this code for a very simple applet that loads an image, called lilies.jpg, and displays it:
import java.awt.Graphics;
import java.awt.Image;
/*<APPLET
CODE=BugApp.class
WIDTH=500
HEIGHT=270 >
</APPLET> */
public class BugApp extends java.applet.Applet {
Image image;
public void init() { image = getImage(getCodeBase(), "lilies.jpg"); }
public void paint(Graphics g) { g.drawImage(image, 10, 10,this); }
}
The result of the code appears in Figure 25.3. In this example, the instance variable image holds the lilies image,
which is loaded in the init() method. The paint() method then draws that image on the screen. This
example is BugApp.java, and you can see its output in Figure 25.3:
940
Immediate Solutions
The second form of drawImage() requires six numbers of arguments, namely, the image to be drawn, the x and
y coordinates of the top-left corner, the width and height of the image bounding box, and this. In case the
width and height arguments for the bounding box differ in the size from the actual image, then the image will be
automatically scaled to fit. Hence, by using those extra arguments, you can compress and expand images
according to the space provided for it.
Keep in mind, however, that there may be some image degradation or loss from scaling it smaller or larger than its original size.
One useful hint for scaling images is to find the actual size of the image loaded so that you can scale it to a
specific percentage and avoid distortion in either direction. The methods that are defined for the Image class are
getWidth() and getHeight(). Both these take a single argument, an instance of ImageObserver, which is
used to track the loading of the image. Youll read more about it later in the chapter. Most of the time, you can
use this as a parameter to either getWidth() or getHeight().
If you store the logo image in a variable called bugimg, for example, this line returns the width of that image, in
pixels:
theWidth = bugimg.getWidth(this);
If the image isn't loaded fully, you may get different results. Calling getWidth() or getHeight(), before the full loading of the
image, will result in the value of -1 for each one. Tracking image loading with ImageObserver can help you keep track when this
information appears.
Lets look at another program that uses the Image class to display an image in a panel:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
public class PictureFrame extends JFrame implements ActionListener {
Image img;
JButton getPictureButton;
public static void main(String [] args) { new PictureFrame(); }
public PictureFrame() {
this.setSize(300, 300);
this.setTitle("Image Frame");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel picPanel = new PicturePanel();
this.add(picPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
getPictureButton = new JButton("Open Image File");
getPictureButton.addActionListener(this);
buttonPanel.add(getPictureButton);
this.add(buttonPanel, BorderLayout.SOUTH);
this.setVisible(true); }
public void actionPerformed(ActionEvent e) {
String file = getImageFile();
if (file != null) {
Toolkit kit = Toolkit.getDefaultToolkit();
img = kit.getImage(file);
img = img.getScaledInstance(300, -1, Image.SCALE_SMOOTH);
this.repaint(); }
}
private String getImageFile() {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new ImageFilter());
int result = fc.showOpenDialog(null);
File file = null;
941
Chapter 25: Images and Animation
if (result == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
return file.getPath(); }
else { return null; }
}
private class PicturePanel extends JPanel {
public void paint(Graphics g) { g.drawImage(img, 0, 0, this); }
}
private class ImageFilter
extends javax.swing.filechooser.FileFilter {
public boolean accept(File f) {
if (f.isDirectory()) { return true; }
String name = f.getName();
if (name.matches(".*((.jpg)|(.gif)|(.png))"))
return true;
else { return false; }
}
public String getDescription() {
return "Image files (*.jpg, *.gif, *.png)"; }
}
}
This example uses JFileChooser dialog box that lets the user select an image and then display it, (Figure 25.4).
In addition to it, the file chooser includes a filter so that only .jpg, .gif and .png files are listed. This
example is PictureFrame.java and you can view its output in Figure 25.4:
942
Immediate Solutions
more control, say in cases where an image may only be partially loaded, or if a lot of image loading has to be
tracked asynchronously. Lets have a look at an example:
import javax.swing.*;
import java.awt.*;
/* <APPLET
CODE=App.class
WIDTH=500
HEIGHT=200 >
</APPLET> */
public class App extends JApplet {
public void init () {
Container conpane = getContentPane();
Image image = getImage (getCodeBase(), "lilies.jpg");
DrawPanel drawPanel = new DrawPanel (image);
conpane.add (drawPanel); }
}
class DrawPanel extends JPanel {
Image imag = null;
DrawPanel (Image image) { imag = image; }
public void paintComponent (Graphics g) {
super.paintComponent (g);
int imgX = getSize().width/2 - imag.getWidth(this);
int imgY = getSize().height/2 - imag.getHeight(this);
g.drawImage(imag, imgX, imgY, this); }
}
The result of the code can be seen in Figure 25.5. This example is App.java and you can see its output as
Figure 25.5:
943
Chapter 25: Images and Animation
The java.util package contains a class (Hashtable) that implements a hash table. For larger numbers of images, a hash table is
a faster way to find and retrieve images. Since there are a few images here and arrays are better for fixed-length and repeating
animation, we'll use an array here.
In the Aniapp applet, the kitten images are displayed in different positions on the screen, so you must keep
track of the current positions of the x and y coordinates. This will help the different methods in the applet to be
aware of the position from where to start drawing. In this applet, the position for the y coordinate always
remains constant as the kitten runs from the left side of the screen to the right side at the same y position.
However, the position for x coordinate may vary. The following code shows two instance variables to track x
and y positions on the screen:
int xposition;
int yposition = 50;
While initializing an applet, all the images will be first read and stored in an array. All this initialization process
takes place in a method called init().
You can use the getImage() method to make an individual call to the nine images having different file names.
If you create an array of strings, kittensrc, to store the file names and use the for loop to iterate the item one
by one and load them, it will help in saving time. The following code uses the init() method for the
kittensrc array that loads all the images into the kittensrc array:
public void init()
{
String kittensrc[] = { "rt1.gif", "rt2.gif",
"stp.gif", "yn.gif", "sc1.gif",
"sc2.gif","slp1.gif", "slp2.gif",
"awk.gif" };
for (int i=0; i < kittenpics.length; i++)
{
kittenpics[i] = getImage(getCodeBase(),
"images/" + kittensrc[i]);
}
}
944
Immediate Solutions
In the preceding code, a call to the getImage() method is made. All the images stored in the image directory
are added as a part of the path.
945
Chapter 25: Images and Animation
Lets now look at the paint() method, which is used to paint each frame. In this application, the paint()
method is quite simple. This method paints the current image at the current x and y coordinate positions. The
instance variables are used to store all such information.
However, before drawing the images, we must first ensure that they exist. To ensure that we are not trying to
draw an image that does not exist, it is advisable to first verify whether the currentimg variable exists or not
prior to calling the drawImage() method to paint the image. The code for the paint() method is as follows:
public void paint(Graphics g) {
if (currentimg != null) { g.drawImage(currentimg, xposition, yposition, this); }
}
Now, lets look at the run() method, where the animations main processing would take place. In the run()
method, the kittenrun() method is called using the appropriate values to make the kitten run from the left
side of the screen to the center, as shown in the given code:
kittenrun(0, size().width / 2);
Apart from running across the screen, the kitten also stops and yawns. A single frame is used for each of these
things (in positions 2 and 3 in the array); therefore, you do not really require a separate method to draw them.
Now, you must set the appropriate image by calling the repaint() method and pausing the animation for a
specific amount of time. In this case, the animation is paused for a second, every time, for stopping and
yawning-again by using the trial and error method. The following is the part of code for the same:
currentimg = kittenpics[2];
repaint();
pause(1000);
currentimg = kittenpics[3];
repaint();
pause(1000);
When the kitten scratches, that is, during the third part of the animation, there seems to be no horizontal
movement happening. To show the animation effect, you must alternate between the two scratching images
stored at positions 4 and 5 of the image array. As scratching is a separate action, lets create a different method
for it.
The kittenscratch() method takes a single argument as parameter, that is, the number of times the kitten is
made to scratch. This argument will help to iterate through the loop and then alternate between the two
scratching images and repaint each time. The following code defines the kittenscratch() method:
void kittenscratch(int numtimes) {
for (int i = numtimes; i > 0; i--) {
currentimg = kittenpics[4];
repaint(); pause(150);
currentimg = kittenpics[5];
repaint();
pause(150); }
}
Within the run() method, you can call the kittenscratch() method using an argument:
kittenscratch(4);
The kitten must sleep after scratching. To do so, you can find two images for sleeping in positions 6 and 7 of the
array. You can alter these images for a specific number of times. In this case, the kittensleep() method takes
a single number argument and animates for that many turns. The following code defines the kittensleep()
method:
void kittensleep(int numtimes) {
for (int i = numtimes; i > 0; i--) {
currentimg = kittenpics[6];
repaint();
pause(250);
currentimg = kittenpics[7];
946
Immediate Solutions
repaint();
pause(250); }
}
The kittensleep() method is called in the run() method as follows:
kittensleep(5);
Finishing Up
Finally, to complete the applet, the kitten wakes up from sleep and then runs off to the right side of the screen.
To wake up the kitten, reuse the kittenrun() method and use the waking up image, which is the last image in
the array at position 8:
currentimg = kittenpics[8];
repaint();
pause(500);
kittenrun(xposition, getSize().width + 10);
All the images for this application have white backgrounds, and when you draw these images on an applet, a
white box with a medium gray background appears around each image as an applet by default. To solve this
issue, simply set the background of the applet, as shown here to white, at the beginning of the run() method:
setBackground(Color.white);
A lot of code is used in this applet to show the animation effects. The main aim is to set up the frame and then
call the repaint()method to enable the screen to be redrawn.
One thing to be noted here is that there is nothing done to minimize the amount of flicker in this applet. It
appears that the images used in this applet are small and the drawing area is also very small. So, the flicker does
not look that bad for this applet.
It's always a good practice to develop code for your animation to perform the simplest thing first and then add behavior to make
it run smoothly.
947
Chapter 25: Images and Animation
runner.start(); }
}
public void stop() {
if (runner != null) { runner = null; }
}
public void run() {
setBackground(Color.white);
kittenrun(0, getSize().width / 2);
currentimg = kittenpics[2];
repaint();
pause(1000);
currentimg = kittenpics[3];
repaint();
pause(1000);
kittenscratch(4);
kittensleep(5);
currentimg = kittenpics[8];
repaint();
pause(500);
kittenrun(xposition, getSize().width + 10); }
void kittenrun(int startposition, int endposition) {
for (int i = startposition; i < endposition; i += 10) {
xposition = i;
if (currentimg == kittenpics[0])
currentimg = kittenpics[1];
else currentimg = kittenpics[0];
repaint();
pause(150); }
}
void kittenscratch(int numtimes) {
for (int i = numtimes; i > 0; i--) {
currentimg = kittenpics[4];
repaint();
pause(150);
currentimg = kittenpics[5];
repaint();
pause(150); }
}
void kittensleep(int numtimes) {
for (int i = numtimes; i > 0; i--) {
currentimg = kittenpics[6];
repaint();
pause(250);
currentimg = kittenpics[7];
repaint();
pause(250); }
}
void pause(int time) {
try { Thread.sleep(time); }
catch (InterruptedException e) { }
}
public void paint(Graphics g) {
if (currentimg != null) {
g.drawImage(currentimg, xposition, yposition, this); }
}
}
948
Immediate Solutions
The result of the code appears in Figure 25.7(a), 25.7(b), 25.7(c), 25.7(d), 25.7(e), and 25.7(f), where the kitten runs,
stops, scratches, sleeps, yawns, and again runs, respectively. This example is Kitten.java and you can see its
output in Figure 25.7:
949
Chapter 25: Images and Animation
Summary
In this chapter, you have learned the ways to implement images and animations in your Java-based application.
You have come across different classes used for implementing the same.
In the next chapter, youll learn about Java DB.
950
26
Java DB
If you need an immediate solution to: See page:
Configure Environment Variables 958
Java DB Directory Structure 959
Creating Database in Java DB Using ij-Tool 959
Connecting with a Database 963
Disconnecting from a Database 964
Adding Tables in an Existing Database 964
Deleting Tables from an Existing Database 964
Adding Data into a Table 965
Displaying Content of a Table 965
Java DB Database Encryption 966
Using Java DB with Java Application 966
Chapter 26: Java DB
In Depth
Java DB is the brand name of a database product of Sun Microsystem, which was released with Java 6. Java DB is
a lightweight relational database engine based on Java and Structured Query Language (SQL). This is an open-
source database technology having Java's write once and run anywhere property. It is a robust, but a cost-
effective technology that provides a small footprint. Java DB is easy to deploy and we can migrate an application
to other open-source databases using it. You can create applications using Java DB with NetBeans, Eclipse, and
Java Studio Creator. Moreover, Java DB has some tools like ij, which can be used with the command line
interface.
The standards followed by Java DB are similar to that of the American National Standards Institute (ANSI) SQL
or Java Database Connectivity (JDBC). Thus, it has the same Relational Database Management System (RDBMS)
functionalities, such as transaction management, concurrency control, and triggers, as the other databases. The
syntax of the SQL Query of Java DB is based on SQL92, SQL99, and SQL2003. Java DB provides two
environments, namely, multiple databases per system and multiple systems per read-only databases, which
make database development simple for developers. Moreover, it provides security using various security
mechanisms like database encryption, authentication, and authorization.
Java DB provides the following features:
Open sourceJava DB is an open-source technology.
Implemented by JavaJava DB is purely implemented through Java. Thus, it has all the advantages of Java
like write once run anywhere and Java Virtual Machine (JVM).
Easy to useJava DB is an easy to use technology that does not require maintenance. It is a Compact,
robust, and mature database technology.
Small footprintThe size of the base package of Java DB is just 2 MB.
Standards basedJava DB follows same standard as JDBC and SQL92, 99, and 2003.
SecureJava DB provides security against threats through on-disk database encryption, built-in,
Lightweight Directory Access Protocol (LDAP), Network Information Service (NIS)+, and pluggable
authentication, network client authentication, Derby network client driver, Java Security Manager, and
Secure Sockets Layer/ Transport Layer Security (SSL/TLS).
Java DB has a long list of features along with some limitations. Some limitations of the Java DB are as follows:
Java DB does not support updatable queries with subqueries
Java DB does have the LIMIT clause
It has not any built-in clustering solution
Evolution of Java DB
In 1996, Cloudscape Inc., California, founded and started developing a database technology based on Java. Then,
in 1997, it released a Java-based RDBMS known as JBMS. The company renamed JBMS as Cloudscape in 1998
and released its new versions in every six months. Informix Software Inc. acquired Cloudscape Inc. in 1999.
Now, Cloudscape became the product of Informix Software Inc. In 2001, IBM acquired all databases assets of
Informix, including Cloudscape. Cloudscape database engine is now re-branded as IBM Cloudscape. In August
2004, IBM decided to give Cloudscape to the Apache Software Foundation. Apache renamed the Cloudscape
project as Apache Derby. Sun joined the Derby project so that it could use Derby as a component of its own
products Java. In December 2006, Sun Microsystem released Java 6, which packages Derby with its new name
Java DB.
Java DB is not a new database engine; it is exactly the same product as Derby. Eventually, this embedded
database engine has three names, that is, Cloudscape, Derby, or Java DB. In this chapter, we proclaim this
database software as Java DB.
952
In Depth
Now that you have learned about the evolution of Java DB, you can differentiate between Java DB and Apache Derby easily;
however, still there is a need of separate discussion related to the differences between Derby and Java DB. It is important to
note that there is hardly any difference between Java DB and Apache Derby. Derby is a product of Apache, while Java DB is a
product of Sun Microsystem. Java DB is exactly the same as Derby. Also, there is no difference between Java DB
documentation and Derby documentation. The Java DB 10.6 documentation is similar to Derby 10.6 documentation. Finally,
Java DB can be understood as the synonym for Derby and vice versa.
953
Chapter 26: Java DB
Architecture of Java DB
The architecture of Java DB is a simple and solid state-of-the art technology and based on the modular
architecture Aries.
Aries stands for Algorithms for Recovery and Isolation Exploiting Semantics. This is actually based on the
following three principles:
1. Write ahead logWhen any change is made on any object, it is first recorded into a log file and then stored
in the log file within the stable storage. After saving the log, actual update can be applied on the object.
2. Log changes during UndoOn undoing transaction, the log must be updated to prevent the repetition of
action with the database.
3. Repeating history during RedoWhen any crash occurs and the database restarts, Aries checks the history
of the database to retrace the actions done before the crash. This activity helps in restoring the system back
to its exact state as it was before the crash.
Java DB operates on the following two types of architectures:
1. Embedded architecture
2. Client/server architecture
Embedded Architecture
Java DB documentation refers embedded architecture as embedded mode and it can be used with the embedded
Java applications. With this option, Java DB runs in the same JVM as the application.
Figure 26.1 shows the embedded architecture of Java DB:
Client/Server Architecture
In the client/server architecture (also known as network-server configuration or client/server mode), several
applications can use single database simultaneously. This architecture requires some drivers to use Java DB
database. These drivers provide scripts to start and stop the network server. Therefore, client/server architecture
requires a little administration.
954
In Depth
Drivers of Java DB
A Java DB driver is a program that defines an interface to interact with the Java DB database in a particular
mode. Drivers for the Java DB come within the package of Java 6 or the latest version.
It is known that Java DB supports two types of architectures and thus provides the following two types of
drivers:
1. The org.apache.derby.jdbc.EmbeddedDriver driverThis driver is used in embedded application
when Java DB is running in the same JVM where application is running.
2. The org.apache.derby.jdbc.ClientDriver driverThis driver is used for the network server
environment.
955
Chapter 26: Java DB
Java DB URLs
You need to have Derby JDBC driver to connect with Java DB. Derby JDBC driver is produced by Apache and
included in the Java DB distribution package.
Some important features of Derby JDBC driver are as follows:
It is a Type 4 JDBC driver. Type 4 drivers can use Java networking libraries for communicating with the
database server.
It supports JDBC 4.0 specifications.
The org.apache.derby.jdbc.EmbeddedDriver class of Derby JDBC driver can be loaded automatically to
DriverManager.
It is available free of cost.
Some commercial JDBC-ODBC drivers are also available. For example, Easysoft JDBC-ODBC Bridge.
To connect with an existing Java DB database using the embedded driver, the following syntax is used:
jdbc:derby:<Database_Name>;<URLAttrib>
where Database_Name is an identifier that shows the name of your database to which the embedded driver
will connect and URLAttrib specifies some attributes of Uniform Resource Locator (URL), such as create and
upgrade, to be used during connection.
To connect to an existing Java DB database using the network client driver, the following syntax is used:
jdbc:derby://<Host>:<Port>/<Database_Name>;
where Host is an identifier that shows the name computer in which Java DB is running. If Java DB is running on
your local system, then use localhost or 127.0.0.1 as a Host. Port refers to a port number that can accept
incoming requests. Database_Name is an identifier that shows the name of the database to which the client
wants to connect.
956
In Depth
957
Chapter 26: Java DB
Immediate Solutions
Configure Environment Variables
Before the implementation of any Java DB database, you need to configure some environment variables
depending on the methods used for running the Java DB tools and startup utilities. The environment variables
that you need to set before starting the Java DB server are discussed in the following subsections.
DERBY_HOME
You need to set the DERBY_HOME environment variable to the location of Java DB bin directory. For example,
after the installation of Java DB with the JDK 1.8 (Java 8) in Windows, the bin directory of Java DB is created at
the location C:\Program Files\Java\jdk1.8.0_31\db. Thus, the DERBY_HOME environment variable is set
through the following command:
set DERBY_HOME=C:\Program Files\Java\jdk1.8.0_31\db
PATH
The DERBY_HOME\bin directory is added to the PATH environment variable; the Java DB/Derby scripts can be
run from any directory through this setting. The PATH environment variable should be set with the help of the
following command:
set PATH=C:\Program Files\Java\jdk1.8.0_31\db\bin;%PATH%
Once you are through with the setting of the DERBY_HOME environment variable, you can use the following shortened
commands:
set PATH=%DERBY_HOME%\bin;%PATH%
to add the underlying /bin directory in the PATH environment variable.
It is important to note that the setting of DERBY_HOME and PATH environment variables is valid only on the
current command window; whenever you open a new command window, you must set the DERBY_HOME and
PATH environment variables.
JAVA_HOME
For locating the JVM and Java applications, the scripts used the JAVA_HOME environment variable, as shown
in the following command
set JAVA_HOME= C:\Program Files\Java\jdk1.8.0_31
To verify that the environment variables are set correctly, the sysinfo command is used. The information
concerning the JVM and the version of Java DB/Derby that you have installed is shown through the sysinfo
command if there is correct configuration of the environment variables, as shown in Figure 26.4:
958
Immediate Solutions
959
Chapter 26: Java DB
960
Immediate Solutions
In Figure 26.10, the current directory is D:\MyJavaDB and the Java DB is started from this directory. So, whenever any
database is created on the Java DB server, it will be located in the MyJavaDB directory.
Creating Database
To create a new database in network mode with the ij-tool, use the connect command.
The syntax of the connect command for the network mode is as follows:
connect jdbc:derby://<Host>:<Port>/<Database_Name>;create=true;';
For example, if you are creating a new database Network_EmpDB (for Employee Database) on your local
system, then use localhost or 127.0.0.0 as a host and 1527 (default) as the port number. Thus, the
connection statement can be written as:
connect 'jdbc:derby://localhost:1527/Network_EmpDB;create=true;';
or
connect 'jdbc:derby://127.0.0.0:1527/Network_EmpDB;create=true;';
Java DB connection URL for Network Server mode is very simple and looks like the embedded mode, that is, just
add //localhost:1527/ before the database name.
Do you know about the physical location of newly created database? You have studied that there are two types of Java DB
drivers, namely, embedded driver (i.e., jdbc:derby:<Database_Name>;<URLAttrib>;) and network client driver
(i.e., jdbc:derby://<Host>:<Port>/<Database_Name>;<URLAttrib;).
If you are using the embedded driver during the creation of the database, then the new database will be stored in the same
directory in which ij was started up. On the other hand, when you are using the network client driver, then the new database will
be stored in the directory where the network server was started up (i.e., DERBY_INSTALL/bin).
961
Chapter 26: Java DB
Figure 26.12: Creation of a New Database Network_EmpDB in Network Mode Using ij-Tool
Now, a database Network_EmpDB is created into the directory D:\MyJavaDB, as shown in Figure 26.13:
Figure 26.14: Shutdown the Network Server using the stopNetworkServer.bat Command
962
Immediate Solutions
Maximize the window where you have started the network server. In this window, you will also see an
echo message about the shutting down process, as shown in Figure 26.15:
Figure 26.15: Echo Massage after Shutting Down the Network Server
Figure 26.16: Making Connection in Embedded Mode and Displaying the Name of Current Connection
Figure 26.17: Making Connection in Network Mode and Displaying the Name of Current Connection
Note that during creation as well as connection, you need to run the connect command; the difference is that
the create=true; property is used during the creation of a new database, while the create=true;
property is not used during connection. When you want to create a new database, you have to add the
create=true; property into the connect statement, which shows that you are giving permission to create a
new database. The absence of the create=true; property in the connect statement denotes the connection
with the existing database.
963
Chapter 26: Java DB
If you had applied user name and password during the creation of database, then you must pass user name and password in
the connect command as:
connect 'jdbc:derby:EmpDB;user=scott;password=tiger';
964
Immediate Solutions
965
Chapter 26: Java DB
966
Immediate Solutions
try {
//String driver = "org.apache.derby.jdbc.EmbeddedDriver";
Connection con = DriverManager.getConnection("jdbc:derby:Emp_DB;create=true;");
System.out.println("Emp_DB created!");
}
catch (Exception err) {
System.out.println(err.getMessage());
}
}
}
You need to close the connection of database explicitly. To shutdown Java DB, you must use the connection
object to initiate the shutdown sequence:
DriverManager.getConnection("jdbc:derby:<database_name>;shutdown=true");
Once the db is running, don't stop it until the application is shut down.
967
Chapter 26: Java DB
Summary
In this chapter, you have learned about the Java DB, including features, history, architecture, and drivers of Java
DB. Then the chapter has provided a comparison between Java DB and MySQL. It has also provided various
Java DB product documentation, Derby tools, and utilities. You have learned the installation and configuration
of Java DB on Windows operating system. Further, you have learned about the creation, deletion, and
connection of Java DB database in embedded mode as well as network mode. In the section Java DB database
encryption, you have learned how to encrypt/decrypt your database using a password. Finally, you have
learned about using Java DB with Java application.
In the next chapter, you will learn about Java FX.
968
27
Java FX
If you need an immediate solution to: See page:
Creating Simple JavaFX Application 981
Creating JavaFX Application on NetBeans IDE 981
Using the UI Controls 989
Using Visual Effects 989
Using Canvas API 990
Chapter 27: Java FX
In Depth
JavaFX is a collection of various advance features to strengthen the Java programming language. The inclusion
of Scene Builder, Modena themes, FXML, 3DViewer graphics, etc., in JavaFX facilitates Java language in
designing and developing rich interfaces with high-performance experiences for users. Generally, JavaFX is used
in the form of an Application Programming Interface (API) that can directly be imported into an application. In
todays age of the Internet, we find that the role of attractive user interfaces has increased. Any purchase, sale, or
demonstration depends on how creative and well-designed interface has been provided to it. JavaFX can be used
extensively to add to the attractiveness quotient of user interfaces. You can use the Scene Builder software
package of JavaFX to create powerful designs without any requirements to write the code and script for it.
Moreover, JavaFX applications are created using the standard Java language; hence, you need not worry about
the consistency and availability. The most important part of developing JavaFX applications is the use of themes,
Three-Dimensional (3D) viewers, Scene Graph APIs, graphics software and hardware, thread, pulse, media and
images, etc. JavaFX provides Web component and User Interface (UI) controls in the layout to include some
visual effects that are responsible for attracting the eyes of users.
In this chapter, you will learn about the general concept of JavaFX. Further, you will come to know about JavaFX
features. You will learn about the availability of JavaFX for various platforms. In addition, you will get to know
the scope of developing different kinds of applications using JavaFX APIs. Also, you will learn about JavaFX
architecture and various components of it. Toward the end, you will come to know about the downloading and
running of sample JavaFX applications and the use of Scene Builder in JavaFX.
JavaFX Applications
The JavaFX library is included in the Java language in the form of an API. Therefore, application code for JavaFX
has the capability of accessing any Java library API. As an instance, you can use Java libraries to access Java
language APIs that support native system capabilities. Also, Java APIs can be used to connect to middleware
applications that are based on the server.
With the help of Cascading Style Sheets (CSS), the look and feel of JavaFX can be customized so that you can
differentiate style and appearance from your implementation. The designers can take care of all the required
customizations in the appearance and style of JavaFX applications, and the developers are allowed to focus on
the coding section only. People who are aware of the Web design practices or those who want the back-end logic
and UI to be separated can use FXML scripting language for developing the UI presentation aspects and Java
code for developing the application logic. Moreover, with the help of JavaFX Scene Builder, UIs can be
developed without the need of writing the code. You can directly create the markup for your UI design by using
Scene Builder. You can import the FXML markup into an Integrated Development Environment (IDE) in order to
make it easy for the developer to add the business logic.
JavaFX Availability
JavaFX APIs are an integral feature of the Java Runtime Environment (JRE) and the Java Development Kit (JDK).
These APIs are supported by applications that are compiled to JDK 7 or later on any of the leading Operating
Systems (OSs), including Windows, Mac OS X, Linux, etc., because JDK is supported on all of these OSs. These
APIs started supporting the Advanced RISC Machine (ARM) platform also with JavaFX 8. JDK for ARM
platform involves a number of components, which include JavaFX base, graphics, and control components.
970
In Depth
JavaFX applications are compatible across various OSs. Therefore, developers and users find a consistent
runtime experience from these applications. Additionally, Oracle brings all its updates and new releases
synchronously for all platforms. Also, companies in which mission-critical applications are being implemented
to get the benefit of Oracles support offered in the form of extensive support program. Therefore, you would
never face compatibility or availability-related issues in creating JavaFX applications.
You can check the JDK download page to download sample applications of JavaFX in the form of a zip file that
contains code and snippets for several JavaFX programs demonstrating the use of JavaFX to develop
applications.
971
Chapter 27: Java FX
Multitouch supportJavaFX can be used to design applications in which multitouch operations are
performed. The multitouch support in JavaFX is based on the capabilities of the platform on which the
application is developed.
Hi-DPI supportThe eighth release of JavaFX incorporates Hi-DPI display support in applications.
Hardware-accelerated graphics pipelineJavaFX package involves a pipeline (Prism) to render graphics-
based application interfaces. Prism quickly provides smooth JavaFX graphics with the help of a supported
graphics card or Graphics Processing Unit (GPU). Prism can also use software-rendering stack to provide
smooth graphical experiences on encountering a GPU that is not supported by JavaFX.
High-performance media engineYou can run multimedia content on the Web in the playback through
JavaFX media pipeline support. The GStreamer multimedia framework offers a stable environment to
JavaFX 8 with low latency.
Self-contained application deployment modelJavaFX 8 includes self-contained application packages with
which all of the application resources are provided. Additionally, a private copy of the Java and JavaFX
runtimes are also available with these packages. The distribution of these packages can be installed as
native applications, offering the same experience of installation and launching as native applications on that
platform.
JavaFX Ensemble8
JavaFX provides a gallery of sample applications in the form of Ensemble8 to illustrate a large set of JavaFX
features, such as animation, charts, and controls. These samples, which also involve their descriptions, can be
run on all operating systems. We can view and interact with these samples, and also copy their source code on
our desktop platform where the properties of various samples can be altered and adjusted as per the users
requirements and vision. Moreover, if the Internet facility is available, we can access API documentation, as
relevant for us, through Ensemble8, which is designed to run on the ARM processor using JavaFX.
972
In Depth
Modena
The look and feel of the UI components of JavaFX applications is demonstrated through Modena, which is a
sample application that contains attractive themes. Moreover, you can compare the Modena theme with the
traditional Caspian themes to explore and utilize various facets of both the themes.
Figure 27.1 shows an application screenshot developed in Modena theme:
3DViewer
You can use the 3DViewer sample application for navigation and examination of three-dimensional scenes by
using a computer mouse or trackpad. Also, you can import a subset of Maya and Object (OBJ) files in JavaFX
applications by using the 3DViewer importers. Moreover, animation files created in Maya can be imported
through 3DViewer.
While saving Maya files, you need to delete the construction history on all the objects to enable importing of the files.
Additionally, you can export your contents, too, in the form of Java files or FXML files by using 3DViewer.
Figure 27.2 shows a screenshot of 3DViewer:
973
Chapter 27: Java FX
JavaFX Architecture
JavaFX applications follow a specific architecture pattern in which various parts are interconnected. Figure 27.3
shows the different components of JavaFX Architecture:
974
In Depth
Graphics System
Below the top layer in the architecture (Figure 27.3) is the JavaFX graphics system, which is a detail of the
implementation below the JavaFX scene graph layer. Graphics system provides support for both 2D and 3D
scene graphs. Moreover, you can render graphics through the graphics software system if in case hardware-
accelerated rendering is inadequate for supporting by the graphics hardware on your system.
JavaFX platform uses the following two graphics-accelerated pipelines:
PrismThese processes are used for rendering jobs. You can use them on both hardware and software
renderers, which also include 3D graphics. Moreover, prism processes are responsible for rasterizing and
rendering JavaFX scenes. The device being used by you determines the following multiple render paths:
DirectX 9 on Windows XP and Windows Vista
DirectX 11 on Windows 7
OpenGL on Mac, Linux, Embedded
Software rendering when hardware acceleration is not possible
Moreover, whenever possible, you can use paths that are fully accelerated by hardware. However, in case
this possibility does not exist, we use the software render path to exploit the already distributed software
render path in the Java Runtime Environments (JREs). This is especially significant in handling 3D scenes,
but the performance of hardware rendering paths is better in comparison with that of the software
rendering paths.
975
Chapter 27: Java FX
Quantum ToolkitQuantum Toolkit is the other pipeline used in JavaFX platform through which Prism
and Glass Windowing Toolkit associate together to make them selver available to the JavaFX layer. In
addition, the management of threading rules associated with rendering versus events handling is done by
the threading rules and the Quantum Toolkit.
Threads
JavaFX involves different kinds of threads to support proper running of applications. A system can run two or
more of the following threads at any instant:
JavaFX application threadRefers to the primary thread used by the developers of JavaFX application. A
live scene, which is a scene that is part of a window, can be accessed through this thread. In a background
thread, manipulation and construction of a scene graph can be done. However, accessing of a scene graph
from the JavaFX application thread must be permitted if the scene graphs root node is bound to the live
object of any scene. Therefore, developers can build complex scene graphs on a background thread by
keeping smooth and fast animations on 'live' scenes. You must be careful while embedding JavaFX code
into Swing applications because the JavaFX application thread is not similar to thread from the Swing and
AWT Event Dispatch Thread (EDT).
Prism render threadRefers to the thread that can handle rendering independently from the event
dispatcher. It enables rendering of frame N while frame N+1 is in processing. Therefore, the concurrent
processing ability provided by this thread is a big advantage for modern systems having multiple
processors. The Prism render thread handles off-load work in rendering with the help of multiple
rasterization threads.
Media threadThis thread can execute in the background for synchronizing the latest frames through the
scene graph with the help of JavaFX application thread.
Pulse
A pulse can be referred to as an event that directs the JavaFX scene graph about the time of synchronizing the
state of the elements on the scene graph with Prism. A pulse can be regulated at maximum of 60 frames per
second (fps) and is fired whenever animations are being executed on the scene graph. A pulse can be scheduled
even when an animation is not running and something is modified in the scene graph. For instance, a pulse can
be scheduled when the position of a label control is changed.
Application developers can use a pulse for handling events asynchronously, enabling the system for batch
execution of events on the pulse.
Layout and CSS are also attached to pulse events. When numerous changes are done in the scene graph, it might
lead to multiple updates to layout or CSS, which might degrade the pulse performance to a great extent. The
degradation in performance of the system is managed automatically by it. The system performs a CSS and layout
pass once per pulse for avoiding performance degradation. The passes can be triggered manually by application
developers as required for taking measurements prior to a pulse.
The pulse events are executed by the Glass Windowing Toolkit, which utilizes the high-resolution native timers
for the execution.
976
In Depth
Web Component
The Web component is a JavaFX UI control based on Webkit, which is an open-source Web browser engine in
which HTML5, CSS, JavaScript, Document Object Model (DOM), and Scalable Vector Graphics (SVG) are
supported. This component uses its API for providing a Web viewer and full browsing functionality. The Web
component allows developers for implementing the following features in their Java applications:
Rendering to HTML content from local or remote URL
Support to history, and Back and Forward navigation
Reloading the content
Applying effects to the Web component
Editing of the HTML content
Execution of the JavaScript commands
Handling of events
This embedded browser component comprises the following classes:
WebEngineIt provides the capability of browsing the Web page.
WebViewIt encapsulates a WebEngine object that embeds HTML content into an application's scene.
It provides fields and methods for applying effects and transformations. This class is an extension of the
Node class.
CSS
JavaFX CSS allows customized styling to the JavaFX applications UI without modifying the source code of
application. You can apply CSS to any JavaFX scene graphs nodes asynchronously. JavaFX CSS styles can be
applied to the scene at runtime, thus allowing dynamic change to the appearance of an application.
Figure 27.4 displays the implementation of two different CSS styles to the same set of UI controls:
977
Chapter 27: Java FX
UI Controls
JavaFX API provides the JavaFX UI controls that are created by using nodes in the scene graph. These controls
utilize full benefit of the visually rich features of the JavaFX platform and provide portability across various
platforms. The theme and skins of the UI controls can be set using the JavaFX CSS. JavaFX UI control
components involve the following elements:
Label
Button
Radio Button
Toggle Button
Checkbox
Choice Box
Text Field
Password Field
Scroll Bar
Scroll Pane
List View
Table View
Tree View
Tree Table View
Combo Box
Separator
Slider
Progress Bar and Progress Indicator
Hyperlink
Tooltip
HTML Editor
Titled Pane and Accordion
Menu
Color Picker
Date Picker
Pagination Control
File Chooser
Customization of UI Controls
UI Controls on Embedded Platforms
Layout
Within a scene graph of a JavaFX application, the arrangements of the UI controls can be made flexible and
dynamic with the help of layout containers or panes. The JavaFX Layout API provides the following container
classes that allow automation of common layout models:
The BorderPane class structures its content nodes in the top, bottom, right, left, or center region
The HBox class structures its content nodes horizontally in a single row.
The VBox class structures its content nodes vertically in a single column.
The StackPane class keeps its content nodes in a back-to-front single stack.
The GridPane class allows the creation of a flexible grid of rows and columns.
978
In Depth
The FlowPane class structures its content nodes in either a horizontal or vertical flow.
The TilePane class structures its content nodes in evenly sized layout cells or tiles.
The AnchorPane class allows developers to build anchor nodes to the top, bottom, left side, or center of the
layout
Different containers can be nested within a JavaFX application in order to attain a desired layout structure.
Visual Effects
Visual Effects are used for the creation of rich client interfaces in the JavaFX scene graph for enhancing the
appearance of JavaFX applications in real time. These JavaFX Effects are primarily image-pixel-based; and,
therefore, they use the group of nodes present in the scene graph, render it as an image, and then apply the
specific effects to it. The following effects are available in Visual Effects in JavaFX:
Blend Effect
Bloom Effect
Blur Effects
Drop Shadow Effect
Inner Shadow Effect
Reflection
Lighting Effect
Perspective Effect
Visual Effects in JavaFX use the following classes:
Drop ShadowRenders a shadow of a provided content behind the content
ReflectionRenders a reflected version of the content below the actual content
LightingSimulates a light source shining on a given content and provides a realistic three-dimensional
appearance to a flat object
979
Chapter 27: Java FX
Intended Audience
JavaFX applications are of interest for Web designers and developers who can apply their creativity and learning
toward improving the experience of end users. Hence, the target audience for JavaFX Scene Builder is as follows:
Java developersRefer to persons who can rapidly prototype the client application's GUI layout and create
the application logic independently.
DesignersRefer to persons who can rapidly prototype the client application's GUI layout without the need
of any application code to be written first. Moreover, they can design and preview the GUI layout and
define its appearance using style sheets.
980
Immediate Solutions
Immediate Solutions
Creating Simple JavaFX Application
Notepad or any Integrated Development Environment (IDE) supporting the Java language (such as NetBeans,
Eclipse, or IntelliJ IDEA) can be used for generating JavaFX applications, which are developed using the Java
language.
Here, we are creating a simple JavaFX application using the Notepad editor:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
981
Chapter 27: Java FX
After the successful installation of JDK 1.8 and NetBeans IDE, you need to install the JavaFX Scene Builder 2.0 by
performing the following steps:
1. Download the JavaFX Scene Builder 2.0 setup from the http://www.oracle.com/technetwork/
java/javafxscenebuilder-1x-archive-2199384.html link. Save the downloaded setup at an appropriate
location in your computer.
2. After downloading, double-click the setup file to start the installation. The JavaFX Scene Builder
- 2.0 Setup dialog box appears (Figure 27.6).
3. Click the Next button, as shown in Figure 27.6:
Figure 27.6: The JavaFX Scene Builder 2.0 - Setup Dialog Box
The JavaFX Scene Builder 2.0 Destination Folder dialog box appears (Figure 27.7).
4. Click the Install button, as shown in Figure 27.7:
Figure 27.7: The JavaFX Scene Builder 2.0 Destination Folder Dialog Box
982
Immediate Solutions
The JavaFX Scene Builder 2.0 Progress dialog box appears, as shown in Figure 27.8:
Figure 27.8: The JavaFX Scene Builder 2.0 Progress Dialog Box
After completing the installation of JavaFX Scene Builder 2.0, the JavaFX Scene Builder 2.0
Progress dialog box disappears. Now, the JavaFX Scene Builder 2.0 Complete dialog box
appears, as shown in Figure 27.9:
Figure 27.9: The JavaFX Scene Builder 2.0 Complete Dialog Box
After successful installation of JavaFX Scene Builder 2.0, now perform the following steps to create a simple
application in NetBeans 8 IDE:
1. Open the NetBeans IDE.
983
Chapter 27: Java FX
2. Click the FileNew Project option in the File menu. The New Project dialog box appears
(Figure 27.10).
3. Select the JavaFX folder in the Categories pane and then select the JavaFX FXML Application
template in the Projects pane (Figure 27.10).
5. Click the Next button, as shown in Figure 27.10:
You can also set the location of the project according to your requirement.
985
Chapter 27: Java FX
986
Immediate Solutions
}
}
12. Import the following package in the FXMLDocumentController.java file:
import javafx.scene.paint.Color;
13. Add the following code in the handle event of the Button control:
if(txtBox1.getText().equals("deepak") && txtPass.getText().equals("dreamtech")){
label2.setTextFill(Color.BLACK);
label2.setText("Welcome "+txtBox1.getText());
}
else{
label2.setText("Invalid username or password!");
label2.setTextFill(Color.rgb(210, 39, 30));
}
987
Chapter 27: Java FX
14. Press the F6 key to run the JavaFXApplicationDemo application. The output appears, as shown in
Figure 27.16:
988
Immediate Solutions
@Override
public void start(Stage s) {
ImageView iV = new ImageView();
iV.setImage(new Image("JavaFX.png"));
StackPane sPane=new StackPane();
sPane.getChildren().add(iV);
Scene scene = new Scene(sPane);
s.setTitle("Displaying Image");
s.setHeight(400);
s.setWidth(400);
s.setScene(scene);
s.show();
}
public static void main(String[] args) {
launch(args);
}
}
Save the preceding code with the name AddingImage.java. Use the following commands on the command
prompt to compile and run the application:
C:\>javac AddingImage.java
C:\>java AddingImage
In the preceding code, we have used an image with the name JavaFX.png. This image should be present at the location
where you have saved the .java file.
989
Chapter 27: Java FX
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.transform.*;
import javafx.stage.Stage;
990
Immediate Solutions
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.stage.Stage;
@Override
public void start(Stage s) {
Canvas cnvs = new Canvas();
cnvs.setHeight(400);
cnvs.setWidth(400);
Group g = new Group();
GraphicsContext gContext = cnvs.getGraphicsContext2D();
drawShapes(gContext);
g.getChildren().add(cnvs);
Scene scn=new Scene(g);
s.setTitle("Canvas Demo");
s.setScene(scn);
s.show();
}
}
}
Save the preceding code with the name CanvasDemo.java. Use the following commands on the command
prompt to compile and run the application:
C:\>javac CanvasDemo.java
C:\>java CanvasDemo
Here is the output of the preceding code, as shown in Figure 27.21:
991
Chapter 27: Java FX
Summary
In this chapter, you have learned about the basic concept of JavaFX and its features. Next, you have learned
about the availability of JavaFX for different platforms. In addition, you have studied the JavaFX architecture
along with its different components. The chapter has also explained the development scope of various
applications using JavaFX APIs. Furthermore, you have studied the process of downloading and running sample
JavaFX applications. Finally, you have learned the use of JavaFX Scenen Builder software package.
992
Glossary
ABORT Command
It indicates that an image that was being tracked is Command consists of a list of strings which make
aborted before its production was completed. the external program file to be invoked and its
arguments, if any, significant.
ALLBITS
It indicates that a static image that was previously Data members
drawn is now complete and can be redrawn in its These are variables that are part of a class. You use
final form. them to store the data the object uses. Objects
support both instance variables, whose values are
Applet specific to the object, and class variables, whose
An applet is a program written in the Java values are shared among the objects of that class.
programming language that can be included in an
HTML page in the same way as an image is Deployers
included in a page. The Deployers are responsible for deploying EJB
applications and Web applications into the server
Appletviewer environment.
Facilitates to run Java applets.
Deque
Block It extends Queue to handle a double-ended queue.
A block indicates that a thread is waiting for the lock
or permit to access the resource. Distributed
Java is a distributed language as it can be used to
Buffers create applications to communicate over the network.
The Buffer class defines the core functionality
current position, limit, and capacity. Dynamic
During runtime of a Java program, the relevant
Charsets information that is used to verify and resolve access to
A charset defines the way the bytes are mapped to objects is required. This concept of providing runtime
characters. information is referred to as dynamically linking the
Class code.
This is a template from which you can create objects. Environment
The definition of a class includes the formal A mapping, which is system-dependent varying
specifications for the class and any data and from variables to values. The copy of the
methods in it. environment of current process is the initial value.
Collection ERROR
It is the top of the collection hierarchy. It supports It indicates that an image that was being tracked has
basic grouping of elements. encountered an error.
Glossary
FRAMEBITS javacdoc
It indicates that another complete frame of a Creates HyperText Markup Language (HTML)
multiframe image (which was previously drawn) is documentation for Java source code files.
now available to be redrawn.
javah
HEIGHT Serves as the C header and stub generator, which is
It indicates that the height of the base image is now used to write native methods.
available (and can be read from the height argument
javap
of the imageUpdate method).
Serves as a Java disassemble used to convert
Inheritance bytecode files into a Java program description.
This is the process of deriving one class, called the
JButton
derived class, from another, called the base class,
It is a push or command button.
and being able to make use of the members of the
base class in the derived class. JCheckBox
JApplet It is a checkbox that can be selected or deselected,
displaying its state visually.
It is an extended version of java.applet.Applet that
adds support for root panes and other panes. JCheckBoxMenuItem
jar It is a menu item that can be selected or deselected
and displays its state visually.
Serves as archive used to package related class
libraries into a single executable JAR file and also JColorChooser
helps to manage the JAR files. It is a pane of controls to allow a user to select a
java.applet color.
Provides classes that are necessary for creating an JComboBox
applet and those which are used to communicate It is a combo box, which is a combination of a text
with its applet context. field and dropdown list.
java.awt JComponent
Provides classes for creating user interface and It is the base class for Swing components.
painting graphics and images.
jdb
java.io
Serves as a Java debugger used to find errors in Java
Provides classes for system input and output through programs.
data streams, serialization, and the file system.
JDesktopPane
java.lang
It is a container used to create a multiple-document
Provides classes that are fundamental to the design interface or a desktop.
of the Java programming language.
JDialog
java.net
It is the base class for creating a dialog window.
Provides classes that are used for implementing
networking in Java programs. JEditorPane
It is a text component that allows the user to edit
java.util
various kinds of content.
Provides legacy collection classes, event model,
collection framework, date and time capabilities, JFileChooser
internationalization, and other utility classes, such as It lets the user choose a file.
string tokenizer.
JFrame
Java It is an extended version of java.awt.Frame that adds
Serves as a Java interpreter used to run Java applets and support root panes and other panes.
applications by reading and interpreting bytecode files.
JInternalFrame.JDesktopIcon
javac
It represents an iconified version of a JInternalFrame
Serves as a Java compiler used to translate Java component.
source code to bytecode files.
994
Glossary
JInternalFrame JRun
It is a lightweight object that provides many of the JRun is an Application server from Macromedia that
features of a heavyweight frame. is based on Oracles Java Enterprise Edition.
JLabel JScrollBar
It is a display area for a short text string or an image It is an implementation of a scrollbar.
(or both).
JScrollPane
JLayeredPane It is a container that manages a viewport, optional
It adds layers to a Swing container, allowing vertical and horizontal scrollbars, as well as optional
components to overlap each other. row and column heading viewports.
JList JSeparator
It is a component that allows the user to select one or It is a menu separator.
more objects from a list.
JSlider
JMenu It is a component that lets the user select a value by
It is a pop-up menu containing JMenuItem objects sliding a knob within an interval.
thats displayed when the user selects it in the
JMenuBar component. JSplitPane
It divides two components.
JMenuBar
It is an implementation of a menu bar. JTabbedPane
It lets the user switch between a groups of
JMenuItem components by clicking tabs.
It is an implementation of a menu item.
JTable
JOptionPane It presents data in a two-dimensional table format.
It makes it easy to pop up a standard dialog box.
JTextArea
JPanel It is a multiline area that displays plain text.
It is a generic lightweight container.
JTextField
JPasswordField It allows the editing of a single line of text.
It allows editing of a single line of text where the
view does not show the original characters. JTextPane
It is a text component that can be marked up with
JPopupMenu.Separator attributes.
It is a pop-up menu-specific separator.
JToggleButton.ToggleButtonModel
JPopupMenu It is the toggle button model.
It is a pop-up menu.
JToggleButton
JProgressBar It is a two-state button.
It is a component that displays an integer value
within an interval. JToolBar.Separator
It is a toolbar-specific separator.
JRadioButton
It is a radio button that can be selected or deselected, JToolBar
displaying its state visually. It is a toolbar, useful for displaying commonly used
controls.
JRadioButtonMenuItem
It is a radio button menu item. JToolTip
It displays a tooltip for a component.
JRootPane
It is the fundamental component in the container JTree.DynamicUtilTreeNode
hierarchy. It can wrap vectors/hashtables/arrays/strings and
create appropriate children tree nodes.
995
Glossary
Multithreading Unicast
This feature helps you write interactive programs, As the name indicates, it is an identifier for a single
wherein multiple tasks can be performed interface.
simultaneously, thus making it a robust
programming language.
WebLogic
The WebLogic Platform delivers application
Object infrastructure technology in a single, unified, easy-
This is an instance of a class, much as a variable is an to-use platform for application development,
instance of a data type. You can think of a class as deployment, and management.
the type of an object, and you can think of the object
as an instance of a class. Objects encapsulate WIDTH
methods and instance variables. It indicates that the width of the base image is now
available (and can be read from the width argument
Permit of the imageUpdate method).
A permit is like a token to a lock that allows the
thread to access a resource. A thread must have a Working directory
permit from the semaphore before obtaining a The current working directory of the current process
resource. When the thread stops, it returns the is the default value; usually the system property,
permit to the semaphore, allowing another thread to user.dir, imparts name to this directory.
access next.
996
Index
addSeparator, 333, 337-338, 340-343, 553, 557-559,
A 567-568, 570-571, 574-575, 577
AdjustmentEvent, 194, 266-270, 463-464
@Deprecated, 828, 830
AdjustmentEvent class, 266-267
@Documented, 828
AdjustmentListener, 194, 265-267, 269-270, 463-464
@Inherited, 828-829
adjustmentValueChanged, 266, 268-270, 464
@Overdrive, 828
ALIGN, 188, 228-229, 244, 405-406, 550
@Retention, 828-829, 842-843
ALLBITS, 305, 544, 936
@SuppressWarnings, 792, 828, 830
Annotations, 12, 770, 822-824, 826-831, 834, 836, 838,
@Target, 828-830
840, 842-844, 890, 975
AbstractCollection, 768-769, 779-782, 784, 786, 789-
anonymous inner classes, 145, 168, 202
790, 811, 813
AbstractCollection class, 779-780 append, 15, 26, 29, 38, 61-62, 65, 96, 131, 164, 248-249,
260, 329, 407-409, 412, 639, 641, 648-649, 653, 658,
AbstractList, 768, 780-782, 786, 811, 813 664, 670, 731
AbstractList class, 780-781 Appendable Interface, 164
AbstractMap, 767, 769, 795-796, 799 appletviewer, 6, 173, 187, 189-190, 192, 707, 841-842,
AbstractMap class, 767, 795-796 853
AbstractQueue, 768 Application Servers, 2, 9
AbstractSequentialList, 768-769, 781-782, 786 Application servers, 2, 9
AbstractSequentialList class, 781-782 ArithmeticException, 71, 109, 132, 135-138
AbstractSet, 769, 789-790 ArrayDeque, 769, 784-785
AbstractTableModel, 477 ArrayDeque class, 784-785
Accelerators, 549-550, 565-566, 574 ArrayList, 73, 100-102, 165-167, 703, 720, 733, 768-769,
access specifier, 18-19, 114-117, 120, 148, 150-151 775-777, 780, 782-784, 788, 794-795, 819-820
ActiveX, 174, 846 ArrayList class, 782-783
Adapter Classes, 147, 171, 200-202, 206, 214, 277, 320 Arrays, 13, 30-36, 38, 40, 42, 44, 46-50, 52, 54, 56-58,
60, 62, 64, 66, 68-70, 72-74, 97, 100-101, 105-106, 113,
adapter classes, 147, 171, 200-202, 206, 214, 277, 320
118, 124, 126-127, 129, 144, 184, 214, 294, 313, 354,
addElement, 471-472, 482, 495, 500, 811, 813 615-616, 651, 653, 672, 767, 769, 772, 775, 779-780,
addition assignment, 78, 88-89 782, 801-804, 818, 821, 826-827, 830, 865, 933, 944
addLayoutComponent, 229, 231, 234, 236, 239, 244, Arrays class, 767, 801-804
547 Atomic variables, 718-719
Index
998
Index
Collection, 5-6, 8, 25, 36, 66-67, 70, 96, 99-102, 105, currentThread, 678, 682, 684, 686-687, 689-690, 692,
123-125, 130, 142, 144, 148, 161, 166, 294, 306, 354, 694-695, 705
412, 522, 616, 626-627, 697, 715, 719, 723, 727, 731, Custom Class Loader, 677
736, 763, 767-769, 772-784, 786, 788-791, 793, 796- Custom List Cell Renderer, 443, 472, 488
797, 801, 811-812, 814-816, 820, 822, 825, 857, 871,
Customizers, 847, 849
880, 970
CyclicBarrier, 696, 699-701, 721
Collection interface, 100, 767-768, 776-777, 779, 822
CyclicBarrier Class, 699-700
Color class, 190, 300-301
Combo Box Model, 489, 492, 500
Combo Boxes, 172, 488-492, 494, 496-500, 502, 504,
D
506, 508, 510, 512, 514, 516, 518, 520, 549-550, 576, Data Types, 31, 34, 36-37, 40, 42, 45-46, 52, 66, 74, 112,
578 129, 478, 745, 775, 782, 879-881, 904-906, 908-909,
ComboBox, 172, 475-476, 493, 495-499, 534 919
ComboBoxEditor interface, 498 Database Access, 879, 881
Comparator, 52, 767, 778-779, 783, 790-792, 799-801, Database Metadata, 446, 879, 881
804, 821 DatabaseMetaData, 877, 881, 894, 909, 921-922
compareTo, 53, 91, 620, 644, 793, 808-809, 820-821 DatabaseMetaData.ownDeletesAreVisible, 922
ComponentEvent, 181, 194, 277, 280, 509, 587 Datagram, 726, 729, 732, 734-735, 756-758, 766
ComponentListener, 175, 177, 181, 194, 508-509 DatagramPacket, 726, 756-758
ComponentListener interface, 508-509 DatagramPacket class, 756-757
ComponentResized, 509, 587 DatagramSocket, 618, 726, 740, 756-759
componentResized, 509, 587 DataSource, 881-882
Concatenating Strings, 32, 58 debugging, 22, 106, 110, 141, 143-144, 355, 360, 954,
Concurrency Utilities, 673, 718-719, 723 956
Concurrent collections, 719 DEFAULT_LAYER, 369, 526
conditionals, 11, 75-78, 80, 82, 84, 86, 88, 90, 92, 94, 96, DefaultComboBoxModel, 495, 500
98, 100, 102, 104 DefaultComboBoxModel class, 495, 500
Connected Device Configuration (CDC), 8 DefaultMutableTreeNode, 475, 484-487
Connected Limited Device Configuration (CLDC), 8 defaultsProperty, 385
Connection interface, 875, 893-896, 899, 912, 914 Delegated Classes, 197
Connection management, 877, 879 deleteCharAt, 62, 65
999
Index
Desktop Panes, 578-580, 582, 584, 586, 588, 590-592, dual state, 216
594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614 Dynamic Link Libraries (DLLs), 3
destroy, 171, 186, 190, 214 dynamic method dispatch, 145, 157
Dialog class, 316-317, 344-346
Dialog Modality, 209, 213 E
Dictionary class, 814-815 Editable Combo Boxes, 489, 497
Disabled icon, 419-420, 426, 528-529 EditorKit, 409-411
Disabled Images, 396, 426 elevator, 246
DISPOSE_ON_CLOSE, 377, 517-518, 589 Embossing, 275, 313-314
Distributed Notification, 845, 873-874 Empty String, 32, 56, 60, 248, 346, 407, 732
Distributed Transaction, 881-882 encoding, 21, 53, 110, 642-643, 651, 735, 752, 798-799,
Divider Size, 521, 540-541 986
division assignment, 77, 89 Enum, 14, 17, 99, 177, 359, 473-474, 773, 805-809, 819,
division operators, 83 830, 877-878
Domain Name System (DNS), 743 equalsIgnoreCase, 54, 91, 320, 328, 330, 336, 738, 760
Double Buffering, 276, 673, 713-715, 724 ERROR, 21, 27, 38, 45-47, 51, 71, 73, 87, 109-110, 115,
130, 132-133, 135-136, 138, 151, 159-160, 163-164,
double buffering, 276, 673, 713-715, 724
207, 305-307, 367, 406, 423, 429, 513, 516, 544, 599,
Double Clicks, 256, 443, 472-473, 488 605, 627-628, 640, 657-659, 726, 749, 761, 805, 809-
DRAG_LAYER, 369, 526 810, 829-830, 868, 881, 893, 908, 926, 938-939, 945-
946, 966
drawArc, 191, 293, 299
Events, 142, 147-148, 171, 174-176, 181, 184-185, 194,
drawBytes, 191, 293
197-200, 204, 206, 209, 216, 218-219, 222, 225, 246,
drawChars, 191, 293 253-255, 261-262, 265-267, 269, 273, 278-279, 315,
drawImage, 191, 205, 270, 290-293, 305, 308, 311-313, 318, 320-325, 329, 334-335, 340, 350, 356, 362, 375,
708, 711-712, 714, 930, 934-936, 938-943, 946, 948 377, 397, 404, 419, 421, 426-427, 441, 444, 472, 486,
drawLine, 191, 205, 293, 297, 299, 668 489-490, 494, 496-497, 504-505, 508, 553-554, 593,
611, 621, 626, 722, 824, 835-836, 845-849, 852, 864-
drawOval, 191, 294, 297-298 865, 867, 871-874, 882, 926, 976-977
drawPolygon, 191, 294, 299 EventSetDescriptor, 849, 857, 865, 871
drawPolyLine, 191, 294, 299 exception handling, 109-110, 144, 877, 881
drawRect, 191, 294, 297-298, 327-328, 668, 714 exception subclasses, 891
drawRoundRect, 191, 294, 297, 299 Exchanger, 696, 702-703, 721
drawString, 146, 173-174, 187-188, 190-192, 201-203, Exchanger Utility, 702
206-207, 212, 264, 269, 289, 294, 374, 376, 378, 382,
589, 714, 841, 854, 856, 861, 867, 936, 938 executeUpdate, 897, 903-904, 913, 917, 924-925
Driver interface, 875, 877, 879, 892, 926 EXIT_ON_CLOSE, 212, 374, 377-379, 384, 406, 423,
435, 438, 475, 478, 480, 531, 584-586, 588, 941
DriverManager, 14, 875-879, 883, 892-893, 899, 903,
912-913, 926, 956, 966-968 Extension classes, 22, 28, 677
1000
Index
FileOutputStream, 207, 618-619, 634, 638-640, 665 Generic Class, 784, 788
Filtering, 444, 478, 480-482, 773, 933 getColumnLabel, 482-483, 909, 968
finalize, 105, 124-125, 144, 161, 294, 637, 639, 808, 839 getDividerSize, 536, 540-541
getFileName, 620-621
Finally, 13, 15, 17, 20, 27, 29, 86, 100, 106, 123, 133-134,
137, 186, 204, 244, 258, 330, 356, 406, 473, 484, 486, getFileStores, 626-628
522, 664, 698, 718, 768, 807, 834, 846, 854, 862, 899- getHeight, 177, 205, 287-288, 290, 309, 360, 379, 585,
900, 945, 947, 953, 968, 992 587, 862, 931, 934, 941-943
fireTableChanged, 482-483 getHorizontalAlignment, 399, 404-405, 419
Flicker, 673, 710-711, 714-715, 947 getKeyCode, 280-281
Floating-Point Literals, 31, 38 getLayoutAlignmentX, 234, 236, 239, 244, 542, 547
Floating-point numbers, 17-18, 33-34, 37-38 getLayoutAlignmentY, 234, 236, 239, 244, 542, 547
flow layout manager, 202, 216, 228-229, 231, 318 getListCellRendererComponent, 472, 500
FlowLayout class, 228-229 getModifiers, 222, 278, 280, 343, 573
FocusEvent, 179-181, 194, 196-198 getName, 13, 178, 285, 390, 515-516, 621, 645-647, 678-
focusGained, 196-198 679, 682, 685-687, 689-690, 692, 694-695, 705, 764,
FocusListener, 175, 181, 194, 196, 198 820-821, 839-840, 848, 858, 942
font, 177, 179, 182, 186, 276, 283-288, 294-295, 360, 363, getParent, 178, 343, 483, 486, 620-621, 645-647
381, 384-385, 387, 391-392, 398, 404, 408-409, 414- getPath, 475, 516-519, 620, 626-627, 645-646, 750, 942
416, 422-423, 457, 466, 569, 576, 824, 868, 986 getPathMatcher, 626-627
1001
Index
getPreferredSize, 178, 180, 185, 205, 218-219, 249, 254, HSPACE, 188
360, 404, 408, 410, 508-509 HyperlinkListener, 398, 410
getPreferredSize(), 178, 180, 185, 205, 218-219, 249, Hypertext Transfer Protocol (HTTP), 726
254, 360, 404, 408, 410, 508-509
getQuote, 733, 760
I
getRoot, 620-621
IDS Driver, 887
getRootDirectory, 626
if-else Ladders, 75, 93
getSelectedCheckbox, 227
IllegalArgumentException, 109
getSelectedIndices, 466, 468, 470
Image class, 276, 289-290, 927-928, 930-931, 934-935,
getSelectionEnd, 251
939-941, 944
getSelectionStart, 251
ImageIcon, 385-386, 391, 397, 401-403, 413, 424-425,
getSize, 178, 183, 212, 269, 271, 285, 288, 327-328, 360, 427, 431-432, 440, 449-450, 455, 472, 500, 530, 532-
415, 495, 509, 714, 840, 854, 856, 861, 867, 943, 947- 533, 559, 573, 575, 577, 927-928, 938
948
imageIcon, 385-386, 391, 397, 401-403, 413, 424-425,
getState, 203, 224, 226-227, 337, 340-341, 562 427, 431-432, 440, 449-450, 455, 472, 500, 530, 532-
getUserPrincipalLookupService, 626-627 533, 559, 573, 575, 577, 927-928, 938
getViewPosition, 448, 450 ImageIcon class, 397, 401-402, 424, 927-928, 938
Gif Writer, 209, 213 ImageObserver, 176, 180, 275, 290-291, 293, 305-306,
Global addresses, 736 314, 402, 483, 927, 930-932, 934-935, 937, 941-943
Graphics class, 187, 190, 276, 290-295, 298-299, 710, Improved maintainability, 719
940 Increased performance, 719
Grayscale, 275-276, 312-314 Increased productivity, 719
Grid Bag Layouts, 215, 238, 243 Increased reliability, 719
Grid Layouts, 215, 231, 243 Indexed Properties, 848, 864-865
GridBagConstraints class, 240-241 IndexedPropertyDescriptor, 865, 871
GridBagConstraints.BOTH, 242 indexOf, 54, 59, 62, 252, 778, 781-782, 787, 812
InetAddress class, 736-737, 739-740
H inner class, 147, 168, 202, 323, 377, 769
has-a relationship, 160 Inner Frames, 579-580, 582, 584, 586, 588, 590, 592,
594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614
HashMap, 767-769, 774, 796-798
InputEvent, 195, 277-278, 280, 566, 573
HashMap class, 767, 796-797
InputEvent.ALT_DOWN_MASK, 566
HashSet, 100, 198, 768-769, 774, 778, 789-792, 821
InputEvent.ALT_GRAPH_DOWN_MASK, 566
HashSet class, 769, 789-791
InputEvent.CTRL_DOWN_MASK, 566
Hashtable class, 774, 814-817
InputEvent.META_DOWN_MASK, 566
HIDE_ON_CLOSE, 377
InputEvent.SHIFT_DOWN_MASK, 566
HORIZONTAL_SCROLLBAR_ALWAYS, 408, 453,
455 inputMap, 360, 363, 385, 391
HORIZONTAL_SCROLLBAR_AS_NEEDED, 453 InputMismatchException, 109, 135, 137
HORIZONTAL_SCROLLBAR_NEVER, 453 InputStreamReader, 109-110, 164, 615, 641-642, 647,
660, 672, 742-743, 749
Host Name Resolution, 736
1002
Index
1003
Index
1004
Index
1005
Index
1007
Index
R S
RadioButton, 172 Scanner, 109, 132, 135, 137, 164, 615, 671-672, 738, 760
Readable Interface, 163-164 scope, 19, 98, 105, 115, 122-123, 129, 144, 151, 213, 736-
ReadAllBytes, 624 737, 970, 972, 992
readAllLines, 624 Scroll bars, 245-250, 252, 254, 256, 258, 260, 262, 264-
274, 407
Readers, 21, 352, 616, 651
scroll box, 246, 445
readLock, 721-722
Scroll Pane Headers, 443, 454
ReadWriteLock, 721-722
Scroll Panes, 244-248, 250, 252, 254, 256, 258, 260, 262,
reboxing, 68
264, 266, 268, 270-272, 274, 443, 445, 450, 454-455,
Reduced programming effort, 719 538, 591
registerAsParallelCapable, 677 Scrollable, 172, 265, 408, 410, 445, 450, 483, 890, 908,
Remote Notification, 845, 873-874 914-917, 919
removeLayoutComponent, 229, 231, 235, 237, 240, ScrollBar, 172, 194, 265-270, 353, 445, 451-452, 458,
244, 547 462-465, 468
replaceRange, 249, 251, 408 ScrollPane, 172, 247, 272-274, 329, 447, 453-455, 468-
470, 475, 479, 481
Replacing Strings, 32, 59
ScrollPane class, 247, 272-273
ResultSet, 477-478, 482-483, 875-877, 879, 881, 884,
894-900, 904-911, 913-926, 967 Security Policies, 171, 207, 214
ResultSetMetaData, 477, 482-483, 875, 877, 881, 905, SELECT Annotation, 890
908-911, 967-968 Selected icon, 419-421, 426
ResultSetMetaData interface, 875, 908-910 selected-key set, 620
resume, 141, 680-681, 685, 705-706, 711-713, 847 Selection Modes, 469
RGBImageFilter, 312, 934 Selectors, 620
Rich Text Format (RTF), 397 Semaphore, 696-699, 721, 723
Rigid areas, 522, 543, 545 ServerSocket, 618, 726, 735, 743-748, 759
Rollover, 396, 418-419, 421, 426-427, 440, 574-576 Set Interface, 767, 769, 778-779
Rollover icon, 419, 421, 426 setActionCommand, 222-223, 334, 336, 404, 406, 420,
Rollover selected icon, 419, 421, 426 425, 494, 557-560, 569
RowSetFactory interface, 877 setBackground, 182, 190-191, 193, 203, 243, 256, 268,
279, 302, 326, 344, 363, 371-373, 376, 378, 472, 500,
RowSetProvider class, 877
512, 548, 584-585, 589, 714, 863, 947-948
Rowsets Object, 882
setBlockIncrement, 266, 268, 463
RowSorter, 478-480
setBounds, 182, 228, 326, 363, 376-377, 379, 517-518,
rs.deleteRow, 921 523, 525-526, 582-583, 589, 612-613
RTFEditorKit, 411-412 setCaretPosition, 409
Runnable, 211-212, 383, 425, 474, 478, 480, 533, 584- setCellRenderer, 467, 471
586, 588, 673-676, 680-681, 683-685, 687, 691, 695,
setData, 120, 757, 864
699-703, 705-706, 708, 710, 712-713, 720, 724, 759,
936-937, 947 setDefaultButton, 368, 427-429
1008
Index
1009
Index
StringBuffer class methods, 61-63 TextArea, 172, 248-252, 260, 271, 273, 328, 409, 414-
416, 595, 597
StringBuilder Class, 131-132
TextEvent, 195
stringWidth, 288
1010
Index
TreeSelectionListener, 486
TreeSet, 768-769, 778, 790-792
W
TreeSet class, 769, 790-791 Waiting, 161, 276, 330, 352, 631, 638, 675-676, 681, 688,
695-698, 700-702, 704, 707, 716, 718, 721, 942
try block, 109-110, 134, 136, 140
Warnings, 34, 830, 879, 881, 893, 896, 898
Two-Tier, 889-890
WeakHashMap, 769, 774
U Web-based Enterprise, 7
WebLogic, 9-10, 886-888
UIManager, 383, 386-389, 393, 511, 530, 537, 590, 595,
603 Weblogic OCI Driver, 886
Unicast, 736 while loop, 17-18, 75, 83, 95-97, 99, 135, 483, 924
Uniform Resource Locator (URL), 726, 930, 956 Whois, 725, 746, 766
UPDATE annotation, 890 windowClosing, 146, 148, 174, 206-207, 321-323, 328-
329, 347, 349, 414-416, 429, 517, 519, 589
URI Instance, 732
windowDeactivated, 321, 328-329
URL class, 290, 411, 726, 731, 735, 749-752, 880
1011
Index
WindowEvent, 146, 148, 174, 195, 206-207, 321-323, Wrapper Class, 32, 66-67
325, 328-329, 347, 349, 375, 377, 414-416, 429, 517, writeLock, 721-722
519, 589, 611
Writers, 616, 651, 721
windowFocusListener, 323, 325, 328-329
WindowListener, 194, 206, 320-323, 325, 328-329
Z
windowOpened, 321-322, 328-329
Z-order, 184-185, 521-524
Windows look and feel, 388, 390
ZipEntry class, 839-840
word-wrapping, 246
ZipFile class, 838-839
1012
A WIDE RANGE OF BOOKS