Vous êtes sur la page 1sur 135

Magic Boxes: Spiral Approach to Learning Java and Swing

Dzenan Ridjanovic

November 2003

Preface
The object oriented (OO) approach has proven itself both in theory and practice. It has brought productivity gains in design and programming of software and information systems. It is based on two fundamental concepts: inheritance and information hiding. Inheritance is used to create new things based on what has been already done. Information hiding is used to encapsulate data and provide meaningful operations that are immune to changes in data representations. Inheritance builds on experiences of others, and information hiding controls future changes. This new way of thinking, coupled with the concept of the client/server architecture, has contributed to the appearance of new programming languages better suited for todays demands and technologies. One of these new languages, Java, was conceived by Sun, among other things, for the development of applications that are better adapted to this new paradigm. The presence of a Java interpreter on the users workstation, which Sun calls The Java Virtual Machine (VM), removes the constraints related to a particular operating system or computer. The Java source code is analyzed and byte code files are produced to keep the code portability. Diverse mechanisms have been put into place in order to eliminate many of the initial problems related to the speed of execution of Java applications. The Java language allows the deployment of applications on platforms such as Linux, Windows or Macintosh. This process uses the same Java VM on the users workstation and in addition eliminates the constraints of proprietary platforms. In fact, considering that client workstations only need Java VM and that the applications and data are located on servers, this type of architecture favoring an efficient deployment of applications decreases the cost of maintaining a computer environment of this nature by thousands of dollars, according to a study done by the Gartner Group. To summarize, there are several important reasons why Java technology has become a strategic choice when building systems by way of the new paradigm that constitutes the object oriented approach in client/server environments. First, Java is an OO language. Second, Java code is portable. Third, Java applications are located on servers and may be executed both on clients and servers. Fourth, Java was born after Internet had started and has been designed from the very beginning to be Web enabled. For example, the Java code used in this book is available on my server, http://drdb.fsa.ulaval.ca/mb/, and can be executed on Internet. As stated above, using the OO approach and Java technology offers many significant advantages. However, the development of applications of this nature requires specific theoretical and technical knowledge that can be acquired only through a long and arduous process of learning. In order to shorten the learning curve that could take many long hours, I suggest beginning with the development of a small Java application using a graphical user interface (GUI). In addition, in order to simplify the learning process of the development of systems using the Java

language, which involves certain complex mechanisms, I propose using an iterative or spiral approach. This approach permits an evolutionary learning of concepts through a succession of development cycles going from very simple to more complex. This method allows us to comprehend on a simple example the most fundamental building blocks of the language that we can use and expand on in the subsequent cycles. Through this gradual process the learner, while discovering the inner workings and the beauty of Java, at the same time builds confidence in his own capacity and, when satisfied with the results, maintains the level of motivation necessary for the completion of such a learning objective. I have used this method for the past 6 years, with my undergraduate and graduate students, as well as in training sessions in organizations with excellent results. In a short period of time, starting with zero knowledge of Java, my students were able to make real life applications with remarkable achievements. The presentation strategy of this book, in my opinion, constitutes an added value when compared to the majority of (if not all) textbooks on Java currently available on the market. In effect, when we consult a textbook explaining the inner workings of a programming language like Java, we see the theory of the language sprinkled with disparate examples. Even with very attentive reading, we experience difficulties in building a system. It is only after numerous hours of practice that we can achieve our objectives. The approach presented here allows more rapid learning through a succession of iterative development stages. Certainly, I do not pretend to cover all technical aspects of the Java language. My main preoccupation in this textbook is the acquisition of the most important object oriented notions, rather than technical details. Once the basic elements are mastered, the learner will be better tooled for consulting other reference works available on the market. This text is especially suitable for those who wish to learn the new concepts inherent in the object oriented approach through practice. Consequently, both computer professionals who desire to expand and perfect their knowledge and beginners in the development of software and information systems can benefit from it. The code used in this book is written using a regular text editor. The code is compiled and executed using Java console commands that come with Java SDK (Standard Development Kit). SDK may be downloaded freely from java.sun.com. Integrated development environments (IDE) such as JBuilder (www.borland.com) and Eclipse (www.eclipse.org) may be used to edit, compile and execute the code. Personal version of JBuilder and Open Source Eclipse are both available for free. The text begins with a small, simple application, and gradually integrates OO concepts and GUI notions considered to be the most important. The spiral approach will allow a rapid, easy and step by step mastering of the concepts presented.

On the Spiral Approach


Learning a new, object oriented programming language, such as Java, is a difficult task. There are already many books on Java. Most of those books have many pages and cover many topics. And still, they are not sufficient to learn a modern language designed for the new world of Internet. Once you understand that you have to use more than one book to learn a complex technology, you have to ask yourself what is the easiest and fastest way to start learning such a technology. It took me more than ten years of learning and teaching to find out that the initial learning of a new technology must be task driven and not topic (subject) driven. Most books on Java are topic driven. It takes a quick look at the Table of Contents of almost any Java book to realize that each chapter introduces a new topic. In my teaching, I use a task driven, spiral approach, which consists of a single project developed in multiple spirals. In this book, the project is simple graphical software that allows a user to create "boxes" and move them around. Even for a simple project such as this, there are many spirals used. The first spiral creates a simple class in Java, which does almost nothing. However, there are several concepts used in this simple task and all of them are explained in Chapter 1. With each new spiral, the project grows and new concepts are introduced. A new spiral is explained with respect to the previous one. The difference between two consecutive spirals is that the new spiral has the new code introduced (+) and the old code modified (&) or deleted (-). This is called learning by anchoring to what we already understand. With a new spiral, we can come back to what we did previously and improve it. In this way, learning in spirals can touch the same topic several times, but each time with a new, better version. As a university professor, I have found out, that even students without any experience in programming, can learn the basics of object oriented programming in Java in ten weeks. It is true, that with this approach only a subset of Java is covered, the subset used to develop our project in spirals. However, once the subset is understood well, a reader can consult many other books on the market or Web, to learn more in an independent way. More experienced students like the spiral approach as well, since it allows them to be selective in their learning. By following a subset of spirals, or parts of a single spiral, they can reach their goal in a productive way. I have used a similar approach with Silverrun CASE (Computer Aided Software Engineering) tools, www.silverrun.com, first to teach Java, and second to develop commercial products in the role of Director of Research and Development. The spiral approach allowed me to focus on Java essentials in a more controlled way. I want to thank Rmy Mathieu for working hard on the French version of this book. Dzenan Ridjanovic Qubec, Canada, 2003 October 19

CHAPTER

Java Language Basics


This chapter presents the fundamental notions of the Java programming language allowing the development of a very simple application. More precisely, the goal of this chapter is to introduce: 1) the concepts of object and class, and 2) the concept of inheritance. The execution of the sample application in this chapter will not yield any visible results. Nevertheless, it is an important step in the development of Java applications.

Basic Structure
Object
The first task of someone in charge of the design of an information system consists of understanding the real world in which users interact. We must be sure that the final software product reflects reality as much as possible. From the point of view of the articulation and implementation of a data structure, we can say that our goal consists of organizing data in function of real world objects. The data structure used constitutes an abstraction of the reality. This data structure must be able to respond to the needs of users. The data structure is in fact an abstraction of the real world. The concept of objects encapsulates part of the knowledge of the real world in which users live. Like living beings, objects are born, live, and die.

Class
In order to group objects, we try to naturally join elements that resemble each other, attempting to identify structures of higher levels of abstraction. Each object belongs to A class is a description of a set of objects that share the same a class. definition domain. Consequently, each object belongs to a class. Generalities are part of the class while objects contain particularities. The creation of objects from a class is effected through a process called instantiation. Therefore, every object is an instance of a class. Object oriented languages such as Java reduce the distance between human reasoning and the languages understood by computers. As a result, it is easier to develop an application with an object oriented language than with a traditional language. Class: specification of data and operations. The notion of object makes reference to the class concept. In effect, the class describes the format of data and the definition of operations of an object that operate on the data. It is impossible to write Java code without using this fundamental concept. Here is our first example of a Java class:

Class Start

1: public class Start { 2: 3: public Start(){ 4: super(); 5: } 6: 7: public static void main(String[] args){ 8: new Start(); 9: } 10: 11: }

The class is used to define the data and operations of an object. In our example, the code shown above defines the class Start. The heading or signature of this class is displayed on line 1: 1: public class Start { A Java class: class Name { ... } The keyword public allows the access to the class from anywhere. The keyword class is followed by the name of the class. An open brace "{" followed by code (lines 2 to 10) defines the class. The specification of this class ends on line 11 by a close brace "{". Please note: The first character of a class should be a capital letter. - the majority of Java developers begin the names of their classes with a capital letter; - in order to connect the Java code with their corresponding explanation in the text, we use line numbers to the left of each line of code. Please note that these numbers along with : are not parts of the language as such. They are used strictly for information purposes.

Methods
Methods: the only way to access object data. Processing units are written most of the times in function of the data attributes contained in objects, and we call them the methods of the object. In fact, access to data attributes of an object is generally only possible through methods. Please note that it is also possible to define attributes and methods relative to a class and not to an object. The presence of the word

static in the definition of attributes or methods allows this particular aspect.

Constructor
Constructor: Special method included in each class that serves to create class objects. In order to associate data attributes and methods to an object in particular, we must beforehand create the object from the definition of its class. This process is realized thanks to a special method that is called the constructor of the object. All classes must possess a constructor. Otherwise, Java furnishes one by default. In fact, it is possible for a class to have more than one constructor, the difference lying in the arguments of each. The constructor has the same name as the class. The characters "()" follow its name. It is inside these parentheses that arguments are optionally placed. In our example, lines 3 to 5 show us the constructor of the class Start: 3: public Start(){ 4: super(); 5: } Contrary to the constructor, the first character of the name of a method must be a lowercase letter. In general, in a class, any name can be assigned to a method. Contrary to the constructor, method names must always begin by a lowercase letter. We recommend that you follow these programming standards proposed by the creators of Java, as these norms allow a better visibility of the code.

Constructor Name = Name of the class

The main Method


Like the constructor, the main method possesses intrinsic functions that distinguish it from other methods. In our example, the main method is defined as follows: 7: public static void main(String[] args){ 8: new Start(); 9: } When an application is launched, the Java VM calls the main method. The function that distinguishes the main method from other methods concerns the moment of execution of an application. The Java virtual machine (VM) calls the main method when an application is launched. In our example, the following line of code

7: public static void main(String[] args){ serves as the point of entry of our application. Line 8, 8: new Start(); shows us a way to call the constructor Start which creates an object according to the definition of the Start class. The calling of a constructor uses the keyword new. This keyword must always be present and must always precede the name of the constructor of a class object. This process of creation and definition of the values of an object has permitted to instantiate the class Start. We can also say that we have created an instance of the class Start. After creating an object, we are now allowed to invoke the methods of the object. The methods are accessible in three different ways: - in their class definition; - in another class of the application; - outside the application.

Inheritance
The creation of an object according to the definition of the class Start is realized by the execution of the code that composes the constructor Start. This deserves particular attention, as it uses the fundamental idea of class inheritance. All classes are interlinked on a hierarchical level below the class Object. In Java, there always exists a unique relationship between a class and its parent. Java uses a hierarchical structure between classes. At the top of the pyramid, we always find the class named Object. All classes are interlinked in a hierarchical fashion below this class.

Generally speaking, it is important to mention that Java does not use so called multiple inheritance. In fact, a unique relationship must always exist between a class and its parent class.

In our example application, the relationship between the class Start and the class Object is realized by the execution of the constructor of the parent class Object. This call to the constructor of the class Object is explicitly defined within the constructor of the class Start and is as follows: 4: super(); If the term super is absent, Java presumes that it exists by default. A constructor must invoke the constructor of its parent class or superclass. This call must always be the first term of the constructor of the child class. If the term super is absent from the child class, Java executes it by default. Technically, the term super allows Java to obtain references to the public data attributes and methods from its inherited class.

Modifiers
The keyword static to the left of the name of a method signifies that this method shall be referenced by its class and not by an object of the class. It is possible to call a method, such as the method main, without having previously created an instance of the class Start. This is made possible by the presence of the keyword static in the signature of the method main of our sample application: 7: public static void main(String[] args) We see here that three special words have been placed to the left of the name of the method main. The terms public, static and void are in fact modifiers and are part of the list of reserved keywords of Java. The keyword public The modifier public placed in front of the name of a class as in placed in the signature line 1 allows the access to public data and methods of the class from of a class allows anywhere within or outside the class. access to the class from anywhere. As we can see on line 7 of our example, the method main, which has the modifiers public and static, can be called from outside the class Start. In effect, the Java runtime environment calls this method when the application is executed, in the following way: Start.main(); This example shows how the method main can serve as the point

of entry to the application from outside the class Start. The general syntax of the method invocation, which does not require the creation of an object, is as follows:
<Name of the class>.<name of the method>([parameters])

Also note that when a method is found in the same class as the method that invokes it, the name of the class followed by "." can be omitted. With void, no explicit A method can return, at its point of invocation, a value. However, result is returned by situations arrive where a method does not need to return a value. In the method. this case, the modifier void specifies this constraint. In order for the external environment of a Java application to be able to give control of the application to the method main, it is important to include the modifiers public, static and void to the method main, since: the method main must be public so that it can be called outside the application; since no object has yet been created, it is appropriate to use the keyword static in the specification of the method main. Calling the method main is then qualified by the name of its belonging class; the Java VM must not receive any value after execution, which explains the mandatory use of the modifier void.

Parameters of a Method
Messages are sent by In order to communicate information between different parts of an way of parameters application, Java uses parameters attached to methods. These are associated to methods. placed immediately to the right of the method name within parentheses. After the parameters, the programming elements of the method are enclosed by braces {}. In our example, the method main contains a single parameter: String[] args The term String makes reference to a predefined Java class that

allows you to work with text. In fact, Java offers several predefined classes. The class Date is another example.

Array
The word args in the method main is its parameter. The word args that follows the predefined class String serves to name the parameter of the main method. The word args is in fact a local variable associated to the main method. The brackets [], to the right of String, serve to define the parameter args as a reference to an array. In the example of the class Start, no reference is made to args within the main method. Despite the fact that this parameter is not invoked anywhere, we must nevertheless define it as a text array.

CHAPTER

JBuilder Development Tool


To illustrate what a Java development tool may look like, and to allow the editing and execution of the Java code used in this book, it seems important to show how a Java application is handled by a development tool. The code used in this book is written using a regular text editor. The code is compiled and executed using Java console commands that come with Java SDK (Standard Development Kit). SDK may be downloaded freely from java.sun.com. An integrated development environment such as JBuilder (www.borland.com) or Eclipse (www.eclipse.org) may be used to edit, compile and execute the code. Personal version of JBuilder and Eclipse are both available for free. In this chapter the personal version of JBuilder will be introduced briefly. Many good tutorials on Eclipse may be found on www.tutorial-omondo.com. There are several sections that make up the principal graphical user interface of JBuilder. The first section contains the menu bar. A toolbar containing JBuilders visual components is also a part of the first section. The second section displays different components of an application. By clicking on the component Start.java instead of inChap2.jpx, we obtain the code of the class Start in the right part of the second section. Our goal here is not to show the strengths and weaknesses of JBuilde, but to show users how to use such a tool in order to prepare the application environment and then launch the Java application. If you wish to continue learning JBuilder, it will always be possible to refer to the online help. In summary, this chapter provides a brief overview of the personal version of JBuilder. Even if you will not be using this tool, I recommend that you nevertheless read the entire chapter. Certain comments such as those on application files and "packages" will be useful to everyone.

Preparing the Application Environment


In order to be able to implement the sample application presented in Chapter 1 in JBuilder, the application environment must be first prepared.

Directory
To group all the examples in this book in a single location, we propose creating a directory code under magicBoxes. Then all that remains to be done is to create a directory for each chapter. The final result should give the following: According to the standards established by Java community, directory names must begin by a lowercase letter. - magicBoxes - code - ch01 - ch02 - ch03A - ch03B Please note that the directory ch01 refers to the programming code of Chapter 1.

Project
Once the directory structure of our application is established, the second thing to do (before beginning to work with Java classes) consists of creating the "project" of the application. In the example application of Chapter 2, the project file used is ch02.jpx. Project: Permits saving options as well file references in the application. The project concept allows grouping and saving different files as well as options used by the application under the project name. We created the project by clicking on the File menu located at the top of the first window in JBuilder, followed by the menu option New Project... : The field Name allows you to name the project that we are currently defining (ch02). By clicking on the ... button, you

can determine the project directory path. The field Directory allows you to specify the project file location. Once the project file name and directory path is defined, all that remains to be done is to define the source code (*.java) directory path and output (*.class) directory path. Here is the new contents of the directory ch02 once the creation of the project is finished: - magicBoxes - code - ch02 ch02.jpx In addition to the project file ch02.jpx, JBuilder may create the project notes file ch02.html. This file allows the display of project information in the "html" format.

Application Files
Source Files
In addition to project information stored in the file with the extension ".jpx", the Java class code must be stored in source files. In Chapter 1, we used the file named Start.java. The extension ".java" indicates what type of file we are dealing with. Here are the steps to follow to create a new source file: 1- Select the File menu followed by the option New...; 2- In the window that appears, in the tab "General", select the "Class" icon and click on "OK"; 3- Insert the name of the class in the field "Class Name". In our example, the class name is Start. After empting package name and selecting the Public and Generate default constructor options, JBuilder automatically generates the following Java code:

public class Start { public Start() { } } All that remains to be done is to insert the appropriate Java code, such as what will be presented in the next example in Part A of Chapter 3.

Compilation of Classes
Compiled class: When a class is compiled, the resulting "byte code" is stored in a file <Name of the with the same name as the class followed by the extension .class. class>.class In our last example, the source file Start.java will serve to create another file named Start.class. In order to make all files more manageable, we strongly recommend that you physically separate the files of type ".class" from the source files (".java"). To do this, we have created the directory classes for compiled files and the directory src for source code files. For example, here is the directory structure used by the application in Chapter 2: - magicBoxes - code - ch02 - classes - src Please note that the subdirectories below classes are created automatically by JBuilder during compilation. The names of these subdirectories correspond to those of the source files in src.

Project Properties
The menu item Project properties... in the Project menu allows you to define project properties. When selecting this item, JBuilder presents the project properties starting with the tab

Paths: The following file path, ...\magicBoxes\code\ch02\src inserted in the sub page Source, must correspond to the location of the source code files, such as Start.java. As for the example path shown below in the field Output path, ...\magicBoxes\code\ch02\classes it corresponds to the real location of the files of type ".class", such as Start.class. The functions offered by the buttons and Edit allow you to easily modify the two file paths discussed above. In the same window where the project properties can be specified, the tab Run allows you to indicate the class as well as the directory of the application entry point (method main). The specification of the application entry point allows JBuilder, during the launching of the application, to know which class to refer to for the launch. If this property is not defined, we have to select the class that has the main method before launching the application. Note that the launching of the application can be done in three different ways: 1 2 3 By clicking on the run button in the first section of the JBuilder graphical user interface; By using the Run menu, the menu item Run Project; By pressing the F9 function key.

Package
Package: collection of classes The development of a Java application requires a particular grouping of classes. It is the package concept that permits us to carry out this type of grouping. For example, we may want to regroup certain classes in the package mb.view and other classes in the package

mb.model. In concrete terms, the name of a package corresponds to the path of the directories below the location of the src directory (or classes directory). In terms of Java code, the keyword package followed by a path of directories allows the specification of the location of the source files. In our example (Part A, Chapter 3), you will need to include the following statement above the definition of a class: package mb; More precisely, we would have the following Java instructions: package mb; public class App { . . . } A package statement This last example allows the definition of the App makes reference to one (App.java file) within the directory mb. or several directories. class

Libraries of Pre-Defined Components


To facilitate the development of applications, companies such as Sun offer libraries (packages) of predefined components. For example, Sun offers a collection of interface components called Swing in the package javax.swing.

External Class
Import from When we wish to use a class belonging to another package, we

elsewhere: import

must import the class into the desired class. The command import, as shown in the following example, allows us to do this: import javax.swing.JFrame; In this example, the class JFrame is imported from the package javax.swing. Also note that the package java.lang is always included by default even if no import statement concerning this package has been specified.

CHAPTER

Application / Applet Frame


It is an application window or frame that determines the application context. The result obtained in the first part of the chapter (Part A) corresponds to the principal application frame that is empty in terms of contents. This object, although empty, consists of a title bar. In the second part of this chapter (Part B), we will first modify two states of the application frame, in order to add a title and to specify exactly the width and height that we wish our graphical user interface to have. This chapter will introduce the concept of Java applets. From now on, we will furnish supplementary Java code within our applications so that they can be executed on an Internet browser. One of the goals in the second part of this chapter therefore consists of presenting these "special" Java applications that are called "applets". The execution of the applet is simply done by linking to a standard HTML (Hyper Text Markup Language) page (start.html file). The reference to the applet is found within this file that can be located in the classes directory of the application.

Part A:

Application Frame

External Class
In the first part of this chapter, we are continuing the development of our sample application from Chapter 1. The class Start now calls the constructor of the new class called App. Here is the new representation of the class Start: 1: package mb; // + 2: 3: public class Start { 4: 5: public Start() { 6: super(); 7: System.out.println("Magic Boxes"); // 8: } 9: 10: public static void main(String[] args) { 11: new App(); 12: } 13: 14: } The location of all external classes used outside of the "package" of the current class must be explicitly defined by way of the import statement. Since the physical location of the class App does not correspond to the one of the class Start (from which the application is launched), it is therefore necessary to specify the location of the external class App. In concrete terms, it is the import statement in line 1 that specifies the location of this external class. As a reference, here is the directory path allowing access to the class App: \magicBoxes\code\ch03A\src\mb

Inheritance
The first and only statement within the point of entry of the application corresponds to line 11 shown below: 11: new App(); This statement calls the constructor of the App class. As we have already mentioned, each constructor (except that of the Object class) always invokes the constructor of its superclass by way of the keyword super. Therefore, the first instruction of the constructor of the App class 25: public App() { 26: super(); 27: appFrame = new JFrame(); 28: appFrame.setVisible(true); 29: } explicitly invokes the constructor of its superclass. Given that the class App does not explicitly indicate a link with another class, an inheritance link is then established, in line 21, to the Object class. This link permits the attributes and references to the public methods of the Object class to be copied to the object being created.

Frame
The objective of the App class is to define the frame of our sample application. Here is the code of the App class: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: // {+} package mb; import javax.swing.JFrame; public class App { private JFrame appFrame; public App() {

26: super(); 27: appFrame = new JFrame(); 28: appFrame.setVisible(true); 29: } 30: 31: } The statement in line 15 15: package mb; defines the location of the class source file in the mb package. The second statement of the App class makes reference to the following import command: 19: import javax.swing.JFrame; This statement imports the class JFrame that we will need in order to define the appFrame attribute on line 23. The JFrame class is part of the package javax.swing. In concrete terms, the code of the JFrame is not part of the application source code as such. The use of methods offered by external classes such as JFrame considerably facilitates application development.

Data Types and Class Attributes


Data types = data definitions Like all other programming languages, Java uses "base" data types in order to represent the format and structure of data variables that it uses. These data types are grouped in four categories : Category 4567Integer Decimal Character Boolean Java Base Type byte, int, long, short double, float, char boolean

For example, in the definition of the external method setVisible (used on line 28), public void setVisible(boolean b) the b parameter that corresponds to the boolean base type is defined as a local variable in the method setVisible. For this particular

data type, only two values are permitted: true or false. The local variable b is initialized to true when the method setVisible is called: 28: appFrame.setVisible(true); The following line: 23: private JFrame appFrame; Swing: Java package that defines graphical user interfaces. defines the attribute appFrame of the type JFrame. In this example, the data type corresponds to the predefined Java class JFrame from the javax.swing package.

Base type: With base data types, you have direct access to the value of the direct access to the variable. With class data types, you have access to the reference of an value of an attribute. object. Class type: access to the reference of the object. The attribute appFrame on line 23 is data part of the object defined during the execution of the constructor of the App class. This attribute is of the JFrame type. It does not refer yet to an object, so its value is null. Its value will change from null to an object reference on line 27: 27: appFrame = new JFrame(); The character "=" followed by the constructor of the JFrame class returns to the attribute appFrame the reference to a minimal "application frame" defined through the constructor of the class JFrame.

Independent Inheritance Hierarchy


The object appFrame possesses an inheritance hierarchy different and independent of the class to which it belongs (App). AWT : Java toolkit used in the development of multiplatform graphical user interfaces. By its intrinsic inheritance structure, the JFrame class inherits the Frame class as well as its ancestors (JFrame Frame Window Container Component Object). The Frame class is part of the Java AWT (Abstract Window Toolkit). AWT is a toolkit that allows you to develop graphical user interfaces that can work on any platform.

private Modifier
The keyword private used in the definition of the attribute appFrame 23: private JFrame appFrame; is a modifier that restricts access to appFrame. For example, if the modifier of the constructor of the App class was equal to private instead of public, the class Start would have been unable to call its constructor (see line 11). A compilation error would have resulted indicating that the constructor of the App class has the private accessibility.

Displaying the Application Frame


After defining on line 27 the object appFrame of our application frame, all that remains to be done is to display it. The following line does it: 28: appFrame.setVisible(true); This seemingly simple statement nevertheless contains several important notions.

Calling a Method from an Object


Line 28 of our sample application makes reference to the concept of using a method associated to an object. The general syntax of the relationship between an object and a method is shown below : <object name>.<method name>([parameters]) It is the method header (signature) that determines if an object or class must be associated to a method. In our example, we can immediately see that the method setVisible is not part of the classes Start and App. Since we do not know this method, we must necessarily find

its header in order to learn the nature of its function. A development tool offers often an interesting search function that allows, among other things, to find the methods associated to a class. To find the method setVisible, click on the Help menu followed by the menu item Help Topics. Once the search window is displayed, click on the tab "Find" and type setVisible in the textbox ("Type the first few letters of the entry:"). The search for setVisible shows that the name of this method is used in several classes. Since the object appFrame is part of an inheritance structure including the Component class, it is clear that it is this class that interests us. By double clicking Component class, we obtain among other things the list of all methods of this class. We can see in the method header of setVisible that the term static is absent. This determines that the use of the method is at the object level and not at the class level. Also note that it is the modifier public associated to setVisible that allows this method to be used outside the Component class.

Property
A property allows you A property is a state that conserves a specific object value. In our to save a specific state example of the use of the method setVisible, a state is associated of an object. with the appFrame object in order to determine whether this object should be displayed or not on the users screen. This state is saved in a private attribute named visible. This attribute contains the boolean value true or false. A property is a private In order to modify the value of a property, read and write methods are

attribute possessing special methods composed of the prefixes "is", "get" or "set" followed by the name of the property, with the first letter of the name capitalized.

used. These methods begin with the prefix "is", "get" or "set" followed by the name of the property attribute. The name of the property attribute used as a suffix in the method name must begin by a capital letter. By following these basic rules, we see that it is the setVisible method that allows you to specify or to change the state of the property visible of the object appFrame. Also note that the "set" methods all have the modifier void. The value allowing the modification of the property state is passed as a parameter.

Part B:

Applet

Eliminating the Class Start


In the preceding section, we used two classes to define the principal frame of the application. Defining the main method in the Start class served as the point of entry into the application. In addition, the statement in line 11 called the constructor of the class App. In concrete terms, we saw that the Start class constructor was not part of the application as such. Also, the Start class was only used to launch the application. This procedure was presented to show the difference between the definition of the application frame and the point of entry into an application. Given the number of times the Start class was used outside of the application as well as its unused constructor, we consequently choose to eliminate the Start class and include all of its functions in the class App. Here is the new App class that now also serves as the point of entry into the application: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: + 14: 15: 16: 17: 18: 19: 20: 21: package mb; import javax.swing.JApplet; import javax.swing.JFrame; // + // &

public class App extends JApplet { private JFrame appFrame;

public App() { super(); appFrame = new JFrame(); appFrame.setTitle("Empty window");// appFrame.setSize(400, 300); // + // appFrame.setVisible(true); //} // {+} // Start.java // public void init() {

22: appFrame.setLocation(80, 80); 23: } 24: 25: public void start() { 26: appFrame.setVisible(true); 27: } 28: 29: public void stop() { 30: appFrame.setVisible(false); 31: } 32: 33: public void destroy() { 34: appFrame.dispose(); 35: } 36: 37: public static void main(String[] args) { 38: App app = new App(); 39: app.init(); 40: app.start(); 41: } 42: 43: } We see, among other things, the addition of the main method (lines 37 to 41) which has as its sole purpose to execute the App class constructor that defines the principal application frame. The super statement on line 11 now calls the JApplet class constructor instead of the Object constructor as in Part A of this chapter.

Inheritance
In order to be able to use our applications in an Internet browser, we link the class that launches the application to the class JApplet. The App class is now an integral part of the following inheritance structure: App JApplet Applet Panel Container Component Object. This new link established between the App and JApplet classes is defined by the keyword extends in the header of the class App: 6: public class App extends JApplet {

The term extends defines a hierarchical inheritance relationship between the child class and the parent class.

This defines a hierarchical inheritance relationship between the two classes. In concrete terms, this link is established with the name of the class specified after the keyword extends. Therefore, in the example on line 6, the JApplet class is called the parent class (or superclass) and the App class is called the child class (or subclass). We also say that the App inherits from the class JApplet. In addition to being able to access its own attribute as well as its own methods, the App class can also use the properties and methods that the creators of the JApplet class (as well as those contained in a hierarchical link above it) have made available. Therefore, the JApplet class is in turn inherited from the class Applet. This chain mechanism of classes continues up to the class Object.

Comments
Like other programming languages, Java allows the insertion of comments to document certain points of a program that need particular attention. As a result, it will be easier for another person to understand the code. The insertion of comments can take one of two forms: // comment or /* 1st line 2nd line . . . last line */ // A single line of comments or /* 1st 2nd line of comments line of comments . . . last line of comments */

Java code can be found also to the left of a line of comments, such as on line 13 below: 13: appFrame.setTitle("Empty window"); // +

The chain of characters "//", "/*" or "/**" indicates to Java that the information that follows is for documentation purposes only. Also note that the characters "/**" can replace "/*".

Conventions
As already mentioned, this book uses a series of development cycles (spirals). We start with a small Java application that is as simple as possible and gradually we add or modify the appropriate Java code. In order to better visualize the modifications performed in a chapter or to compare the current chapter with the previous chapter, we will use the following comments or conventions: // + // + Addition of a new statement

For example: 13: appFrame.setTitle("Empty window"); 14: appFrame.setSize(400, 300); // + // & // // & // Modification of a statement Deletion of a statement // +

For example: 19: // Start.java // This comment signifies that the Start has been deleted from the application. Of course, in order, for Java, not to interpret what is found to the left of "// -", it is manadtory to insert "//" at the beginning of the line.

Modifications Applicable to a Block of Statements


When a block of statements is added, we will use the following convention: // {+ ... // +} // {+ Added Java statements // +} This way of proceeding avoids the insertion of "// +" at the end of each added line. The same thing applies to a block of statements requiring modification. Here is the convention that will be used in this situation: // {& // {&

... // &}

Modified Java statements // &} Contrary to the addition or modification of Java statements, the deletion of lines will use the following convention:

/* {... -} */

/* {Deleted Java statements -} */ For the addition of a new class or the addition of code up to the end of a class, the following convention will be used:

// {+}

// {+} Addition of new lines of Java code up to the end of the class For example: 18: // {+} When "// {+}" is placed on the first line above the definition of a class, this comment signifies that we are introducing a new clas

Modification of the State of an Object


title Property
Two statements have been added to the constructor of the App class. Line 13 below 13: appFrame.setTitle("Empty window"); // +

specifies a title for our application frame. In concrete terms, this statement modifies the state of the title property defined for the class JFrame. Since this class is part of the inheritance hierarchy of the object appFrame, it is therefore permitted to use the property.

size Property
The same remark applies to the statement on line 14. Here, it is the

size property defined for the Component class and consequently the public methods associated to this property are inherited from Component. The method setSize allows us to redefine the width and height of the application frame. By default, during the construction of a frame object such as appFrame, the width and height of the frame are equal to zero. When these default values are in use, we obtain only the title bar of the frame. In the second situation, that is, when the setSize method is used, the application frame contains a space calculated in function of the values passed. These values correspond to a number of pixels. The width of the title bar of the window is adjusted to the width of the new size of the object. In our example, when the execution of the program arrives to line 13, we are dealing with the modification of the property and not its creation. Please note that two integers are passed to the method setSize. Since two setSize methods exist for the class Component: public void setSize(Dimension d) public void setSize(int width, int height) the method parameters will determine which method Java will use. In our example, it is the second signature. By calling the setSize method in line 14 14: appFrame.setSize(400, 300); // +

we pass the values 400 and 300 to the parameters of setSize. This method modifies the state of the size property that is of Dimension type. In concrete terms, the size is determined by: - width: frame width; - height: frame height.

Browser and Java Runtime Environment

General View
Applet: collection of related Java classes that can be executed on an Internet browser. Application: collection of related Java classes that can be executed on a users computer. Generally speaking, we can define a Java applet as a collection of related classes that can be executed on an Internet browser. Applets are launched from an "html" page. The name of a start class is then specified in this page. In relation to a standard Java application, it is only this start class that is modified. The major part of the underlying programming of other classes is identical. We will come back a little later to details of modifications to be done. Please note that in this book, the term application is a collection of related Java classes that permits the execution of a series of operations on a users computer. In order to recognize and execute statements that make up Java applets, a browser must be equipped with a Java Runtime Environment. Java runtime environment is a part of Java Standard Development Kit (SDK).

Applet / Server
To begin, we assume that an applet is located on a server connected to Internet. When an "html" file is referenced, the browser does a search for the file on the server in question. If the file is found, it is loaded and executed on the users browser. When an "html" page calls a Java applet, a second request takes place. This time, all the "byte code" files that are part of the applet are loaded. These files are located on the same server as the "html" page previously loaded. Since the loading of the applet may involve several classes, the time required for the load may be relatively long. To accelerate the process, all ".class" may be compressed into one file, called a jar file. Afterwards, the jar file is placed on the application server.

HTML Plugins
As already mentioned, it is the start.html file, located in the classes directory of each application that is loaded as the startup web page. When loaded, the page will trigger the loading and execution of the applet. In the start.html file, a special section has been added in function of the particularities of the two major browsers on the market. Explorer interprets the following OBJECT block:
57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="400" height="30" align="baseline" codebase="http://java.sun.com/j2se/1.4.2/download.html"> <PARAM NAME="code" VALUE="mBox.appForm.App.class"> <PARAM NAME="codebase" VALUE="."> <PARAM NAME="archive" VALUE="mbLib.jar"> <PARAM NAME="type" VALUE="application/x-java-applet;version=1.4"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" width="400" height="30" align="baseline" code="mBox.appForm.App.class" codebase="." archive="mbLib.jar" pluginspage="http://java.sun.com/j2se/1.4.2/download.html"> </EMBED> </COMMENT> </OBJECT>

All instructions inside the EMBED block (lines 68 to 77) are not recognized in Explorer. With Netscape, the contrary is true. In fact, in Netscape, OBJECT and COMMENT are not recognized. This section (lines 57 to 80) was specially introduced to use extra functionalities not available to basic browsers. It consists of using an application capable of doing additional work that the browser cannot do itself. This type of application is called a "plugin". In the example presented, you need to add, if its not already done, Java runtime environment to the browser. The browser then verifies if it already has this plugin. If not, it asks the user whether he wishes to load the plugin that can be found at the address specified in line 61 or 76. The address allows the user to download the Java Runtime Environment or Java SDK from the Sun Java server. The type parameter on lines 65 and 69 states that we wish to work with Java Runtime Environment or SDK version 1.4. It is on lines 64 and 75 that the archive parameter optionally

indicates the name of the jar file. If the option to use jar files had not been used, all ".class" files would need to be placed on the server. In addition to the jar file, the server must also have the basic html page. For example, the server could have the following directory (magicBoxes) and files: - magicBoxes mb.jar start.html It is the location of the class that launches the applet that is specified within the HTML file. As we have already mentioned, an applet, like a standard Java application, possesses a "launching" class (startup class). It is this class that is specified in the HTML file as shown in the following lines:
62: <PARAM NAME="code" VALUE="mb.App.class">

or
73: code="mb.App.class"

This part of the HTML code indicates the class name of the Java applet. In this example, it is the App class in the mb package. The width and height properties on lines 58, 59, 70 and 71 define the width and height of the area used by the applet in the HTML page. In our example, it is a fictitious area used principally to display a message indicating the loading of the applet from a server.

Data Access on Another Computer


According to certain security permissions, Java may allow applets to read and write files on a users computer. Another important aspect concerns access of an applet to data on a users computer. Java security constraints prevent applets to have an unlimited access to files on a network. Even though Java allows, according to certain security permissions, reading and saving files on another computer, we must mention that in general and by default, applets do not have access to files on a users computer. In concrete terms, a verification of the "byte code" files before being loaded on a users computer is performed in order to determine whether any Java conventions have been violated. For example, the code is checked to see if it accesses memory locations that contain other applications or files.

Execution Norms of Applets


Many applet functions are contained in the class Applet. A rule requires the class that inherits from the JApplet class to include the methods init, start, stop and destroy predefined in the class Applet. These methods need simply to be rewritten according to the required needs. The order of execution of an applet is as follows: 1- The constructor of the class that launches the applet; 2- Method init; 3- Method start; 4- Method stop; 5- Method destroy. Immediately after the Java applet is loaded, the constructor of the class that launches the applet is executed. In our example, it is the App constructor: 10: public App() { 11: super(); 12: appFrame = new JFrame(); 13: appFrame.setTitle("Empty window"); 14: appFrame.setSize(400, 300); // + 15: // appFrame.setVisible(true); //16: } Please note carefully that the following main method 37: public static void main(String[] args) { 38: App app = new App(); 39: app.init(); 40: app.start(); 41: } is not used in the execution of applets since, contrary to the Java VM, the Java Runtime Environment included in browsers automatically calls the constructor of the launching class instead of calling the method main. However, as we have already mentioned, in order to be able to also execute an applet as an application from a development tool, we recommend that you nevertheless include the main method like the one included in the App class. The method init. Once the execution of the App construction is terminated, the init method is then called. Its principal function consists of effecting certain initializations, such as redefining the size of the graphical

// +

interface, the creation of certain instances, initialization of certain parameters, the loading of images, and so on. In our example, we use the following init method: 21: public void init() { 22: appFrame.setLocation(80, 80); 23: } Note that the developer must always include this method in the class that launches an applet, even if it doesnt include any Java instructions. The same is true for the methods start, stop and destroy. The method start. After having terminated the execution of the method init, the browser proceeds to the execution of the method start. In our example, the start method is as follows: 25: public void start() { 26: appFrame.setVisible(true); 27: } Please also note that the start method can be invoked another time when the browser needs to restart an applet suspended after the stop method is executed. A stopping of the execution of an applet can occur when a user leaves a web page by clicking on another link. If the user returns to the page, the start method is then recalled. This constitutes a major difference between the init and start methods. The init method is called only once during the lifecycle of the applet whereas the start method can be called more than once. Generally, the start method contains code that allows, among other things, to display or send messages to other objects. In our example, this method serves to restart the setVisible method allowing redisplaying of the application frame. The method stop. As previously mentioned, when a user leaves a page that contains an applet, the browser suspends the applet by invoking the method stop. The developer must include the stop method in the class that launches the applet. In our example, we have the following stop method: 29: public void stop() { 30: appFrame.setVisible(false); 31: } The method destroy. Finally, when an applet is no longer required, the destroy method allows, among other things, to liberate resources used by different

objects. For example, it could be the closing of files in current use. Generally, an applet is no longer required when a user clicks on the "Back" button in the browser or when he closes the browser (X button at the top right of the window or the options Close or Exit in the File menu). Without going into details, it is important to force the release of resources in the operating system of the users computer. Otherwise, too many resources in use may cause problems in the operation of the computer. The destroy method was conceived especially for Java applets. This method is consequently invoked automatically by the browser at the end of execution of an applet. In our example, we use the following destroy method: 33: public void destroy() { 34: appFrame.dispose(); 35: } The dispose method on line 34 liberates all operating system resources used by the object appFrame.

CHAPTER

Panel: Component and Container


The principal frame of an application must, of course, contain different graphical elements. It can even contain other containers that themselves contain certain basic graphical components such as buttons. One of these elements of an application frame is the panel. Generally, panels allow you to define certain application areas in which you can insert objects according to the needs established during the design process. The first part of this chapter shows how to create the empty diagram panel. In this example, we will see, in detail, that the part of the application frame under the title bar will be entirely hidden by the new panel presented (diagram object). In the second section of the chapter (Part B), we continue to refine the development of our graphical user interface by defining a panel with a blue background situated inside the diagram that is now the object of the Diagram class. Finally, the third section (Part C) ends the presentation of the concept of class specialization introduced in the previous section by creating the new Box class. This section also shows how to create our own properties, in contrast with the previous chapters, where we used properties belonging to external classes defined by someone else.

Part A:

Relationship Application Frame / Panel

Inheritance
As we can rapidly see, the App class presented in this section
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: package mb; import javax.swing.JApplet; // import javax.swing.JFrame; // import mb.view.AppFrame; // + public class App extends JApplet { private AppFrame appFrame; // &

public App() { super(); appFrame = new AppFrame(); // & // appFrame.setTitle("Empty window"); // appFrame.setSize(400, 300); // } public void init() { appFrame.setLocation(80, 80); } public void start() { appFrame.setVisible(true); } public void stop() { appFrame.setVisible(false); } public void destroy() { appFrame.dispose(); } public static void main(String[] args) { App app = new App(); app.init(); app.start(); } }

// -

is very similar to the one presented in Part B of the previous chapter. On line 9, instead of defining the appFrame object of type JFrame, we assign rather the class type AppFrame. This class is the second class presented in this section:
41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: // {+} package mb.view; import import import import java.awt.Color; java.awt.Container; javax.swing.JFrame; javax.swing.JPanel;

public class AppFrame extends JFrame { private JPanel diagram; public AppFrame() { super(); diagram = new JPanel(); diagram.setBackground(Color.white); this.setTitle("Empty Panel"); this.setSize(400, 300); Container cp = this.getContentPane(); cp.add(diagram); } }

Note that the App class contains an import statement in order to access the AppFrame class since both classes are not in the same package. The new relationship established between the AppFrame and JFrame classes is effected by the keyword extends in the header of the class AppFrame: 50: public class AppFrame extends JFrame As already mentioned, in addition to being able to access its own attributes as well as its methods, the AppFrame class can, in the same way, use the properties and methods that the creators of the JFrame class (as well as all those contained in the inheritance hierarchy above JFrame) have made available: AppFrame JFrame Frame Window Container Component Object. Attention: The words The AppFrame class as well as the appFrame object of our appFrame and example application are two things not be confused with each other.

AppFrame do not mean the same thing.

this
As we saw in Chapter 1, in order to associate data and methods to a particular object, we must create this object from its class definition. In our example, it is the AppFrame constructor from the class of the same name that is used to create the application frame. Since the AppFrame object does not have a name within the AppFrame class, we consequently have the problem of establishing the relationship between the current class object and its methods. this: current object To solve this problem and at the same time simplify the programming as much as possible, Java uses the keyword this. In our example, the object that is unknown within the definition of its class and that represents the current object, is replaced by the word this. The relationship between the object and a method is established only during the execution of statements such as in lines 58 and 59: 58: 59: this.setTitle("Empty diagram"); this.setSize(400, 300);

Class Specialization
Graphical user interfaces such as frames are simple containers. These containers can "contain" other containers like panels. Frames are, in a way, containers that can contain other graphical components. In the previous chapter we defined the first basic container that let us define the principal application frame. This container can obviously contain menus, images as well as other containers, such as panels. Part B of the previous chapter defined the App class in the package mb. The goal of this class was simply to display an empty application frame (appFrame object). In this section, we will use the AppFrame class to separate the definition of the object (AppFrame class) from its display (setVisible method in the App class). In a way, we want to specialize the appFrame object, previously of type JFrame. From now on, its type will correspond to the AppFrame class. This procedure allows a developer to specialize the definition of an object that is inherited from a predefined Java class: AppFrame Jframe Frame Window Container Component Object The definition of the object appFrame (inside the class AppFrame) includes the creation of a panel that will eventually be added to the frame. In our example, line 52 52: private JPanel diagram; defines an attribute of type JPanel with the name diagram. Then, with line 56 56: diagram = new JPanel(); an object of type JPanel is created. Its reference is assigned to the attribute diagram. The inheritance hierarchy of the diagram object is: JPanel JComponent Container Component Object. Generally, panels are principally used to group certain graphical components such as buttons, check boxes, labels or text fields. As we have already mentioned, panels are added inside other containers such as our application frame.

Frame Predefined Panels


The AppFrame class header creates an inheritance relationship with the JFrame class as follows: 50: public class AppFrame extends JFrame The inheritance relationship created with the JFrame produces a particular instance structure. Java automatically adds a container to appFrame. In reality, this container must be the only container associated to an object (such as appFrame) inherited from JFrame. This container references an instance defined from the class JRootPane. The internal architecture of the appFrame object is defined as follows: An object defined from a class whose parent is JFrame inherits one and only one container. This container is an instance of the class JRootPane. - appFrame object inherits from JFrame - composed of the unique container defined according to JRootPane that is composed of - glassPane component - layeredPane component that is composed of - [menuBar] component - contentPane component The object defined according to the JRootPane class corresponds to a panel that covers the same graphical space occupied by appFrame, except for the space occupied by the title bar of the frame. JRootPane itself is composed of two objects or panel components: glassPane and layeredPane. In concrete terms, they are two distinct panels displayed when needed in the same graphical space occupied by the object of the JRootPane class. By default, glassPane is not displayed. When glassPane is displayed, it is placed above layeredPane. In this book, we do not require the use of glassPane. In general, we can say that glassPane allows the addition of some special graphical effects. In our example application, it is the subcomponent layeredPane that is used in the space occupied by the object defined according to the JRootPane class. The layeredPane object is in fact a container organized in such a way that each component added within it overlaps the other components previously added. For example, in future chapters we will dynamically add a box using a simple click of the mouse on the diagram. When another box is added by clicking on

the diagram space just to the left of the first box, a part of the first box is covered by this second, new box. Since the menuBar component is not used for the moment in our example application, the contentPane component occupies, by default, all the space occupied by layeredPane. If menuBar had been used, it would be found at the top of layeredPane. The contentPane object would then occupy the rest of the available space. Please note that the contentPane panel (like all panel objects) is in fact an object defined according to the characteristics of the Container class. In order to respect and follow the rules of creation associated with the JFrame class, all graphical components that are part of layeredPane must be added to contentPane. For example, in order to be able to add the diagram panel to the frame of our application (appFrame), the following two statements are used: 60: Container cp = this.getContentPane(); 61: cp.add(diagram); On line 60, we obtain the reference to the contentPane object. On line 61, the panel diagram is finally added to the panel contentPane. In general, we should always add graphical components to contentPane instead of appFrame because an object that inherits from JFrame must contain only one child component that is automatically defined by Java according to the rules of the JRootPane class. On the other hand, we should only reference directly an object like appFrame when we wish to modify its properties such as visibility, title or size: 23: appFrame.setVisible(true); 58: this.setTitle("Empty Panel"); 59: this.setSize(400, 300); As we have already mentioned, the keyword this in lines 58 and 59 references the current object during execution. In our example, since these statements are located within the AppFrame constructor, the current object is appFrame referenced in the App class: 9: private AppFrame appFrame; // & // &

13: appFrame = new AppFrame();

Class Constants
The setBackground method in line 57 57: diagram.setBackground(Color.white); Assigns the white color to the background of the newly defined panel. In concrete terms, this assignment modifies the state of the property background from the Component class.

final and static Modifiers


With final, the concept of variable is replaced by the term constant. This definition signifies that the value assigned cannot be changed afterwards. In the definition of the attributes of a class, when the keyword final is used, we are saying that we are dealing with a constant rather than a variable. Therefore, the value given to the constant will be permanently assigned. Note that the value passed, in our example, to the method setBackground corresponds to a constant. Here is the header of the attribute white defined in the Color class: public static final Color white; With static, we have an attribute of a class and not an object attribute. The keyword static signifies that the constant white will not be a constant associated to each defined object, but rather shall be a class constant, common to all objects that will use it. In general, the reference to a constant at the class level must respect the following syntax: <Class name>.<CONSTANT NAME> According to the established standards, all the characters of a constant must be in uppercase letters. Note that the constant in our example should have been defined in uppercase letters (WHITE) in order to respect Java language standards. This transgression to the norms comes from Java developers at Sun! Every rule has an exception.

Part B:

Class Development Structure and Layout Manager

Class Specialization (1st Part)


In the preceding section, instead of defining the appFrame object of type JFrame and including it in the class App, we have chosen to define the class AppFrame that inherits from JFrame. This allows the code encapsulation of the object appFrame. The appFrame object is no longer a standard object of type JFrame but is now an object of type AppFrame with all the specific definitions contained in the AppFrame class. This specific code allows the definition of the attribute diagram and modification of the properties title and size. If we continue our analysis of the code presented, we notice in the AppFrame class of Part A of this chapter that the diagram object, of type JPanel, also contains customized code: 57: diagram.setBackground(Color.white); This statement permits to customize the object of type JPanel. In order to allow for more customization flexibility, we introduce in this section the new class Diagram: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: package mb.model; import java.awt.Color; import javax.swing.JPanel; public class Diagram extends JPanel { private JPanel box; public Diagram() { super(); box = new JPanel(); box.setBackground(Color.blue);

77: 78: 79: 80: 81: 82: } 83: 84: }

box.setSize(100, 50); box.setLocation(40, 20); this.setBackground(Color.white); this.setLayout(null); this.add(box);

Line 57, previously shown, has been moved to line 79. Note that lines 76 to 78 will also be moved in the future (Part C) in a new class, since these lines also contain customization, this time at the level of the box object.

Division of an Application into Packages


A good habit to acquire when developing software consists of grouping classes of similar nature. In our example, we group the classes that serve to create graphical user interfaces in the package mb.view. Therefore, the AppFrame class is part of this package. However, the Diagram class is rather part of the classes that serve to define the "model" or the internal structure of a particular graphical component. These classes are stored in the package mb.model. The following statements determine in which package underlying classes are located: 1: package mb; the

38: package mb.view; 64: package mb.model; Since the class AppFrame uses the diagram object defined in another package, it is therefore necessary to use the following import statement 44: import mb.model.Diagram; to access the Diagram class. Also note that the import statements on lines 45 and 48 of the preceding section have been moved into the Diagram class: // +

66: import java.awt.Color; 67: import javax.swing.JPanel;

location Property
The statement in line 78 78: box.setLocation(40, 20); uses the method setLocation in order to modify the default values associated with the property location. This property saves the coordinates of the box panel to x = 40 and y = 20 from the top left corner of its container (diagram object).

Layout Managers
The graphical components offered with Java allow the development of graphical user interfaces that can work on any platform. These components allow a developer, among other things, to use graphical user interface layout managers that are capable of properly placing graphical components (for example, buttons, menus, and text fields) within graphical containers. As we have seen, these containers can be panels or frames. Layout managers: Created principally to eliminate the different sizes of components from one platform to another. Layout managers were created because of the different sizes of graphical components between platforms. Their goal is to eliminate the need to make assumptions on the various graphical components used as well as needing to know the size of containers and components. Consequently, positioning by value is not recommended.

BorderLayout Layout Manager


The class AppFrame possesses an inheritance relationship with the class JFrame. This class was conceived to use by default the layout manager BorderLayout. Easy to use, this layout manager uses five regions where it is possible

to place graphical components. These five regions correspond to space oriented geographical regions: North, West, South, East, Center. For example, within a frame, a panel can be located in the central region and buttons in the region above (North) or below (South). The components used in a container can use other layout managers other than the one used by the container. If we push our example a little farther, it is possible that the panel occupying the center region uses another layout manager. Generally, we can say that several layout managers can be used to build a container such as the one of the object appFrame. When we analyze different statements in our application, we do not find any explicit references to the layout manager BorderLayout. When no reference is mentioned, Java determines which manager to use. When the panel diagram is inserted in the frame with the following statement 57: cp.add(diagram); Java uses the manager BorderLayout to proceed to an adequate graphical positioning. In such a situation, the center region is used. Since the other regions are not used, the space occupied by these becomes minimal. The center region therefore occupies the major part of the space available to the frame.

layout Property
It is the method setLayout that explicitly determines which layout manager a container must use. For example, we could have explicitly associated the panel contentPane to the layout manager BorderLayout in the following way: cp.setLayout(new BorderLayout()); The diagram panel uses the following method setLayout in order to explicitly determine which layout manager shall be used when graphical components will be placed inside the diagram. 80: this.setLayout(null);

The term null associated to the property layout specifies that no particular layout manager will be used. Consequently, graphical components inserted in the container diagram will need to use a relative coordinate x and y starting from the top left corner of the container. This allows you to preserve the position as well as the size of the object even if the size of the container changes. The following statement positions the new panel named box inside the panel diagram: 81: this.add(box); The following setLocation method 78: box.setLocation(40, 20); determines the position of the top left corner of the panel box (relative position x = 40 and y = 20) with respect to of the diagram panel (x = 0 and y = 0). The size of the box panel is specified in line 77: 77: box.setSize(100, 50);

Part C:

Definition of Properties

Definition and Assigning of Attributes


Line 8 of our example 8: private AppFrame appFrame = new AppFrame(); // & defines the attribute diagram and immediately associates to it the reference to the newly created object. This statement replaces the two statements of the example in Part B: 8: private AppFrame appFrame;

12: appFrame = new AppFrame (); The same remarks apply in this section to the definitions of the following attributes: 46: private Diagram diagram = new Diagram(); // & 66: private Box box = new Box(); // &

Class Specialization (2nd Part)


In Part B, we saw that the code applied to an object immediately after its construction may be contained in a separately defined class. This implies that an inheritance relationship needs to be established between this new class and a predefined Java class. According to this application class development principle, we continue our example by defining the class Box. Therefore the attribute box is no longer explicitly of the type JPanel (predefined Java class) as in the example in the previous section: 71: private JPanel box;

but rather of the type Box: 66: private Box box = new Box(); // &

The Box class serves to define the second application oriented panel in our graphical user interface. Note that in the last section the following statements 76: box.setBackground(Color.blue); 77: box.setSize(100, 50); 78: box.setLocation(40, 20); were moved, in the example presented in this section, to the constructor of the object box : 92: this.setSize(100, 50); 93: this.setColor(Color.yellow); 94: this.setLocation(40, 20); Also note that the constructor of the object box calls, on line 93, the method setColor instead of using directly the method setBackground. This modification introduces and defines an application oriented property concept.

Properties
In Chapter 3, we introduced the fundamental concept of property. Afterwards, we showed the existence of the property visible located in the Java class named Component. The declaration of the We mentioned that a property is in fact a private attribute with get attribute of a property and set methods. In the example presented in this section, we define is optional. the property color inside the class Box. Note that by analyzing the code of the class Box, we do not find the attribute named color. The method setColor calls the method setBackground 102: this.setBackground(aColor); to directly color the panel background. In this case, we do not need to define the following attribute private Color color;

because the inherited method setBackground applies directly the color received, by way of its parameter, to the background of the panel object. Even if the attribute color is not defined, we can still talk about the property color.

JavaBeans
A property = get and set methods We have just seen that a property is in reality a state of an object that is saved in an attribute of a component. In most cases this attribute is explicitly added to the component. Note that we also call components "JavaBeans". In its simplest form, a JavaBean is a class that respects the following characteristics: 1- The class is public; 2- The default (no parameters) constructor is public. Of course, the component can contain other constructors. 3- The properties make reference to auxiliary or special public methods ("is", "get" and "set") that must respect programming rules described below. Only auxiliary public methods can modify the state of a property. When an attribute of a property exists, its header contains the modifier private. Therefore the consultation or modification of the state of a property can only be performed by the use of auxiliary methods. Of course, the public modifier shall be connected to the header (signature) of these methods underlying the property.

Reading of the state The method that reads the value of the property state must follow the of a property: methods syntax below: "is" (boolean type) or get<Name of property> "get". Note that a property of type boolean uses the following syntax: is<Name of property> A standard header (signature) corresponds to each auxiliary method. The "reading" methods ("is" or "get") do not use any parameters and return an object of type identical to that of the attribute used to define the property (if the attribute is explicitly used). For example, see the header of the method getColor on line 97: 97: public Color getColor() {

Modification or As for the method that serves to modify the property state, its syntax writing of the state of is defined as follows: a property: method set<Name of property> "set". A property is composed of a private attribute as well as public methods beginning with the prefixes get (is) or set. Please note that the first letter of the name of an attribute of a property is a lowercase letter. In methods, the first character of the name of the property serving as suffix of the method name becomes uppercase. In the class Box, the method setColor is used to change the box color. This method, as well as all other "set" methods, do not return any values and consequently contain the modifier void. The header of the method setColor therefore is as follows: 101: public void setColor(Color aColor) { The class of the parameter of the method "set" is equal to the type of the property. Read only property: no method "set". A method parameter is a local variable. A local variable scope lies inside the method within it is defined. Any parameter name could have been used. The type associated to the parameter corresponds to the property type. Like the attribute that serves to save the state of a property, the methods "is", "get" and "set" are also optional. If a property is read only, it is permitted not to define the method "set". Inversely, when circumstances dictate that a property only makes sense during a write operation, the method "get" ("is") can also be undefined. However, one of the three public methods must be defined in order to have a property.

CHAPTER

Events
This chapter uses the basic graphical user interface presented in the previous chapter, in order to introduce the mouse actions on the interface. In concrete terms, the goal of this chapter is to make it possible to click, with the left mouse button, on the displayed box and change its color from yellow to red and vice-versa. Working with events such as those presented in this chapter requires control mechanisms adapted to each type of event.

New Java Programming Elements


This chapter will begin by presenting new Java programming elements. We discuss them because they are used in the example presented in this chapter, whose goal is to introduce the fundamental mechanism of event control.

Optional Use of the Keyword this


The keyword this is a reference to the current class object. However, it can be omitted, as shown in the following line: 181: return selected; In the above example, we could have used the keyword this as follows: return this.selected; In general, class attributes and methods can be accessed without using the keyword this since this reference is implicit when located within the class itself. Also note that if we use the same name for class attributes and method parameters, the presence of this inside methods becomes essential in order to distinguish the attributes from the parameters. For example, here is the class Tool that defines the attribute name with its constructor whose parameter is also name. In order to distinguish between these two, the presence of the keyword this is necessary. public class Tool { private String name = ""; public Tool(String name) { super(); this.name = name; } } Another way to name a method parameter that is used to update an attribute is to use the same name as the attribute preceded by the lowercase letter "a". The first character of the attribute is then written in uppercase. In our example, the class Tool could be defined in the following way:

public class Tool { private String name = ""; public Tool(String aName) { super(); name = aName; } }

Optional Use of the Class Name


Like the keyword this, the class name that precedes the reference to one of its attributes or constants defined using the modifier static, can be omitted. For example, in the following statement: 187: this.setBackground(SELECTION_COLOR); we could have used the class name Box as follows: this.setBackground(Box.SELECTION_COLOR); In general, attributes, constants and methods defined with the modifier static can be accessed without using the name of the defining class since this reference is implicit inside the class itself.

Sending Messages between Objects


Message or parameter Objects must send messages among themselves in order to of a method. communicate with each other. Technically, we are talking about parameters (or arguments) associated to a method. Contrary to the main method equipped with the modifier void, the following isSelected method 180: public boolean isSelected(){ 181: return selected; 182: } It is the statement return that transmits an object reference or simple type value to the caller. contains in its header (line 180) the type of the returned value, preceding the name of the method. In this example, it is the data type boolean. The boolean value returned is sent by the keyword return in line 181. The value of the boolean attribute selected is returned to an expression such as the one in line 121 below: 121: box.setSelected(!box.isSelected());

The exclamation point "!", which constitutes the first character inside the parentheses of the setSelected method, obtains the negation of the returned boolean value. For example, if the method isSelected returns the value true, it is the value false that will be passed as a parameter to the method setSelected. In line 184: 184: public void setSelected( boolean aSelected) { we see, in the parameter of the method setSelected, the declaration of the argument of type boolean aSelected. It is the passage of a value from a calling instruction, such as the one in line 121, that allows the use of a new value in the parameter aSelected. A variable is not necessarily a class attribute. Note that the parameter aSelected is a local variable, and not an attribute, since its scope of access does not pass the boundaries of the method setSelected. The definition of an attribute is rather located in the scope of the class and outside its methods.

Assignment Statement
In Part C of the previous chapter we introduced the concept of assigning objects or values to attributes during the definition of attributes. We have, among other things, shown the assignment of an object to the variable cp as follows: 53: Container cp = this.getContentPane(); In this chapter, we will show other assignment statements. For example: 152: private Color currentColor = Color.yellow; // + 153: private boolean selected = false; We can assign an object or a value to an attribute during its declaration.

// +

The first statement declares the attribute currentColor and initializes this object with the reference to the constant yellow that is part of the class Color. The second statement declares the attribute selected and initializes it with the value false. The assignment statement can also be used inside a method (for example setCurrentColor) as shown in line 170 below:

170: currentColor = aColor; Here, we assign the object aColor, received as parameter, to the attribute currentColor.

if Statement
In the "if" statement, a boolean expression is evaluated. If the result is true, a certain group of statements is executed; if the result is false, another group of statements is executed. Lines 186 to 191 show an example of the "if" statement: 186: 187: 188: 189: 190: 191: if (selected) { this.setBackground(SELECTION_COLOR); } else { this.setBackground(currentColor); }

In line 186, the value of the boolean attribute selected, in parentheses, is evaluated. If the evaluation of this simple expression corresponds to the value true, line 187 will be executed; otherwise, line 190, which is part of the else clause, will receive control of the execution. Note that the else part of the if statement is optional, as shown in the following lines of code: 169: if (aColor != SELECTION_COLOR) { 170: currentColor = aColor; 171: this.setBackground(aColor); 172: } If more than one statement exists in the "true" or "false" part, the lines of code must be grouped with braces "{}" like those shown in previous examples. For reasons of clarity and potential maintenance, it is suggested to always use the braces even if you have only one statement in the true or false part of a conditional statement.

repaint Method
The use of the method repaint such as in line 173 173: this.repaint();

is sometimes useful in order to force Java to redisplay a container. Note that the method repaint, in our example, is inherited from the Container class.

Specification versus Implementation


As we saw in Chapter 1, a class is composed of, among other things, public methods. It is these methods that allow access to the private attributes of an object. For example, the class Box presented in this chapter contains the following public methods: public Box() public public public public The specification of a class = header of the public methods of the class. Color getCurrentColor() void setCurrentColor(Color aColor) boolean isSelected() void setSelected(boolean aselected)

These method headers (signatures) are part of the "specification" of the class Box. A developer wanting to use the class Box does not need to understand the code that is part of the "implementation" or execution logic of the methods. All that he needs to know is the class specification.

The implementation For example, the internal code of the method setCurrentColor = internal code (Color aColor) located within the braces "{}" of the methods. 169: if (aColor != SELECTION_COLOR) { 170: currentColor = aColor; 171: this.setBackground(aColor); 172: } 173: this.repaint(); does not have to be known to external users.

Inheritance of Class Specification and Implementation


The following line 45: public class AppFrame extends JFrame implements WindowListener { // &

The keyword extends allows the inheritance of the class specification and implementation.

shows an inheritance relationship between the class AppFrame of our application with the predefined Java class JFrame. As we have already seen, this simple inheritance relationship is established by the keyword extends. In our example, this relationship allows the AppFrame class to inherit the specifications and implementations of its ancestor classes.

Inheritance by "Contract"
The second part of the statement on line 45 shown previously starts by the keyword implements followed by the name of one or several Java "interfaces". The management of The term Java interface must not be confused with the concept of events is done by the graphical user interfaces. Java mechanism called "interface". For example, the click of the mouse inside the box of our example application is considered to be an event, since a predetermined action, predicted by the creators of the application, is produced. In concrete terms, we can say that the developer passes an agreement or contract with Java. This agreement permits him to use the mechanisms associated with the Java interfaces. In this way, the developer must of course respect the Java demands that will be imposed on him. For example, the Java interface WindowListener used in line 45 contains the following seven specifications: public void abstract windowOpened(WindowEvent e); public void abstract windowClosing(WindowEvent e); public void abstract windowClosed(WindowEvent e); public void abstract windowIconified(WindowEvent e); public void abstract windowDeiconified (WindowEvent e); public void abstract windowActivated(WindowEvent e); public void abstract windowDeactivated(WindowEvent e);

It is the developer that must handle the implementation of abstract methods related to Java interfaces.

The contract between the developer and Java consists of including all the methods in the class that implements the Java interface. In reality, as far as the Java interfaces are concerned, these methods do not need to contain any lines of code. It is the role of the developer to write the code in function of the event needs. To respond to these needs, the developer must, of course, previously learn at exactly which moment these methods will be executed. If we consult the definition of the methods that are part of Java interfaces, we find the modifier abstract. It is this modifier that indicates that there is no implementation part in the abstract method.

All methods of the Java interface must be included in the class that implements the interface.

In our example application, it is only the method windowClosing of the class AppFrame that contains specific code allowing a reaction to an action of the mouse on the application frame (a click on on the close button X of the frame). Even if no particular action is expected during the execution of the other methods of the Java interface WindowListener, we must still include them in the class AppFrame. Otherwise, Java will signal an error during compilation.

When an event occurs, During the execution of the application and when a user clicks with Java creates an object the mouse on the close button of the frame, Java intervenes by associated to it. creating an object from the class WindowEvent. This object is sent to the method windowClosing and the method is then executed: 69: public void windowClosing(WindowEvent e) { 70: this.exit(); 71: } The method exit in the class AppFrame is then called. Its first instruction is as follows: 61: this.dispose(); The dispose method deletes the resources associated to the application frame. According to the inheritance hierarchy of our example, the method dispose comes from the class Frame. After the execution of the method dispose, instruction is finally executed: 62: System.exit(0); The class System contains several useful methods in the development of applications. This class is found in the package java.lang. The method exit of this class stops the execution of the following

the Java virtual machine (VM). The argument indicates a status code indicating the normal or abnormal functioning of the application. According to the standards, a status other than zero indicates an abnormal end. The statement in line 51 51: this.addWindowListener(this); // +

inserts the application frame object in a collection of objects susceptible to react to a click of the mouse. When an action of the mouse occurs on this object, Java looks to see if the object is part of the objects associated to the Java interface WindowListener. If we look more closely, we see that the keyword this appears in two places in the statement of line 51. The first time, this makes reference to the current object of the AppFrame class, or appFrame in the App class. In this case, this corresponds to the "source" of the event, that is to say on which object the event shall be applied. In the second case, this is the "destination" of the event. In concrete terms, the object created by Java for an event must be sent to different methods of the class that implements the Java interface. This destination of the event corresponds in our example to the current class object. In other words, the second this determines the destination object that will decide how to react to an event on the source object. The source and destination objects do not have to be necessarily the same objects.

Java Interface MouseListener


The term MouseListener used in the class Diagram 102: public class Diagram extends JPanel implements MouseListener { // & constitutes the second Java interface used in our example application. Remarks made with respect to the Java interface WindowListener also apply to MouseListener. What differentiates these two Java interfaces is the nature of the events. In the first case, WindowListener reacts to events in relation to window actions applied to the object appFrame. The example that we saw consisted of a closing action of the application using the method windowClosing.

As for the Java interface MouseListener, it reacts to a click of the mouse on the box object that is part of the diagram object. The diagram box is placed in the collection of objects of the Java interface MouseListener: 108: box.addMouseListener(this); The execution of the methods of a Java interface is performed in a precise order. // +

This association of the object box to the Java interface MouseListener indicates to Java the need to send an object of the MouseEvent type to the method mousePressed of the destination object this (Diagram), as soon as Java detects a click of the mouse on the box container. Note that in reality, a determined order intervenes in the execution of the different methods of Java interfaces. In Chapter 7, we will explain, with the help of an example, the implicit order of execution of different methods of the Java MouseListener interface.

In Summary
It is the keyword extends that allows the creation of an inheritance relationship. The specifications as well as the implementations belonging to the ancestors of the class are then inherited. In other words, data definitions are copied and methods are referenced. These references allow access, during the execution of the application, to the methods themselves. In turn, the keyword implements allows the establishment of a link with Java interfaces. An agreement is passed between the developer and Java. All the methods included in the specification of the Java interface must be implemented. Four stages must then be traversed: 4 stages of implementation of Java interfaces. 1- Include import statements in order to access the Java interfaces required as well as certain classes such as those defining the parameter type of the Java interface methods. For example :
40: 41: 98: 99: import import import import java.awt.event.WindowListener; // + java.awt.event.WindowEvent; // + java.awt.event.MouseListener; // + java.awt.event.MouseEvent; // +

2- Associate the Java interface to the class where the methods of the interface will be implemented. For example: 45: public class AppFrame extends JFrame implements WindowListener { // &

3- In order to establish a link between the source and the destination of the event, add the object (the left this) in a collection of objects susceptible of reacting to an event (by the right this) expected by the Java interface used. For example: 51: this.addWindowListener(this); // +

4- Implement the methods that are part of the specification of the Java interface. Consequently, Java automatically creates a special object to identify the event that occurred. This new object serves as a parameter to different methods of the Java interface.

Execution Trace
Here is a brief example of the principal stages of execution when someone decides to click on the yellow box in the diagram. First, we take for granted that the source of the event has been defined and that the event has been linked to the object box in the following way: 108: box.addMouseListener(this); // +

When the user decides to click on the yellow box rectangle, Java takes care of creating an object from the class MouseEvent. The object is then sent to the method mousePressed 120: public void mousePressed(MouseEvent e) { 121: box.setSelected(!box.isSelected()); 122: } and Java executes the method. Once Java has succeeded to start the method mousePressed, line 121 evaluates the result of the call to the method isSelected. The value false is returned and then transformed to true (by the negation operation represented by the character "!") before passing control to the method setSelected. In line 185,

185: selected = aSelected; the value of the boolean attribute selected passes from false to true due to the value true of the parameter aSelected. Since the attribute selected is now equal to true, the result of the expression of the statement if in line 186 186: if (selected) { will have as effect to pass control to the true part of this statement. Therefore, line 187 187: this.setBackground(SELECTION_COLOR); will change the box color to red. In effect, this color corresponds to the value of the constant SELECTION_COLOR of line 148. 148: public static final Color SELECTION_COLOR = Color.red; // +

Afterwards, a second click of the mouse on the box turned red returns it to its original color, yellow. Another click and it will turn red again and so on

CHAPTER

Menus
Menus serve to group semantically related functions, according to the application logic. This chapter presents and adds this functionality to our basic graphical user interface of the preceding chapter. The menu bar of the sample application is composed of the following three menus: File, Edit and View.

File Exit Edit Select Box Deselect Box

The File menu has only one item, Exit, which terminates the application. The Edit menu allows you to select the box with the menu item Select Box. The color of the box will become red. Deselect Box is the second item in this menu. With this option, the box assumes its original yellow color. The View menu contains the item Hide Box that allows you to hide the box. The other menu item available is View Box, which redisplays the box. A new class added in this chapter extends the application of the preceding chapter with a menu bar and menu items. The classes App and Box have not been changed. The Diagram class contains a slight modification while the AppFrame class deserves particular attention. In addition, a new class is added, AppMenu. This class will be at the heart of explanations in this chapter.

View Hide Box View Box

Relationship Menu Bar / Java Events


Java Interface ActionListener
The creation of the object appMenu, representing our menu bar, is done in line 47: 47: private AppMenu appMenu = new AppMenu(this); // + In line 100, in the header of the class AppMenu, 100: public class AppMenu extends JMenuBar implements ActionListener { a new Java interface named ActionListener is used. This interface triggers a particular action when one of the menu items is selected by a user. The relationship between the menu item selection and execution of the required Java statements must, of course, be established by the developer. His role consists of implementing an event detection mechanism for the Java interface in question. For example, the object menuFileExit below, 109: private JMenuItem menuFileExit = new JMenuItem("Exit"); Each menu item must be associated to the Java interface ActionListener. which corresponds to the menu item Exit in the File menu, is assigned a relationship with the Java interface ActionListener in the following way: 122: menuFileExit.addActionListener(this); This statement creates a reference between the menu item object and the Java interface ActionListener implemented in the AppMenu class. ActionListener: When event occurs, Java sends an event object to the actionPerformed In general, when a menu item is selected, Java verifies if an event attached to the menu item needs to be triggered. In our case, an event is triggered by the ActionListener interface. Java automatically constructs an object from the class ActionEvent and this object serves as the parameter for the actionPerformed method.

method. The first statement of the actionPerformed follows: method is as

169: String command = e.getActionCommand(); This statement calls the getActionCommand method of the object e that corresponds to the instance of the event triggered. The result of the getActionCommand method recognizes the name of the menu item as being the source of the event. This name is then stored in the command local variable.

switch Statement
The actionPerformed method uses a switch statement. Here is its general form: switch (expression) { case CONSTANT_1: statement(s) case CONSTANT_2: statement(s) . . . case CONSTANT_N: statement(s) default: statement(s) } The default clause is First, an expression is evaluated. After the evaluation, the obtained optional. result is verified to see if it corresponds to the value of one of the case clauses. If not, the default clause is evaluated. Note that the default clause is optional. The constants used in the case clauses must be numerical. The break statement terminates the execution of the switch statement. When a case clause corresponds to the result of the evaluation of the expression of the switch statement, the statements that follow this clause are executed. At the end of the execution of the last statement, the execution continues with the statements of the next case clause encountered, unless a break statement is found. Once a break clause is encountered, the execution of the switch clause terminates. In our example, the instruction switch which begins on line 170:

170: switch (this.getMenuCommand(command)) { contains the expression: this.getMenuCommand(command) The command parameter of the getMenuCommand method, as we have already seen, contains the name of the menu item. The method getMenuCommand in lines 158 to 166 158: private int getMenuCommand( String aCommand) { 159: int action = -1; 160: if (aCommand.equals("Exit")) action = EXIT; 161: else if (aCommand.equals("Select")) action = SELECT; 162: else if (aCommand.equals("Deselect")) action = DESELECT; 163: else if (aCommand.equals("Hide")) action = HIDE; 164: else if (aCommand.equals("Show")) action = SHOW; 165: return action; 166: } is called. This method returns, in line 165, an integer value corresponding to the menu item selected. For example, if the item Exit of the File menu is selected, the expression of the if statement in line 160 would return the value true and the following statement action = EXIT; would be evaluated. Since the constant EXIT contains the value 1, 102: private static final int EXIT = 1; the value returned by line 165, shown above, would be equal to 1. Since the result of the method getMenuCommand corresponds to the value of the first case statement in line 171, 171: case EXIT: the statement that follows the first case clause

172: appFrame.exit(); will then be executed. Note that the object appFrame corresponds to the application frame. In the next section, we will see how to obtain the reference to the application frame in the class AppMenu. Afterwards, the break statement in line 173 173: break; terminates the execution of the switch statement.

Linking Objects
The simple fact of being able to modify the color of the displayed box from yellow to red through the menu item "Select Box" presupposes the existence of a functional link between the different objects in question. The application must be capable of linking objects between themselves. These objects are: the application frame, the menu bar, the "Select Box" menu item, the diagram, and the box. The menu bar and the diagram are part of the application frame. The "Select Box" menu item is part of the menu bar, and the box is part of the diagram. The pursued goal consists of establishing a relationship between the object menuEditSelect and the object box. The starting point is the object menuEditSelect, since it is on this object that an event happens. The end point is the object box, since it is its color that must change from yellow to red. Given that the menu item in question is located in the class AppMenu, we automatically have access to appMenu because the appMenu object includes the object menuEditSelect. The first real link to establish concerns the relationship between the objects appMenu and appFrame. This link is established when the constructor of the class AppMenu is called: 47: private AppMenu appMenu = new AppMenu(this); Contrary to all the constructors that we have seen to date, the reference to the object at the higher level (here, it is the object

appFrame represented by the keyword this) is passed as a parameter since this frame object will be used by the menu object being built (appMenu). To correctly use the menu bar, the object appMenu must effectively know the reference to the object appFrame, since it is this object, as the application frame, that includes the diagram object, and it is this object that allows access, in the end, to the box object. The constructor AppMenu equipped with the parameter of AppFrame type is presented as follows: 145: public AppMenu(AppFrame aAppFrame) { 146: this(); 147: this.setAppFrame(aAppFrame); 148: } When the keyword this is used in a constructor, it refers to the class defining the constructor. The statement in line 146 shows an interesting particularity of the keyword this inside a constructor. In effect, when the keyword this is used inside a constructor as a method, it makes reference to the class constructor. In our example, line 146 calls the AppMenu default constructor that does not have parameters (lines 119 to 143). Execution of the method "set" in line 147 allows us to save, in the property appFrame, the reference to the object passed as parameter in the constructor AppMenu. Afterwards, the property appFrame of the class AppMenu references the same object as the one used in the class App. After having obtained the reference to the object appFrame in the AppMenu class, it will be possible to access the diagram object, since it is contained inside the object appFrame. In the same way, it will be possible to reach the object box since it itself is found to be contained inside the object diagram. Even though the objects box and diagram are found inside the object appFrame, two "get" methods must nevertheless be used to find references to these objects, since the objects are in fact properties possessing the modifier private in their definitions: 48: private Diagram diagram = new Diagram();

200: private Box box = new Box(); First, the method getDiagram, which is located inside the AppFrame class, obtains the reference to the object diagram :

62: public Diagram getDiagram() { 63: return diagram; 64: } Second, the reference to the object box comes from the method getBox located in the class Diagram: 212: public Box getBox() { 213: return this.box; 214: } Finally, it is the instruction in line 175
175: appFrame.getDiagram().getBox().setSelected(true);

that allows in the end to modify the color of the box panel. The property selected associated with the object box becomes equal to true. It is this indicator that tells us whether the object in question has just been selected (value true) or not (value false): 273: public void setSelected( boolean aSelected) { 274: selected = aSelected; 275: if (selected) { 276: this.setBackground(SELECTION_COLOR); 277: } 278: else { 279: this.setBackground(currentColor); 280: } 281: this.repaint(); 282: } The example presented in this section allowed us to present an efficient mechanism allowing to link, among themselves, different objects of an application.

Building the Menu Bar


Several instructions must be used in the construction of a menu bar. First, line 100

100: public class AppMenu extends JMenuBar implements ActionListener { shows the inheritance relationship of the class AppMenu with its superclass JMenuBar. The following attributes define the three menus of the application: Creation and designation of the menu objects. 108: private Jmenu menuFile = new JMenu("File"); 110: private Jmenu menuEdit = new JMenu("Edit"); 113: private JMenu menuView = new JMenu("View"); The parameters used with the constructor JMenu correspond to the names of different menus in the menu bar. The five attributes that follow define the items of the menus located in the menus previously defined: Creation and designation of the menu item objects. 109: private JMenuItem menuFileExit = new JMenuItem("Exit"); 111: private JMenuItem menuEditSelect = new JMenuItem("Select Box "); 112: private JMenuItem menuEditDeselect = new JMenuItem("Deselect Box "); 114: private JMenuItem menuViewHide = new JMenuItem("Hide Box"); 115: private JMenuItem menuViewShow = new JMenuItem("Show Box"); Designation of the action names of each menu item. The method setActionCommand used in each of the following menu items 121: menuFileExit.setActionCommand("Exit"); 124: menuEditSelect.setActionCommand("Select"); 126: menuEditDeselect.setActionCommand( "Deselect");

129: menuViewHide.setActionCommand("Hide"); 131: menuViewShow.setActionCommand("Show"); gives an internal action name to each menu item. It is this preliminary identification of actions that allows the method getActionCommand in line 169 168: 169: 170: 158: 159: 160: 161: 162: 163: 164: 165: 166: public void actionPerformed( ActionEvent e) { String command = e.getActionCommand(); switch (this.getMenuCommand(command)) { private int getMenuCommand( String aCommand) { int action = -1; if (aCommand.equals("Exit")) action = EXIT; else if (aCommand.equals("Select")) action = SELECT; else if (aCommand.equals("Deselect")) action = DESELECT; else if (aCommand.equals("Hide")) action = HIDE; else if (aCommand.equals("Show")) action = SHOW; return action; }

to identify which menu item an application user has just clicked on. For example, when a user decides to select the menu item "Select Box", the local variable command defined in line 169 obtains the "Select" value from the getActionCommand method. Then in line 170, the method getMenuCommand returns the SELECT constant defined in line 103 below: 103: private static final int SELECT = 2; In addition, the following statements: Relationship of objects susceptible of reacting to an event according to the Java interface ActionListener. 122: menuFileExit.addActionListener(this); 125: menuEditSelect.addActionListener(this); 127: menuEditDeselect.addActionListener(this); 130: menuViewHide.addActionListener(this);

132: menuViewShow.addActionListener(this); associate each menu item to the functionalities offered by the ActionListener Java interface. This means that at the moment where a user releases the mouse button that is positioned on one of the menu items, Java will send to the method actionPerformed an object corresponding to the event occurred. Then, the actions that correspond to the item selected will be executed. The menu item in question corresponds to the "source" object. The object corresponding to the localization of the Java interface is called the "destination" object. For example, in line 122, the source object is menuFileExit and the destination object is referenced by the keyword this (appMenu). The instructions that follow assign the menu items to the menus in which they belong: Link menu/item. 134: 135: 136: 137: 138: menuFile.add(menuFileExit); menuEdit.add(menuEditSelect); menuEdit.add(menuEditDeselect); menuView.add(menuViewHide); menuView.add(menuViewShow);

Once the menus have been defined, all that remains is to assign them to the menu bar: Link menu bar/menu. 140: this.add(menuFile); 141: this.add(menuEdit); 142: this.add(menuView); Note that the menu bar is represented by the keyword this.

Graphical Location of the Menu Bar


In Section A of Chapter 4, we showed a way in which an object like appFrame, which inherits from the class JFrame, is assigned the particular frame architecture. It is by way of the component contentPane that a bridge is established between the application frame and the container diagram.

In concrete terms, we used the object cp defined in line 56 56: Container cp = this.getContentPane(); to obtain the reference to the object contentPane. After obtaining this reference, we also showed how the panel diagram was added to the application frame: 57: cp.add(diagram); The object diagram was placed, by the layout manager BorderLayout, in the central region of the application frame. For the menu bar, the following statement 53: this.setJMenuBar("this.appMenu"); // +

assigns the attribute appMenu to the property jMenuBar of the object layeredPane. The menu bar is then added above the space occupied by the object layeredPane (see Chapter 4, Part A).

CHAPTER

Dynamic Manipulation of Objects


The first part of this chapter explains how to allow a user to dynamically place a large number of boxes inside the diagram. This new functionality adds additional friendliness to the graphical user interface presented in Chapter 5. Recall that before, only one box was displayed, giving control to the user to select and deselect the box. Here the user will have free choice to create as many boxes as she wishes. The boxes can be located anywhere in the diagram. Their size is fixed and will be the same size as the box size in Chapter 5. When a box is created, its color is yellow and when it is selected, its color becomes red. Clicking on a selected box returns its color to yellow. In order to present new concepts as simply as possible, we have chosen to temporarily set aside, in the first section of this chapter, the adjoining code of the menu bar of Chapter 6. After having explained the behavior of events coming from two different source objects (diagram and box), we will reintegrate, in the second part of this chapter, the menu bar presented in the previous chapter. Here, we must adjust several menu items so that the actions asked for can be applied not only to one box but also to all boxes in the diagram. In addition, in the third part of this chapter we will show how to dynamically move a box in the graphical interface. Dragging the mouse while keeping the mouse button pressed will allow a user to move a box to a new location in the diagram. Two scrollbars are also added to the interface. These allow the diagram work area to be enlarged in the case where the space required on the screen is insufficient. In order to completely display the box, we must use the scroll bar located at the extreme right of the diagram.

Part A:

Dynamic Creation of Objects and Their Association with Java Interfaces


In comparison with the graphical user interface presented in Chapter 5, the list of classes used in this chapter increases user friendliness. The goal of this section consists of allowing a user to dynamically add an indeterminate number of boxes. The top left corner of each box created corresponds to the position of the mouse cursor inside the diagram panel. A box is created following a click of the mouse.

MouseListener Interface
Source and Destination of Events
Since we wish that an action of the mouse triggers the creation of a box, we must of course use, as in Chapter 5, the MouseListener interface in the following way: 90: public class Diagram extends JPanel implements MouseListener { First source of events: the panel. In Chapter 5, a single object type was linked to the Java interface MouseListener. Here, we must associate two object types to the Java interface. First, we must predict the triggering of an event when a click of the mouse is performed on the panel diagram. This action will create a new box object in which its top left corner will be precisely located at the point in the diagram where the mouse was clicked. In concrete terms, it is the instruction in the following line that creates this first association: 97: this.addMouseListener(this); Second source of events: the box. When a box is created and placed in the appropriate spot on the diagram panel, the application must then be able to detect another mouse action on the box. In order to create this new function, we must beforehand establish a link between each box in the graphical interface and the Java interface MouseListener. It is line 113

113: newBox.addMouseListener(this); that allows the creation of this other source of events. In concrete terms, it is the object newBox that serves as the event source. The developer must specify the destination of event where the Java interface is used. As we saw in Chapter 5, two objects must be mentioned in order to create the association between an object and a Java interface. The implicated object (source of the event) must be indicated as well as the object (class) in which the Java interface is used (this of the Diagram class that implements MouseListener). We have called the latter object the event destination. A developer of the application must specify the location of the definition of the methods associated to the Java interface. It is the keyword this in line 113 that defines the destination of the current object that will handle a mouse event when a click of the mouse occurs on a box in the diagram. The same remark applies in line 97. In this case, the destination is represented again by this. As we have just seen, two sources of events have been defined, one on the diagram and the other on the box. They are mutually exclusive since, in our application, the background cannot come into conflict with the space used by a box. In order to specify a particular process on a source of events to the detriment of another, we must verify the nature of the objects as shown in lines 121 and 124 below: 121: if (e.getSource() == this) { Verification of the equality of two objects and verification of the 124: else if (e.getSource() instanceof Box) { belonging of one instance to one class. The method getSource that we can see in the above lines returns the reference to the event source, i.e., to the object where the mouse The method event happened. For example, if the object is a box (instance of the getSource returns the class Box), the expression of the if statement in line 124 will return source object of an the boolean value true and the two statements below will be event. executed: 125: Box clickedBox = (Box) (e.getSource()); 126: clickedBox.setSelected( !(clickedBox.isSelected())); In the assignment statement, the type of expression evaluated can be changed before In line 125, even though the object that is the source of the event is an instance of the class Box, the method getSource nevertheless returns an object of type Object (class at the top of the inheritance hierarchy). Therefore, this object must be converted before its

assigning it to an object.

reference can be assigned to the object clickedBox. In effect, even if the object receiving an event is a box, the method getSource cannot cover all possible object types, thus it does not return an object of type Box. It is up to the developer to force the conversion (called casting in Java). To finish the handling of the mose event, in line 126 of our example, the boolean value of the property selected, from the box at the origin of the event, is changed to its opposite value.

Order of Methods of the Java Interface MouseListener


Each method of the interface MouseListener predefined behaviour. mouseEntered mouseExited possesses a

Once the mouse cursor (without clicking) is placed on the diagram, the method mouseEntered comes into play. If the cursor is then positioned on a box, the method mouseExited starts because of the passage from diagram to box. Afterwards, the method mouseEntered starts the second time because of the second source of events associated to the box. When the mouse leaves the box to return, by example, to the background of the diagram, the method mouseExited is executed once again. Once a mouse action is performed, such as a click of the mouse on the diagram, the method mousePressed is triggered first. In our example, if the source of the event corresponds to the diagram as shown in line 121, 121: if (e.getSource() == this) { the method addNewBox is triggered: 122: this.addNewBox(e.getPoint()); This method defines a new box on the diagram. As we have already seen, if the mouse click had been performed on a box instead of the diagram, the method mousePressed would have launched the execution of lines 125 and 126 below: 125: Box clickedBox = (Box) (e.getSource()); 126: clickedBox.setSelected( !(clickedBox.isSelected()));

mousePressed

mouseReleased

After the method mousePressed, it is the mouseReleased that comes into function. This

method method

corresponds to the release of the mouse button. mouseClicked Finally, it is the method mouseClicked that is invoked. It is a compound event consisting of mousePressed and mouseReleased.

Definition of the Coordinates of Panels


It is by the method addNewBox, mousePressed, called within the method

122: this.addNewBox(e.getPoint()); that a new object of type Box will be created. The parameter of the method addNewBox uses the method getPoint that belongs to the external class MouseEvent. This method returns the x and y coordinates of the position of the mouse on the source object. In our example, it is the diagram panel that acts as the event source. The top left corner of the panel corresponds to the position x = 0 and y = 0. The coordinates returned by getPoint are in fact an object compatible with the property point of the class MouseEvent. Since the method addNewBox in line 122 uses the method getPoint as its parameter, the definition of the parameter from a specification point of view must be of type Point, as we can see in line 110 below: 110: private void addNewBox(Point aPoint) { In addition to the definition of the position relative to the diagram panel, what remains to be defined is the width as well as the height of the box. Since the data is fixed for all new boxes, these two values are stored in the BOX_SIZE constant: 149: public static final Dimension BOX_SIZE = new Dimension(100, 50);

Object Recognition

In the example of our application, all new objects are of type Box and are created by the following statement: 111: Box newBox = new Box(); This statement uses the same name newBox for all new boxes. Will there be a problem regarding the object recognition? getSource allows the recognition of the object triggering the event. The answer is no, since the Java language gives us a way to obtain the reference to the object triggering the event. The method getSource is used to find the reference to the current object as is shown in line 125 below: 125: Box clickedBox = (Box) (e.getSource()); The name of the object has no importance, since the object that interests us in reality is the one in association with the event occurring during the last click of the mouse. An object that receives the reference of another object becomes that object. Once the object is recognized, we assign its reference to a temporary object named clickedBox. This object is in fact a local variable (local with the respect to the addNewBox method) in which its internal value corresponds to an object reference to the clicked box. Consequently, the same variable can contain different references at different times. When another box will eventually be clicked upon, the value of clickedBox will be modified so that it can reference this other box. It is this recognition of the object that will allow the modification of the property selected during the execution of the following instruction: 126: clickedBox.setSelected( !(clickedBox.isSelected()));

Part B:

Relationship Menu Bar/ Objects


In this second part of the chapter, our objective consists of applying the functionalities of the menu bar introduced in Chapter 6 to each box in the graphical interface. Principally, it consists of replacing the following instructions 175: appFrame.getDiagram().getBox(). setSelected(true); 178: appFrame.getDiagram().getBox(). setSelected(false); 181: appFrame.getDiagram().getBox(). setVisible(false); 184: appFrame.getDiagram().getBox(). setVisible(true); by these: 165: appFrame.getDiagram().selectAllBoxes(); 168: appFrame.getDiagram().deSelectAllBoxes(); 171: appFrame.getDiagram().hideSelectedBoxes(); 174: appFrame.getDiagram().showSelectedBoxes(); For example, in Chapter 6, the Box method setSelected used in line 175 was replaced by the Diagram method selectAllBoxes: 210: public void selectAllBoxes() { 211: Component[] components = this.getComponents(); 212: Box box; 213: for (int i = 0; i < components.length; i++) { 214: if (components[i] instanceof Box) { 215: box = (Box) components[i]; 216: box.setSelected(true); 217: } 218: } 219: } The methods selectAllBoxes, deSelectAllBoxes,

hideSelectedBoxes and showSelectedBoxes contain a series of statements requiring more detailed explanations.

Arrays
In Chapter 1, we briefly introduced the array concet. It consisted of the array args serving as the parameter to the method main. Generally, we can define an array as a collection of data or object references stored in its cells. Each object is called an element of the array. Each element must be of the same type. Line 211 211: Component[] components = this.getComponents(); In the example, the array components is also a property. The numbering of the elements of an array begins with an index value of zero. defines a local variable called components.

The array belements are numbered, from the first element, using an index that starts with the number zero. The number of elements that make up an array is called the size of the array. It is at the moment when the array is defined that its size is determined. In line 211, the method getComponents has as function to access each component of the container this (diagram) and to insert the reference of each component (in sequential fashion) to the elements of the new array components. Note that in our example, boxes represent the components. During the use of the method add in line 205 205: this.add(newBox); the reference to the object newBox is then automatically added to the list of internal objects (components) that make up part of the container this(diagram). It is possible to determine the array size, as being equal to the value of the "N" boxes, where "N" is equal to the number of boxes in the container diagram. Also according to our example, the type of the array components

will be a type associated to the class Component. Technically, the array type is written as follows: 211: Component[] ... As for accessing one of the array elements, an expression must be evaluated that determines the index value. This value must correspond to a whole number. For example, the following line 214: if (components[i] instanceof Box) { accesses an element of the array components corresponding to the evaluation of the index variable i. For example, if this value is equal to 8, it will be the 9th element of the array.

for Statement
Execution Loop
In our application, when a user triggers an action starting from the click on the menu item "Select Boxes", the following instruction is launched: 165: appFrame.getDiagram().selectAllBoxes(); In order to select all boxes in the diagram, it is necessary to execute one or several statements a certain number of times. In this context, here are the statements required to select only one box: 212: Box box; 215: box = (Box) components[i]; 216: box.setSelected(true); Line 212 creates a local variable for the method selectAllBoxes named box. As we have already mentioned, a local variable is not an attribute. The variable box does not exist outside of the method selectAllBoxes and it cannot at the same time play the role of an attribute coming from the diagram object. Line 215 copies in the object box the reference to a box inserted in the array components according to the position corresponding to the value of the index variable i. The object box will become, at the

same time, the referenced object. After having obtained the reference to a particular box, all that remains is to call the method setSelected of the class Box in order to assign the value true to the property selected of the referenced object. This operation must be performed for all boxes in the interface. We must therefore create a loop using the for statement. Here is the general syntax of the for statement: for (initialization; boolean expression; counter) { loop statements; } Initialization Before beginning the execution of the statements of the for loop, it statements (1st block). is necessary to start the execution of one or several initialization statements. These statements can be, in principle, any valid Java instruction. If there is more than one, they must be separated by commas. For example: x = 5, y = 8; It is the character ";" that indicates the end of the first of the three blocks of the for statement header. Also note that the initialization statement block is executed only once. Boolean expression (2nd block). After the initialization stage, it is the true result of the boolean expression of the second block that determines if the 1loop statements1 should be executed. Like the first block, the second block also ends with a semi-colon 1;1. When the results of the evaluation of the boolean expression is equal to true, the system executes the first time the statement(s) of the for loop. Once the last statement is executed, control is then passed to the third and last block. Generally, the instructions of the third block of the for statement are used to change the value of the index variable that controls, in the second block, the exiting of the loop. Once the last of these statements has been executed, the control is given once again to the second block in order to reevaluate the expression. If the result is true, a new cycle restarts. If the result is false, the for statement is terminated and control is passed to the instruction that follows the for statement. In more concrete terms, here is an example of the for statement:

Counter expressions (3rd block)

213: for (int i = 0; i < components.length; i++) { 214: if (components[i] instanceof Box) { 215: box = (Box) components[i]; 216: box.setSelected(true); 217: } 218: } The counter expression that is part of the third block of the preceding for block uses a new form of the assignment statement.

++ and -- Operators
The operators "++" and "--" add or subtract 1 to or from the value contained in the variable associated to them. For example: i++; When the operator "++" is placed after the variable, the value of the variable is used before 1 is added to it. For example: int a = 10; int b; b = a++; After execution of the last line, the variable a is equal to 11 and b takes the value of 10. If the operator "++" had been placed before the variable a, its value would have been the same as in the above example, but b would have been equal to 11. Note that the remarks of the preceding paragraph do not represent any source of confusion in regards to our example of the header of the for loop in line 213, 213: for (int i = 0; i < components.length; i++) { since the expression i++ is not, for example, assigned to another index variable. We could have also written ++i and obtained the same result.

Scope of Variables
In the header of the first block of the for statement in line 213, we find the definition as well as the initialization of the index variable i. Since this variable is defined within the for statement, its scope or its duration will not go past the execution of the for statement. Generally, it is the braces {} that govern the scope of the variables. For example, the array in line 211 211: Component[] components = this.getComponents(); can only be used within the method selectAllBoxes.

Size of Arrays
The second block of the above for statement contains the following boolean expression: i < components.length; This expression verifies if all the boxes have been selected. When i is equal to the size of the array, the expression returns the boolean value false and the for statement is terminated. It is the public final attribute named length, which is contained in the object components, that allows us to know the size of the array. Note that because of its definition as a constant (final), the size of an array cannot be modified.

Part C:

Scroll Bars and the Dynamic Displacement of Boxes


In the third and last part of this chapter, we continue our presentation concerning the dynamic manipulation of objects in the graphical user interface. Here, we concentrate mainly on the aspect of changing the position of a box in the diagram. However, we will begin by showing how to add more workspace despite the physical constraints imposed by the user's screen.

Scroll Bar
Comparatively to the previous part, line 58 in this part, 58: cp.add(new JScrollPane(diagram)); in a way, enriches the functionality of the panel diagram before adding it to the application frame. In fact, the object diagram serves as the point of entry to the construction of a new object according to the definition of the class JScrollPane. It is this new object that is added to the panel contentPane. In addition, the method getPreferredSize is explicitly defined in the class Diagram. It replaces (overrides) the method getPreferredSize inherited from the class JComponent: 264: public Dimension getPreferredSize() { 265: return new Dimension(1600, 1600); 266: } This definition included in the class Diagram allows the explicit enforcement of the size of the diagram container. Since getPreferredSize is defined in this way, it is no longer Java that determines by default the size of the diagram panel, but rather this specialization (overriding) of the method getPreferredSize in the class Diagram. This way of proceeding assigns a size of 1600 by 1600 pixels to the object diagram located inside appFrame that itself possesses a size of 600 by 400 (line 56).

56: this.setSize(600, 400);

// &

Since the size of diagram is greater than the size of appFrame, scroll bars are added to the right and below the frame of the graphical user interface.

Dynamic Displacement of Boxes


MouseMotionListener Interface
The new Java interface MouseMotionListener used in the header of the class Diagram, 193: public class Diagram extends JPanel implements MouseListener, MouseMotionListener { // & is at the origin of the mechanism allowing the displacement, with the help of the mouse, of any box in the diagram. Of course, the objects susceptible of reacting to an event associated to the Java interface MouseMotionListener must be linked to the interface as shown in line 210 below: 210: newBox.addMouseMotionListener(this); + MouseMotionListener methods: - mouseDragged; - mouseMoved. //

When an event of this nature occurs, Java creates an object according to the definitions contained in the class MouseEvent. This object is then sent to the methods mouseDragged and mouseMoved that are part of the interface MouseMotionListener. The first thing to do when we wish to move a box consists of placing the mouse on a box and keeping it presses by holding the left mouse button down. Pressing the mouse button indicates to Java that an event was produced. Java creates an object from the definition of the class MouseEvent. It is important to mention that the two interfaces, MouseListener and MouseMotionListener, used in the Diagram class react to objects coming from the MouseEvent class. First, it is the method mousePressed of the Java interface

MouseListener that comes into play following a pressed click of the mouse. One of its instructions is as follows: 276: mousePressed = e.getPoint(); // + was

Note that the definition of the attribute mousePressed previously done in line 197: 197: private Point mousePressed = new Point(0, 0); // +

The instruction in line 276 saves the coordinates x and y located inside the box where we pressed clicked. Also note that the values of x and y are relative to the top left corner of clickedBox that corresponds to the point x = 0 and y = 0. Keeping the mouse button pressed followed by a slight displacement of the mouse allows Java to send the new object, similar to the one passed as a parameter to the mousePressed method, to the mouseDragged method of the MouseMotionListener Java interface: 286: public void mouseDragged(MouseEvent e) { 287: if (e.getSource() instanceof Box) { 288: Box box = (Box) e.getSource(); 289: // box location (x, y) and size (r) // before the box has been dragged 290: Rectangle r = box.getBounds(); 291: int x = r.x + e.getX() mousePressed.x; 292: int y = r.y + e.getY() mousePressed.y; 293: if (x < 0) x = 0; 294: if (y < 0) y = 0; 295: box.setLocation(x, y); 296: } 297: } Line 287 allows first of all to verify if the selected object corresponds to an instance of the class Box and not to an instance of, for example, the class Diagram. In line 288, we make a copy of the reference to the event source object. Note that obtaining the reference is important since it is this reference that will permit us to obtain the characteristics of the object in question before proceeding to its displacement. In line 290, we save the values of the size and the location of the box

before proceeding with its displacement in the diagram. Afterwards, lines 291 and 292 calculate the new coordinates x and y of the box. Here is an example of a situation in which a box is located at the position (130, 450) relative to the top left corner of the diagram panel. A pressed click of the mouse is performed on the box at a position of (10, 40) relative to the top left corner. A displacement of the mouse is done corresponding to 50 graphical points to the right (on the x-axis). Here is the calculation of the value of x: x = 130 + 50 10 = 170 In reality, the method mouseDragged is executed several times per second in order to give, in the end, the result associated to the variable x of our example. The calculation of e.getX() must be performed several times in order to be able to constantly redisplay the box, so that the user has the impression that it is a single displacement instead of successive displacements interspersed with as many redisplays of the box. When the mouse cursor is placed outside the diagram (left and top only) and, the values of x or y can assume negative values. If this is the case, these values are brought back to zero by way of the instructions in lines 293 and 294. Once the calculation of the new position of the box is terminated, the instruction on line 295 finally saves its new location, which in turn changes the box placement in the diagram.

MouseMoved Method
The mouseMoved method constitutes the second method that is part of the specifications of the MouseMotionListener interface. The example presented in this chapter does not contain any code associated to the mouseMoved method: 299: public void mouseMoved(MouseEvent e) {} Nevertheless, we wish to mention that this method possesses characteristics of execution that greatly resembles those of the mouseDragged method. In the case of mouseMoved, simply place the mouse cursor in the space occupied by the object so that the method is executed. Therefore, the user does not need to press the mouse button as with the mouseDragged method.

CHAPTER

Tool Bar
During the design of graphical user interfaces, it is important to make a distinction between creating objects and using them. In order to represent this with an example, we have defined a tool bar that allows you to work according to one of the two modes below: 1The "selection" mode (hand image)

2- The "add" mode (box image) In the "add" mode, that is, when a user clicks on the box image in the tool bar, he can add as many boxes as he wants anywhere in the diagram with a simple click of the mouse. In the other available mode, that is, when a user clicks on the hand image in the tool bar, he can move any box in the diagram to a destination of his choice. He can also reverse the "state" of selection of a box with a click of the mouse on the box. In addition, when the mouse is clicked on the diagram background and not on a box, all the boxes are "deselected". Of course, the two modes of the tool bar are mutually exclusive. Note that the functionalities offered by the menu bar do not take into consideration the mode in which the graphical user interface is found. Concerning the tool bar images, we had to place the icons of the tool bar in an appropriate area of the computer's external memory. Consequently, knowing that applications can be eventually moved to another machine or in another directory on the same machine, it seems important to show how to develop such systems without having to control directory paths within the programming. Rather, it is from the file that served to launch the application (or applet) that the system should dynamically establish the physical location of the other files, such as those used to display the icons of the tool bar in our example.

Specification and Creation of the Toolbar


The header of the new class AppToolBar in line 195 195: public class AppToolBar extends JToolBar implements ActionListener { implements the interface ActionListener. Interface ActionListener: Only one method actionPerformed. As we have already seen in the previous chapter, the ActionListener interface, by way of its only method actionPerformed, efficiently controls the event activity.

Definition and Relationship of the Components with the Tool Bar


In concrete fashion, we want one of the buttons available in the tool bar to trigger an event. The definition of the buttons is as follows: 203: private JButton selectButton = new JButton(this.getImageIcon(SELECT_IMAGE)); 204: private JButton boxButton = new JButton(this.getImageIcon(BOX_IMAGE)); When constructing the buttons, we would like an image to be associated to each one. These images come from special files such as, for example, "gif" files. In our example, these are placed in a subdirectory called "images" under classes/mb/config. The file name as well as the lowest level directory are defined in the constants SELECT_IMAGE and BOX_IMAGE below: 200: 201: private static final String SELECT_IMAGE = "images/selectButton.gif"; private static final String BOX_IMAGE = "images/boxButton.gif";

The following code shows the general structure adopted in the example presented in this chapter.

- magicBoxes - code - ch08 src - mb App.java - view AppFrame.java AppMenu.java AppToolBar.java - model Box.java Diagram.java - classes - mb App.class - view AppFrame.class AppMenu.class AppToolBar.class - images selectButton.gif boxButton.gif - model Box.class Diagram.class This structures shows, among other things, that the compiled files (.class) are found below the classes directory. From this directory, we find the same subdirectory structure as used by the source files (.java) starting with the src directory . On line 203 previously shown, we saw that the definition of the button selectButton called the getImageIcon method below: 237: private ImageIcon getImageIcon( String anImage) { 238: URL url = this.getClass().getResource(anImage); 239: ImageIcon imageIcon = new ImageIcon(url); 240: return imageIcon; 241: } It is this method that obtains the real reference to an image resource

that can be used by a Java development tool or as a web resource. In our example, as we have already mentioned, this resource corresponds to a "gif" file. Since the method getImageIcon in line 203 uses as parameter the local directory path contained in the constant SELECT_IMAGE, this way of proceeding forces us to place the folder "images" in the same folder (view) where the defining class of the method getImageIcon is located, that is, the class AppToolBar. With this approach, any file used by the application can be dynamically located even if the application is moved to another computer or to another physical location on the same computer. In effect, it is the directory classes that serves as the base directory of the application. The displacement of this directory has no effect on the execution of the application, regardless of whether the execution is launched from a development tool or from an Internet browser, as long as the folder "images" remains inside the mb/view folder. Two local variables are used within the method getImageIcon, url and imageIcon. First, line 238 obtains the directory path of the file "gif". The method getClass obtains the directory path up to the class used to create the object this (appToolBar). In concrete terms, it is the following directory path: /magicBoxes/code/ch08/classes/mb/view/ It is the method getResource that then allows joining the contents of the constant SELECT_IMAGE (passed as parameter to the method getImageIcon) to the directory path obtained by the method getClass. It is finally this address that serves as parameter to the constructor ImageIcon(url) in line 239 that consequently obtains the reference to the icon object. The image obtained then serves as reference during the construction of the button selectButton in line 203. It is always better to specify a relative directory path rather than an absolute reference. This dynamic search procedure of a directory path of a file shows us that it is not necessary to specify the entire directory path (absolute reference). Rather, it is recommended that you use the relative reference in order to provide applications as flexible as possible. Once the object buttons of the tool bar have been defined, all that remains to do are the following three stages: 3 stages necessary to 1- Designation of an action name for each of the buttons in the tool the assignment of the bar: buttons to the tool bar.

211: selectButton.setActionCommand("Select"); 214: boxButton.setActionCommand("Box"); This internal designation will allow, in the switch statement of the method actionPerformed, 250: public void actionPerformed(ActionEvent e) { 251: String command = e.getActionCommand(); 252: switch (this.getCommand(command)) { 253: case SELECT: 254: this.setSelectedButton(SELECT); 255: break; 256: case BOX: 257: this.setSelectedButton(BOX); 258: break; 259: } 260: } to recognize the source of the event on one of the tool bar buttons. 2- Relationship of the tool bar buttons with the Java interface ActionListener: 212: selectButton.addActionListener(this); 215: boxButton.addActionListener(this);
3- Assigning the buttons to the tool bar:

217: this.add(selectButton); 218: this.add(boxButton);

Properties
In Chapter 4, we introduced the concept of properties defined in a class. In order to understand better this fundamental concept, we wish to show in a more concrete fashion the adequate use of properties. In our example application, the property selectedButton of the class AppToolBar is defined in the following way: 206: private int selectedButton = SELECT;

221: public int getSelectedButton() { 222: return selectedButton; 223: } 224: 225: private void setSelectedButton( int aButton) { 226: selectedButton = aButton; 227: if (selectedButton == SELECT) { 228: selectButton.setSelected(true); 229: boxButton.setSelected(false); 230: } 231: else if (selectedButton == BOX) { 232: boxButton.setSelected(true); 233: selectButton.setSelected(false); 234: } 235: } The property selectedButton conserves a state relative to the current mode. Two states are possible: State 1 2 Description Mode select Mode "add"

The values of the different states available are concretely defined by the following constants: 197: public static final int SELECT = 1; 198: public static final int BOX = 2; During the definition of the tool bar, line 206 initializes the property selectedButton to the state 1. If the user wishes to add some boxes, he must first click the box image in the tool bar. This action will in a way modify the state of the property selectedButton to the value 2. In more detail, an event is triggered by the execution of the actionPerformed method below: 250: public void actionPerformed(ActionEvent e) { 251: String command = e.getActionCommand(); 252: switch (this.getCommand(command)) { 253: case SELECT: 254: this.setSelectedButton(SELECT); 255: break; 256: case BOX:

257: 258: 259: } 260: }

this.setSelectedButton(BOX); break;

The first statement of the actionPerformed method (line 251) saves, in the local variable command, the value of the actionCommand property associated to the source object of the event. Since this object corresponds to the object boxButton, it is significant to mention that its property actionCommand was first initialized to the string "Box" during the execution of the constructor of the toolbar: 214: boxButton.setActionCommand("Box"); In the second instruction of the actionPerformed method, the following switch statement 252: switch (this.getCommand(command)) { calls the getCommand method below: 243: private int getCommand(String aCommand) { 244: int action = -1; 245: if (aCommand.equals("Select")) action = SELECT; 246: else if(aCommand.equals("Box")) action = BOX; 247: return action; 248: } The getCommand method receives the string "Box". Line 247 finally returns the value of the local variable action. In our example, this variable is equal to 2 because of the assignment of the constant BOX to the action variable (line 246). Since the value returned by the method getCommand is equal to 2, it is the second case statement of the switch statement in line 252 that will be executed: 256: case BOX: 257: this.setSelectedButton(BOX); 258: break; In line 257, the value "2" is passed to the setSelectedButton method. The value of this parameter will allow the launching of the three statements below in the method setSelectedButton:

226: selectedButton = aButton; 232: boxButton.setSelected(true); 233: selectButton.setSelected(false); It is in line 226 that the current activity passes from state 1 (mode select) to state 2 (mode "add"). Lines 232 and 233 initialize the property selected associated to each button in the toolbar. Before the first click of the mouse on one of these toolbar objects, the property selected associated to each one was equal to false since no initialization in this sense had yet been effected. Note that during the application startup, the first button to the left of the toolbar is the default mode selected by Java (light blue square around the image) even though the state of its property selectedButton is equal to false. This way of proceeding implies from the part of the developer to initialize the state of the property selectedButton to the value 1. If selectedButton was equal to 2, the user could have immediately created boxes in the diagram even if the active button of the toolbar was the hand image. In general, it is the value of the property selected that indicates the current state of the tool bar (light blue square around the image). At startup, unless the value of the property selected is changed, the first object added to the tool bar gives the illusion that it is the current state. In our example, placing the true value in the property selected of the button selectButton triggers the appearance of the button as if it was selected.

Positioning of the Tool Bar


It is the layout manager BoxLayout that is used by default to position the objects inside the tool bar. The assigning of the objects selectButton and boxButton to the tool bar uses by default, in the JToolBar class, the layout manager BoxLayout. This layout manager sequentially organizes the buttons of the tool bar in a line of equally sized components. The position of the objects in the tool bar is determined starting from the top left corner of the toolbar, from left to right and from top to bottom. This task is performed object by object (or add by add). After the objects selectButton and boxButton are placed in the appToolBar object, the next step consists of placing the toolbar within the application frame, i.e., inside the contentPane object. Since contentPane uses by default manager, the statement in line 59 the BorderLayout // +

59: cp.add(appToolBar, "North");

positions the toolbar in the region "North" of contentPane. Consequently, the application frame, after the following statements, 55: this.setJMenuBar(this.appMenu); 59: cp.add(appToolBar, "North"); // + 60: cp.add(new JScrollPane(diagram), "Center"); // & contains now the menu bar and the content pane, which in turn consists of the tool bar in the north section and the diagram with two scroll bars in the center section.

Relationship between the Tool Bar and the Application Frame


Since available diagram operations must be established in function of different modes offered by the tool bar (mode "add" or select), it is clear that a relationship must first be defined between the diagram and appToolBar objects. This relationship is made possible by the following statement:

50: private Diagram diagram = new Diagram(appToolBar);

// &

It is the Diagram property appToolBar that receives this parameter in the constructor of the diagram object: 289: public Diagram(AppToolBar aAppToolBar) { 290: this(); 291: this.setAppToolBar(aAppToolBar); 292: } The setAppToolBar method is invoked in line 291. This method is written as follows: 298: public void setAppToolBar( AppToolBar aAppToolBar) { 299: appToolBar = aAppToolBar; 300: } This method assigns the tool bar object to the appToolBar property of the Diagram class. Once we have obtained this reference, we can then proceed to verification operations of the current mode such as those illustrated in the following lines: 366: if (appToolBar.getSelectedButton() == AppToolBar.BOX) { // + 369: else if (appToolBar.getSelectedButton() == AppToolBar.SELECT) { // + 374: if (appToolBar.getSelectedButton() == AppToolBar.SELECT) { // + These three operations allow us to recognize which activity a user really wants to perform. Without previously obtaining the reference to the tool bar object, it would have been impossible to verify the current mode in the Diagram class.

CHAPTER

About Window
When developing graphical user interfaces, it is often useful to include a help menu. This menu is designed principally for novice users so that they can more easily familiarize themselves with the operations offered by the application (or applet). Several items can make up this menu. In this chapter, we present the menu item About.... By clicking on this help menu item, we can see the application window named About.... This window is displayed over the principal frame of the application. Inside this window, we see an image followed by several lines of text. The OK button allows you to close the window. As long as this button is not pressed, the use of other application functions is blocked. In addition to adding the Help menu, we will add to the Edit menu the item named Delete Selected Boxes. Also, each box in the interface will have a title that can even be modified.

Maintaining the Menu Bar


Menu Item Constants
In the AppMenu class, we have modified the value of the menu item constants presented in the previous chapters. In order to include the menu items About... (Help menu) and Delete Selected Boxes (Edit menu), two additional constants ABOUT and DELETE were added and previous constants were modified with new numbers:
95: 96: 97: 98: 99: 100: 101: private private private private private private private static static static static static static static final final final final final final final int int int int int int int EXIT SELECT DESELECT DELETE HIDE SHOW ABOUT = = = = = = = 11; 21; 22; 23; 31; 32; 41; // // // // // // // & & & + & & +

AppMenu Constructor
Other than the constants, the addition of the menu items About... (Help menu) and Delete Selected Boxes (Edit" menu) requires the additional code inside the menu bar constructor: 108: private JMenuItem menuEditDelete new JMenuItem (" Delete Selected Boxes"); // 112: private JMenu menuHelp = new JMenu("Help"); // + 113: private JMenuItem menuHelpAbout new JMenuItem("About..."); // 126: menuEditDelete.setActionCommand( "Delete"); // + 127: menuEditDelete.addActionListener( this); // + 134: menuHelpAbout.setActionCommand( "About"); // + 135: menuHelpAbout.addActionListener( this); // + 140: menuEdit.addSeparator(); // + = + = +

141: menuEdit.add(menuEditDelete); 144: menuHelp.add(menuHelpAbout); 149: this.add(menuHelp); // +

// + // +

The addSeparator method in line 140 adds a horizontal line between the menu items Deselect Boxes and Delete Selected Boxes. As for the other lines of code, those were discussed in Chapter 6.

Method getCommand
To include the menu items About... and Delete Selected Boxes, two new if statements were added (lines 184 and 187) inside the method getCommand below: 179: private int getCommand(String aCommand) { 180: int action = -1; 181: if (aCommand.equals("Exit")) action = EXIT; 182: else if (aCommand.equals("Select")) action = SELECT; 183: else if (aCommand.equals("Deselect")) action = DESELECT; 184: else if (aCommand.equals("Delete")) action = DELETE; // + 185: else if (aCommand.equals("Hide")) action = HIDE; 186: else if (aCommand.equals("Show")) action = SHOW; 187: else if (aCommand.equals("About")) action = ABOUT; // + 188: return action; 189: } Note that the keywords "else if" used on a single line is equivalent to the following, where the keywords are placed on two separate lines:
if (aCommand.equals("Exit")) else if (aCommand.equals("Select")) else if (aCommand.equals("Deselect")) else if (aCommand.equals("Delete")) else if (aCommand.equals("Hide")) else action = EXIT; action = SELECT; action = DESELECT; action = DELETE; action = HIDE;

if (aCommand.equals("Show")) action = SHOW; else if (aCommand.equals("About")) action = ABOUT;

The choice of form to be used is left to developers, although we recommend "else if" statements on the same line when these are found inside several linked levels as previously shown in lines 181 to 187.

Method deleteSelectedBoxes
Two additional case clauses were inserted in the switch statement of the actionPerformed method: 204: case DELETE: 205: appFrame.getDiagram(). deleteSelectedBoxes(); 206: break; 215: case ABOUT: 216: this.displayAbout(); 217: break; The development of the deleteSelectedBoxes method, used in the case clause of line 205, essentially follows the same rules of design as those of the hideSelectedBoxes method in the Diagram class. The following lines show the method deleteSelectedBoxes, which is also located inside the Diagram class: 498: public void deleteSelectedBoxes() { 499: Component[] components = this.getComponents(); 500: Box box; 501: for (int i = 0; i < components.length; i++) { 502: if (components[i] instanceof Box) { 503: box = (Box) components[i]; 504: if (box.isSelected()) { 505: this.remove(box); 506: } 507: } 508: } 509: this.repaint(); 510: } The only difference in this method in comparison with the method

hideSelectedBoxes is in line 505, where we replaced box.setVisible(false) with this.remove(box). The method repaint is used to redisplay the graphical user interface. The remove method in line 505 deletes the reference to the object box located inside the diagram object. Since the statement in line 505 is included within the for statement, all objects previously selected will be deleted. Since object references have been removed from the diagram, we must call the repaint method (line 509) to redisplay or refresh the diagram.

Method displayAbout
The method displayAbout is presented below: 166: private void displayAbout() { 167: AppAbout about = new AppAbout(appFrame); 168: Dimension aboutSize = about.getPreferredSize(); 169: Dimension frameSize = appFrame.getSize(); 170: Point frameLocation = appFrame.getLocation(); 171: int x = ((frameSize.width aboutSize.width) / 2) + frameLocation.x; 172: int y = ((frameSize.height aboutSize.height) / 2) + frameLocation.y; 173: about.setLocation(x, y); 174: about.setModal(true); 175: about.setVisible(true); 176: } First, line 167 defines the about local variable. We will return, in a future section, to the real use of this object. The method getPreferredSize gives the preferred size of a container according to the creators of the Java language. The getPreferredSize method in line 168 obtains the preferred size of the about container. In effect, the creators of the Java language have defined the preferred dimensions for each type of container. In our example, we obtain the preferred width as well as the height of the about window. The aboutSize local variable will then serve to calculate the coordinates x and y relative to the top left corner of the principal application window. On the following line, the getSize method is used to obtain the actual width and height of the application frame.

Lines 171 and 172 calculate the position of the about window with respect to the application window. It is the instruction in line 173 that places the top left corner of the about window at the position x and y obtained by the above calculation. A window is modal when a user cannot access the other windows of the application. The setModal method in line 174 controls further operations once a window is displayed on the screen. In our example, we wish to force the user to close the window before he can do anything else. In concrete terms, by passing the parameter true to the setModal method, we restrict the use of the application functions until the user has pressed the button OK. We call this type of operation a modal window. Conversely, a window is said to be nonmodal when it can stay open at the same time as others while allowing a user to pass from one to the other. The method setVisible in line 175 gives the value true to the property visible. This change of value displays the about window on the users screen.

Developing an Application Window


As we have already mentioned, the statement in line 167 167: AppAbout about = new AppAbout(appFrame); permits to use the new class named AppAbout. The header of the AppAbout class is as follows: 234: public class AppAbout extends JDialog implements ActionListener { We can see an inheritance relationship with the class JDialog. It is this class that defines the about object as a dialog window. Before passing to details of the about window code, here are several important concepts related to the mechanism of exceptions that allow you to take charge of execution errors.

Exceptions
All programs are susceptible of having execution errors. Java has an

efficient way of dealing with such error conditions by providing optional mechanisms for localizing and processing these particular situations. One of the available mechanisms with the Java language is the concept of exceptions. An exception is an object created by Java following an uncommon situation produced during the execution of an application. Two execution flows: - the normal flow; - the execution flow of exceptions. An exception is nothing more than an object created by Java following a situation deemed uncommon. In concrete terms, an exception occurs following the execution of a statement. Contrary to certain execution errors that are impossible to detect, exceptions can be detected and manipulated. When a mechanism of detection of exceptions has not been implemented, the application terminates abnormally. A message is then produced to indicate which exception has terminated the application and where. The manipulation of exceptions is important in regards to the development of application software, because they permit the developer to divide the program according to the normal execution flow and according to the execution flow of exceptions. To illustrate the mechanism of exceptions, here is an example: 269: public AppAbout(AppFrame parent) { // different from the default constructor 270: super(parent); 271: try { 272: this.init(); 273: } 274: catch (Exception e) { 275: System.out.println(e.getMessage()); 276: } 277: this.pack(); 278: } This example makes reference to the constructor of the AppAbout class. When the execution of the constructor begins, line 270 calls the constructor of the parent class JDialog. Different constructors of the JDialog class all require as parameter the reference to the frame object in which the dialog window will be displayed. The statement try is then executed and if no exception is met in the execution of the method init, the execution of the try statement ends and control is passed to the following statement, which is the execution of the method pack on line 277. Method pack: allows Java to calculate the Note that the method pack allows Java to calculate the preferable size of a window that itself is located inside another container. The

preferable size of a container that itself is located in the interior of another container. Each catch clause of a try statement manipulates a particular type of exception that occurred during the execution of one of the statements in the try block.

calculated size is consequently smaller than the size of the first container. As for the method init, we will come back a little later on its characteristics. Also note that the catch clause in line 274 is part of the try statement. If an exception occurs during the execution of the method init called in line 272, the control of the execution flow is passed to the catch clause. Otherwise, the normal execution flow continues in line 277. The syntax of the catch clause that is an integral part of the try statement is presented below: catch (ExceptionClass localVariable)

If the exception is an instance of the class indicated in the catch clause, the statements that are part of this clause will be executed.

If the exception detected by Java is an instance of the class indicated in the catch clause, the statements that are part of this clause will be executed. In our example, a single statement is executed: 275: System.out.println(e.getMessage()); The method getMessage returns a text string that explains the cause of the exception. Note that this method is part of the class Throwable from which all exception objects are derived. After the execution of the statement in line 275, Java returns control to the normal execution flow. In concrete terms, it is the statement following the try clause. In our example, the control is returned to the pack statement in line 277. Note that several catch clauses can be part of a try statement. It is the parameter class that determines which exception we are dealing with. This procedure permits the execution of statements in function of the type of exception produced.

When an exception occurs outside of the try statement, Java has recourse to the calling method in order to verify, at a higher level, the possible existence of the try statement.

When an exception is detected from a statement belonging to the normal execution flow but in which the exception is not an integral part of a try statement, the control of the execution flow is passed to the method at the next higher level (calling method). In the event of a negative search result, this procedure is followed up to the main method. As a last resort, if no mechanism of detection of exceptions exists, the application terminates abnormally and an exception message is produced.

The following init method demonstrates this mechanism of the propagation of exceptions: 280: private void init() throws Exception { 281: this.setTitle("About..."); 282: this.setResizable(false); 283: 284: Container cp = this.getContentPane(); 285: cp.setLayout(borderLayout1); 286: cp.add(northPanel, "North"); 287: cp.add(southPanel, "South"); 288: cp.add(centerPanel, "Center"); 289: cp.add(westPanel, "West"); 290: cp.add(eastPanel, "East"); 291: 292: centerPanel.setLayout(borderLayout2); 293: centerPanel.add(imagePanel, "North"); 294: centerPanel.add(textPanel, "South"); 295: 296: imagePanel.setBackground(Color.red); 297: imagePanel.add(imageLabel); 298: 299: textPanel.setLayout(gridLayout); 300: textPanel.setBackground(Color.orange); 301: gridLayout.setRows(5); 302: gridLayout.setColumns(1); 303: label0.setText(empty); 304: label1.setText(product); 305: label2.setText(version); 306: label3.setText(date); 307: label4.setText(author); 308: textPanel.add(label0); 309: textPanel.add(label1); 310: textPanel.add(label2); 311: textPanel.add(label3); 312: textPanel.add(label4); 313: 314: southPanel.setLayout(flowLayout); 315: southPanel.add(button); 316: button.addActionListener(this); 317: } In this example, we see that no try statement is part of the internal code of the init method. When an exception occurs, control is then returned to the calling method, which is the AppAbout constructor. Note that the Java language demands a developer to explicitly declares, in the header of his methods, if he wants to propagate the treatment of exceptions to the calling context. For example, the header

of the following init method 280: private void init() throws Exception { contains the word throws that forces the calling context to either catches or throws exceptions. In our case, given that no try statement is part of the init method, Java will propagate the analysis of the exceptions to the AppAbout constructor. The adjacent code under one of the catch clauses will be executed since throws demands the use of the try catch sequence in the context of the calling method. In our example, this context is defined in lines 271 to 276. Several exception classes can be part of the verification. Here, in the init method, we have used just one because it encloses, by its higher hierarchical position, several other exception classes. In effect, we could have declared the classes located below the Exception class. Note that an exception mechanism has been added inside the method getImageIcon within the AppToolBar class of the preceding chapter. Here is this method used in this chapter: 391: private ImageIcon getImageIcon( String anImage) { 392: // {+ 393: URL url = null; 394: ImageIcon imageIcon = null; 395: try { 396: // +} 397: url = this.getClass().getResource(anImage); 398: imageIcon = new ImageIcon(url); 399: // {+ 400: } 401: catch (Exception e) { 402: System.out.println(e.getMessage() + " // no URL"); 403: } 404: // +} 405: return imageIcon; 406: } This method is also used in identical fashion inside the AppAbout class.

Details of the About Window


Line 281 below: 281: this.setTitle("About..."); Gives the title About... to the about window represented by the object this (about). The value false passed to the method setResizable in the following line 282: this.setResizable(false); prevents the user to modify the size of the window. Seven objects of the JPanel class are defined in the application window: 244: 245: 246: 247: 248: 249: 250: 251: private private private private private JPanel JPanel JPanel JPanel JPanel northPanel southPanel centerPanel westPanel eastPanel = = = = = new new new new new JPanel(); JPanel(); JPanel(); JPanel(); JPanel();

private JPanel imagePanel private JPanel textPanel

= new JPanel(); = new JPanel();

The JPanel class is nothing other than a graphical container, used often to define window regions. Line 285 285: cp.setLayout(borderLayout1); assigns the layout manager BorderLayout to the cp object. The reference to BorderLayout is produced by the previously defined object borderLayout1: 264: private BorderLayout borderLayout1 = new BorderLayout(); Once the layout manager has been defined, it is then possible to assign a panel space to each region of the window: 286: 287: 288: 289: 290: cp.add(northPanel, "North"); cp.add(southPanel, "South"); cp.add(centerPanel, "Center"); cp.add(westPanel, "West"); cp.add(eastPanel, "East");

This allows, among other things, to surround the border surface of the

window with a gray color. The button OK occupies the SOUTH region. In order to be able to insert an image and some text above the button, it is necessary to explode the zone CENTER region once more, by way of the layout manager BorderLayout: 292: centerPanel.setLayout(borderLayout2); The borderLayout2 object has been previously defined in the following way: 265: private BorderLayout borderLayout2 = new BorderLayout(); The image will consequently occupy the NORTH and the text the SOUTH region: 293: centerPanel.add(imagePanel, "North"); 294: centerPanel.add(textPanel, "South"); The background of the container used for the image is then colored red: 296: imagePanel.setBackground(Color.red); The next step now consists of incorporating the image to the container imagePanel: 297: imagePanel.add(imageLabel); This image references the object imageLabel below: 260: private JLabel imageLabel = new JLabel(imageIcon); The JLabel class allows you to define objects that serve as display zones for text or images. Consequently, the definition of the imageLabel object, container of the image, itself references the imageIcon object. It is the latter object that finally permits us to establish the relationship with the real image in the constant IMAGE_PATH: 253: private ImageIcon imageIcon = this.getImageIcon(IMAGE_PATH); 236: private static final String IMAGE_PATH = "images/aboutMagic.gif"; Layout manager The textPanel object is used to permit the display of five lines of

GridLayout.

text below the image. This container uses the layout manager GridLayout: 266: private GridLayout gridLayout = new GridLayout(); 299: textPanel.setLayout(gridLayout); The layout manager GridLayout helps to organize the contents of the textPanel object according to a grid of cells of equal size, where each cell itself is a component or container. The position of the objects inside textPanel is effected starting from the top left corner of textPanel, from left to right (column by column) and from top to bottom (line by line). This task is done object by object (or add by add). The background of the container is first colored orange and a grid of five lines by one column is prepared: 300: textPanel.setBackground(Color.orange); 301: gridLayout.setRows(5); 302: gridLayout.setColumns(1); In order to place text inside the textPanel container, five objects of type JLabel are defined beforehand: 255: 256: 257: 258: 259: private private private private private JLabel JLabel JLabel JLabel JLabel label0 label1 label2 label3 label4 = = = = = new new new new new JLabel(); JLabel(); JLabel(); JLabel(); JLabel();

As we have already mentioned, the JLabel class allows the definition of objects that serve as a display zone for text or images. In this context, we wish to display the following text strings:
238: 239: 240: 241: 242: private private private private private String String String String String empty product version date author = = = = = ""; " Magic Boxes"; " Java"; " 1997 - 2004"; " Dzenan Ridjanovic";

It is the setText method that assigns text to the five containers of type JLabel previously presented: 303: 304: 305: 306: 307: label0.setText(empty); label1.setText(product); label2.setText(version); label3.setText(date); label4.setText(author);

Once the assignment of labels is complete, all that remains to do is to add them to the textPanel container: 308: 309: 310: 311: 312: Layout manager FlowLayout. textPanel.add(label0); textPanel.add(label1); textPanel.add(label2); textPanel.add(label3); textPanel.add(label4);

Although the southPanel object occupies, inside the cp object (contentPane), the SOUTH region organized by the layout manager BorderLayout, the following statement assigns to this south region a new layout manager, FlowLayout: 314: southPanel.setLayout(flowLayout); Note that the flowLayout object references the layout manager FlowLayout in the following fashion: 267: private FlowLayout flowLayout = new FlowLayout(); With FlowLayout, the components are placed one by one (while being centered), from left to right and from bottom to top. The manager uses the preferredSize method to calculate the size of the components. It puts on one line as many components as possible; then, it changes line and continues the display. By default, the alignment is done from the center of the line. Generally, FlowLayout is principally used for the display of buttons. The button button, used in our about window example, references an object of the JButton class: 262: private JButton button = new JButton("OK"); The label OK is immediately assigned to the button. The following line adds the object button to the southPanel container that is managed, as we have seen, by the rules of FlowLayout. 315: southPanel.add(button); In order to permit a click of the mouse on the button OK to close the about window, we must use a mechanism that manages events. In concrete terms, this is done by implementing the interface ActionListener in the class AppAbout as follows: 234: public class AppAbout extends JDialog

implements ActionListener { The statement in the following line 316: button.addActionListener(this); specifies the object button as a source of events that will be treated by the methods of the ActionListener interface, which are located in the object this (about). When a click of the mouse is detected, Java creates an instance of the ActionEvent class and sends it to the actionPerformed method below: 332: public void actionPerformed(ActionEvent e) { 333: if (e.getSource() == button) { 334: this.setVisible(false); 335: this.dispose(); 336: } 337: } In the actionPerformed method, line 333 verifies if the source of the event corresponds to the button object. If yes, the following line assigns the false value to the property visible. Next, the dispose method is executed. This method disposes all resources assigned to the about window and is always in liaison with the operating system of the users computer.

Box Title
The following lines 597: public static final Color TITLE_COLOR = Color.white; // + 598: public static final String TITLE_TEXT = "Box"; // + 603: private JTextField titleText = new JTextField(TITLE_TEXT); // + 611: 612: 613: 614: titleText.setBackground(TITLE_COLOR); this.setLayout(new BorderLayout()); this.add(titleText, "North"); this.doLayout();

were added to the Box class. First, on line 611, a white background is defined in the zone of the box that will eventually be used for the title. Next, the layout manager BorderLayout is defined to determine, on the line that follows, the position of the title inside the box, which will be in the North region. A default title is contained in the object TITLE_TEXT. The doLayout method on line 614 shows the title inside the box. Once the box is defined and displayed, it will be possible to modify its title. Consequently, with a simple click of the mouse in the space occupied by the title, a cursor appears and we can modify the title easily. By a double click, we can select a box title and erase it completely.

CHAPTER

10

International Application
The development of software in function of the language of users can constitute an important constraint for software development. In the example presented in this chapter, we wish to show how to develop international versions of our application (applet). Despite the small number of natural languages used, the concepts presented here can nevertheless be easily applied to any cultural community. It is the use of Locale class in Java that determines the display language. Once this is established, we will need to develop a class per cultural community of users that we want to support. To complement the idea of developing international applications, we will also present an extra functionality: tool tips below the each item in the tool bar, a mechanism that is greatly appreciated by less experienced users.

Personalizing the Display of Graphical User Interfaces According to User Language


Developing Classes by User Type
It regularly happens that the development of graphical user interfaces created for a large number of users requires a certain specialization by user type. For example, the language of the user can require a different display of the names of menu items. This linguistic characteristic of the user presupposes at first glance the existence of conditional statements in order to be able to use the proper designation in function of the language of a targeted group. In order to overcome this constraint of country, region, or culture of a user, Java offers a selection mechanism of classes depending on the natural language. In our example, we have chosen to group all the words displayed in the graphical user interface when an application or applet will be destined to an Anglophone user. These words are contained in key=value pairs in the file StringRes_en.properties:
about=About... aboutTitle=About appTitle=Magic Boxes author=Dzenan Ridjanovic boxTip=Create a box. boxTitle=Box date=1997 - 2005 deleteSelectedBoxes=Delete Selected Boxes deselectBoxes=Deselect Boxes edit=Edit exit=Exit file=File help=Help hideSelectedBoxes=Hide Selected Boxes ok=OK empty= product=Magic Boxes selectBoxes=Select Boxes selectTip=Select a box. showSelectedBoxes=Show Selected Boxes version=Java view=View

On the other hand, in the case of a Francophone user, we will use the

file StringRes_fr.properties:
about= propos de... aboutTitle= propos de appTitle=Botes magiques author=Dzenan Ridjanovic boxTip=Crer une bote. boxTitle=Bote date=1997 - 2005 deleteSelectedBoxes=Supprimer les botes slectionnes deselectBoxes=Dslectionner les botes edit=dition exit=Sortie file=Fichier help=Aide hideSelectedBoxes=Cacher les botes slectionnes ok=OK empty= product=Botes magiques selectBoxes=Slectionner les botes selectTip=Slectionner une bote. showSelectedBoxes=Montrer les botes slectionnes version=Java view=Vue

Finally, in the case of a user from Bosnia and Herzegovina, we will use the file StringRes_ba.properties:
about=O... aboutTitle=O appTitle=Magi\u010dne kutije author=D\u017eenan Ri\u0111anovi\u0107 boxTip=Kreiraj kutiju. boxTitle=Kutija date=1997 - 2005 deleteSelectedBoxes=Izbri\u0161i izabrane kutije deselectBoxes=Anuliraj izabrane kutije edit=Edicija exit=Izlaz file=Datoteka help=Pomo\u0107 hideSelectedBoxes=Sakrij izabrane kutije ok=OK empty= product=Magi\u010dne kutije selectBoxes=Izaberi kutije selectTip=Izaberi kutiju. showSelectedBoxes=Poka\u017ei izabrane kutije version=Java view=Pogled

Special characters are defined by Unicode (\u) sequences: : : : \u0106 \u0107 \u010c

: : : : : : : My name, Denan Rianovi, Ri\u0111anovi\u0107". becomes then

\u010d \u0110 \u0111 \u0160 \u0161 \u017d \u017e "D\u017eenan

For more information, consult www.unicode.org. A default file is also created, StringRes.properties. This file is identical to StringRes_en.properties. For each file there is a corresponding class that handles the file. The StringRes class will be used when the type of user does not correspond to one of the three types available (StringRes_en, StringRes_fr, and StringRes_ba).

Identifying the User Type


In several places inside our application, we call the method getPara to obtain application parameters. For example, we have the following statement: 52: private Para para = Para.getPara(); The getPara method is consequently defined in the Para class. The specification of the natural language used is done in line 736. In this case, the new Locale object is created with the parameter "ba". Several constants are available in the class Locale for different natural languages. For example, we have the following constants: - CHINESE; - FRENCH; - GERMAN; - ITALIAN; - KOREAN; - SIMPLIFIED_CHINESE; - TRADITIONAL_CHINESE. Note that it is the locale object that is used to receive the

definition of the geographical, political or cultural region of an eventual user. Two constructors are offered to define an object of type Locale: Locale(String language) Locale(String language, String country) The first argument of the two constructors corresponds to a language code. For example, it is "fr" for a Francophone user and "en" for an Anglophone user. The second parameter corresponds to a country code.

718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767:

package mb.config; import import import import import java.util.Locale; java.util.ResourceBundle; java.util.MissingResourceException; javax.swing.ImageIcon; java.net.URL;

public class Para { private static Para para; private static Locale locale; private static ResourceBundle interStringDispenser; { try { // locale = new Locale("ba"); locale = Locale.ENGLISH; // locale = Locale.FRENCH; interStringDispenser = ResourceBundle.getBundle("mb/config.StringRes", locale); } catch (Exception e) { System.out.println(e.getMessage()); } } private Para() { super(); } public static Para getPara() { if (para == null) { para = new Para(); } return para; } public String getT(String key) { String lookFor = null; try { lookFor = interStringDispenser.getString(key); } catch (MissingResourceException e) { System.out.println(e.getMessage() + " // Missing string: " + key); lookFor = "Missing string: " + key; } return lookFor; } public ImageIcon getImageIcon(String anImage) {

768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: } 779: 780: } 781:

URL url = null; ImageIcon imageIcon = null; try { url = this.getClass().getResource(anImage); imageIcon = new ImageIcon(url); } catch (Exception e) { System.out.println(e.getMessage() + " // no URL"); } return imageIcon;

In line 738, the getBundle method, in the predefined Java class ResourceBundle, obtains the reference to the class relative to the name of the base class (StringRes) concatenated with the character _ and the value of the object locale. In our example, since it is a bosnian user, the interStringDispenser object of type ResourceBundle will obtain the reference to the StringRes_ba class that uses the StringRes_ba.properties file. The getBundle method triggers a search for the existence of the language class. If this class does not exist, the second parameter previously presented is removed from the name of the class sought and a new search is started. The same procedure applies to the first parameter and so on. Here are the different suffixes that are looked for: 1- Base class + "_" + language + "_" + country 2- Base class + "_" + language 3- Base class In our example, the search of the class should correspond to the second search level, as there is no class with a country name. If the type of user is not "en", "fr" or "ba", the class used will correspond to the base class StringRes. Note that the name of the local directory path mb/config is inserted before the name of the base class as shown in the example in line 738.

Using the Language Class of the User


After having built the name of the class underlying the language of the user specified in line 736, we can now use the getT method of the Para class to find the name of the text value that corresponds to a given key. For example, the key "file" corresponds to the menu "File" in the StringRes_en.properties file (Anglophone

user) as well as the menu "Fichier" in the StringRes_fr.properties file (Francophone user). In more concrete terms, in our example application, the following line of code 57: appTitle = para.getT("appTitle"); calls the method getT. By assuming that we are dealing with an Anglophone user, the following statement 759: lookFor = interStringDispenser.getString(key); will begin a search in the StringRes_en.properties file. The value returned to the lookFor object then corresponds to the character chain "Magic Boxes". The code in the previous chapter has been modified in order to use this new mechanism of personalization according to a natural language. For example, in the Box class we find the following lines: 659: private static String boxTitle; 660: 661: { 662: boxTitle = para.getT("boxTitle"); 663: } 674: private JTextField titleText = new JTextField(boxTitle); Line 674 corresponds to the following two lines in Chapter 9: 598: public static final String TITLE_TEXT = "Box"; 603: private JTextField titleText = new JTextField(TITLE_TEXT);

Tool Tips
In the tool bar, the tool tips mechanism has been put in place. For example, when the cursor is placed on the box image box, a tool tip appears. This functionality is added to the button boxButton in the following way: 444: boxButton.setToolTipText(boxTip);

It consists simply of defining the toolTipText property with the description contained in the boxTip object in the following way: 412: private static String boxTip; 416: boxTip = para.getT("boxTip");

Grouping Utility Files


It is the method getPara private Para para = Para.getPara(); that obtains the reference to an object defined by the Para class. Note that this object is created only once during the execution of the application. Therefore, it is only when its reference is equal to the null value that the para object is created, as the getPara method below shows: 749: public static Para getPara() { 750: if (para == null) { 751: para = new Para(); 752: } 753: return para; 754: } Since the Para class is used in almost all classes, it might be useful to group all the utility files of the application under the directory path of the Para class. As we saw in the previous chapter, several classes can call utility files such as the "gif" files. In our example, it is the classes AppAbout and AppToolBar. In order to avoid finding ourselves with "gif" files inside several packages, we have grouped those in the folder images below the folder mb/config.

Instructions
Install:
1. download Java J2SE SDK from http://java.sun.com; 2. install SDK on C:\sdk; 3. create JAVA_HOME environment variable; consult for help from http://www.windows-help.net/WindowsXP/howto-04.html; 4. use compile.bat to compile; 5. use execute.bat to execute the main method; 6. use jar.bat to produce jar file; 7. use executeJar.bat to execute the main method (jar file is required); 8. use applet.bat to execute the applet version (jar file is required); 9. use Eclipse from http://www.eclipse.org to edit the code (import a project for each spiral: File/Import... Existing Project into Workspace); 10. learn more about Java from http://www.ecs.soton.ac.uk/~dem/teaching/adultevening/introjava/. All batch (.bat) files can be found both in src and classes directories (Eclipse copies them from src to classes).

Compile:
%JAVA_HOME%\bin\javac.exe -sourcepath @in.txt -d ../classes PAUSE in.txt (the class with the main method must be declared twice): mb\App.java mb\App.java mb\view\AppAbout.java mb\view\AppFrame.java mb\view\AppMenu.java mb\view\AppToolBar.java mb\model\Box.java mb\model\Diagram.java mb\config\Para.java mb\config\StringRes.java mb\config\StringRes_ba.java mb\config\StringRes_en.java mb\config\StringRes_fr.java

Execute:

%JAVA_HOME%\bin\java.exe mb.App

Jar:
%JAVA_HOME%\bin\jar.exe cvf mb.jar mb PAUSE

Execute with jar:


%JAVA_HOME%\bin\java.exe -classpath mb.jar mb.App

Execute applet:
%JAVA_HOME%\bin\appletviewer.exe start.html

Links
Eclipse
http://www.onjava.com/pub/a/onjava/2002/12/11/eclipse.html http://www.3plus4software.de/eclipse/index_en.html

Java Compiling Services


http://www.innovation.ch/java/java_compile.html http://javaboutique.internet.com/compiler.html

Java Courses
http://www.ecs.soton.ac.uk/~dem/teaching/adultevening/introjava/ http://www.cafeaulait.org/course/

Java Download Page


http://java.sun.com/j2se/1.4.2/download.html, http://java.sun.com/j2se/1.5.0/download.html

Java Home Page


http://java.sun.com

Java Swing
http://javafaq.nu/java/free-swing-book/index.shtml http://www.cse.ucsc.edu/~mcnab/ http://www.cs.cf.ac.uk/Dave/HCI/HCI_Handout_CALLER/node6.html

Java Tutorial
http://java.sun.com/docs/books/tutorial/getStarted/index.html

Java Virtual Machine


http://javafaq.nu/java/free-introduction-java-book/c1-s3.shtml

JBuilder
http://www.borland.com/products/downloads/download_jbuilder.html#

Magic Boxes

http://drdb.fsa.ulaval.ca/mb/

Unicode
http://www.unicode.org/

Web
http://www.ansa.co.uk/ANSATech/96/Training/172101.pdf

Vous aimerez peut-être aussi