Chapter 7 Improving the User Interface Fundamentals of Java.
Chapter 9 Improving the User Interface
description
Transcript of Chapter 9 Improving the User Interface
Go
Go
Chapter 9Improving the User Interface
Section 1 - Query Controlled Programs
Section 2 - Menu Controlled Programs
Section 3 - Introduction to Try-Catch Statements
Section 4 - GUI Driven Programs
Section 5 - Printf and String.format Statements
Section 6 - Processing Numerous ActionListeners
Go
Go
Go
Go
1
Chapter 9 Objectives
• Design a query-controlled program.
• Design a menu-controlled program.
• Understand the model-view program design
• Write try-catch and throw statements for error processing
• Design a graphical user interface for an Applet program.
• Understand the model-view-controller program design
• Format output text for a GUI program using System.format
2
Section 1
Query Controlled Programs
3
9.1 A Thermometer Class// The Thermometer model class.public class Thermometer{
private double degreesCelsius;
// Java will provide a default constructor!
public double getCelsius(){
return degreesCelsius;}
public double getFahrenheit(){
return degreesCelsius * 9.0 / 5.0 + 32.0;}
public void setCelsius(double degrees){
degreesCelsius = degrees;}
public void setFahrenheit(double degrees){
degreesCelsius = (degrees - 32.0) * 5.0 / 9.0;}
} // end of class 4
This is a model class that we will be using in a number of demo programs in this chapter.
9.1 Query Controlled Programs
5
We have studied count-controlled loops (entering data inside a for
loop a prescribed number of times) and sentinel-controlled loops
(entering data until a sentinel value is entered, like -1) and also
query-controlled loops that ask the user if they want to run a loop
another time and they answer either “yes” or “no”. Here is the
sample output of a new program named ConvertWithQuery_9_1.
9.1 Repeating Sets of Inputs
• The Query Program is implemented by two classes:
– The View class ConvertWithQuery_9_1 (the driver)
– The Model class Thermometer that models a
Thermometer object.
– Did you notice that the Thermometer class has only one
instance variable, degreesCelsius.
– If the fahrenheit equivalent is needed it is returned by the
accessor method getFahrenheit().
6
9.1 ConvertWithQuery_9_1 Driver Programpublic class ConvertWithQuery_9_1{
public static void main(String [] args) {
Scanner reader = new Scanner(System.in);
Thermometer thermo = new Thermometer();
String doItAgain = “y”;
while (doItAgain.equals(“y”) || doItAgain.equals(“Y”))
{
System.out.print(“\nEnter degrees Fahrenheit: ”);
double fahr = reader.nextDouble();
thermo.setFahrenheit(fahr);
reader.nextLine(); // Consume the trailing end of line
System.out.println(“The equivalent in Celsius is ” +
thermo.getCelsius());
System.out.print(“\nDo it again (y/n)?”);
doItAgain = reader.nextLine();
}}
}7
9.1 ConvertWithQuery_9_1 Program
Let’s stop and run the program ConvertWithQuery_9_1.java
with ….
the model class Thermometer.java
and
the view class ConvertWithQuery_9_1.java
8
Thermometer
model class
ConvertWithQuery_9_1
view class
The driver class is ConvertWithQuery_9_1.java and it is also the view class. This class calls methods of the model class, Thermometer.
Section 2
Menu Controlled Programs
9
9.2 Form of Menu Controlled Programs
10
In a menu-driven program, a list of options are displayed for the user so an operation can be selected to perform.
Once the operation is complete, the program redisplays the menu so another operation can be selected.
One of the operations always available is to quit the program.
The run of a sample menu controlled program is shown on the next slide.
9.2 ConvertWithMenu_9_2 Program Output
Sample program run of the menu controlled program named ConvertWithMenu_9_2
1) Convert from Fahrenheit to Celsius2) Convert from Celsius to Fahrenheit3) QuitEnter your option: 1
Enter degrees Fahrenheit: 32The equivalent in Celsius is 0.0
1) Convert from Fahrenheit to Celsius2) Convert from Celsius to Fahrenheit3) QuitEnter your option: 2
Enter degrees Celsius: 100The equivalent in Fahrenheit is 212.0
1) Convert from Fahrenheit to Celsius2) Convert from Celsius to Fahrenheit3) QuitEnter your option:
11
9.2 ConvertWithMenu_9_2 CodemenuOption = 4; // prime the loop to startwhile (menuOption != 3){
System.out.print(menu); // Display the menu and get the user's optionmenuOption = reader.nextInt();System.out.println ();
if (menuOption == 1){
System.out.print("Enter degrees Fahrenheit: ");double farh = reader.nextDouble();thermo.setFahrenheit(fahr);System.out.println ("The equivalent in Celsius is " +
thermo.getCelsius());}else if (menuOption == 2){
System.out.print("Enter degrees Celsius: ");double celsius = reader.nextDouble();thermo.setCelsius(celsius);System.out.println ("The equivalent in Fahrenheit is " +
thermo.getFahrenheit());}else if (menuOption == 3)
System.out.println("Goodbye!"); // this selection ends the loopelse
System.out.println ("Invalid option"); // Invalid option; re-enter option} 12
9.2 ConvertWithMenu_9_2 View Program
Let’s stop and run the program ConvertWithMenu_9_2.java
with ….
the model class Thermometer.java
and
the view class ConvertWithMenu_9_2.java
13
Thermometer
model class
ConvertWithMenu_9_2
view class
The driver class is ConvertWithMenu_9_2.java and it is also the view class. This class calls methods of the model class, Thermometer.
Section 3
Try - Catch Statements
Allowing Programs to
Gracefully Continue
14
9.3 Handling Number Format Exceptions
To this point, if data input is of the wrong type, a program will
throw an exception and display an error message in the
terminal window and halt the program. (An applet program
may just do nothing in response to invalid data and you
wouldn’t know there is a problem.)
What we really want is for a program to identify invalid data and
output an error message, but then allow the program to run
without crashing it.
15
9.3 Handling Number Format Exceptions
In a console program where we are asking for numeric input and
characters other than numeric digits are entered from the
keyboard, then the program will crash unless the code is
embedded within a try-catch statement.
Methods like nextInt() and nextDouble() actually implicitly
(behind the scene) parse the data input from the keyboard
when using a Scanner object. However, if the data is not
numeric, then an exception will be thrown by the program and
it will be halted … unless the reader.nextInt() or
reader.nextDouble() is imbedded in a try-catch statement.
16
9.3 General Form of a Try-Catch Statement
Programmers write the code in the try clause (branch) that they need
in a program to call various operations. If one of the operations
fails and an exception is thrown - “it will be caught” and the catch
clause (branch) will be executed and an error message displayed.
try
{
// code here that has the possibility of throwing an exception
}
catch (Exception e)
{
// error message here that describes the exception
}17
9.3 Try-Catch Statement Example
Statements within a try branch are executed until an exception is
thrown or all statements are executed. If an exception is thrown,
execution is immediately sent to the catch branch, skipping the
remainder of any code in the try branch.try
{
System.out.print("Enter degrees Fahrenheit: ");
double fahr = reader.nextDouble();
thermo.setFahrenheit(fahr);
System.out.println("The equivalent Celsius is " + thermo.getCelsius());
}
catch (Exception e)
{
System.out.println(“Bad Number Format! You did not input a number.”);
}18
9.3 Handling Number Format Exceptions
If no statement throws an exception within the try clause, the
catch clause is skipped.
Many types of exceptions can be thrown. There is an Exception
class that is at the top of a hierarchy for all exception types.
Catching an Exception object will catch any of them. However,
it is better to be specific about the kind of exception when you
can. For example, you may want a program to output the
error message “divide by zero error” if an exception is thrown.
So it would be better to use an ArithmeticException.
19
9.3 ConvertWithQuery_9_3 Program
Let’s stop and run the program ConvertWithQuery_9_3.java and see
how a try-catch statement can provide error checking and allow a
program to “gracefully continue”. We’ll use ….
the model class Thermometer.java
and
the view class ConvertWithQuery_9_3.java
20
Thermometer
model class
ConvertWithQuery_9_3
view class
The driver class is ConvertWithQuery_9_3.java and it is also the view class. This class calls methods of the model class, Thermometer.
9.3 Original getScore method of Student ClassRemember the code for the getScore method of the Student
class. It looked like this.
public int getScore (int i)
{
if (i == 1)
return test1;
else if (i == 2)
return test2;
else
return test3;
}
Programmers build in their own kind of error messages into code like this by
writing “throw” statements in their methods . (See next slide)
21
This method trusts whoever calls this
method to pass it a correct value,
either a 1, 2, or 3, since there are only
3 tests for a Student object.
9.3 Modified getScore method of Student Class
Here is an example of how to add a Java “throw” statement to a method like getScore and change its method signature:
public int getScore (int i) throws IOException{
if ( i < 1 | | i > 3 )throw new IOException(“Test number out of range. Must be 1, 2, or
3”);if (i == 1)
return test1;else if (i == 2)
return test2;else
return test3;}
To be able to use a throw statement with IOException you must import
the following: import java.io.IOException;22
9.3 Calling getScore in a Try-Catch Statement
In some other file, (other than Student.java) we could then call the
getScore method in a try-catch statement as follows:try
{
Student s1 = new Student(“Ann”, 95, 88, 92);
System.out.print(“Which test score do you want? ”);
int whichTestScore = reader.nextInt();
int testScore = s1.getScore(whichTestScore ));
System.out.println("The test score is: ” + testScore );
}
catch (Exception e)
{
System.out.println(e);
}
23
Note: if the user enters some integer other than 1, 2, or 3, then the error message from the throw statement in the method “Test number out of range. Must be 1, 2, or 3” comes back in the parameter e and is printed by the System.out.println statement.
9.3 Throw Statement Specify Errors More Clearly
Writing throw statements in methods helps clarify the errors that occur
in a program. If a user enters a String, the error message still
makes sense and instructs the user what he or she should do.
public int getScore (int i) throws IOException{
if ( i < 1 | | i > 3 )throw new IOException(“Test number out of range. Must be 1, 2, or
3”);if (i == 1)
return test1;else if (i == 2)
return test2;else
return test3;}
24
9.3 When to Write a Throw Statement
In conclusion, if you are writing a method that has the possibility of
failing based on user input, then you can include a throw statement
in your method like the one in getScore.
However, if you don’t have access to the code of the method, then you
can write an appropriate error message in the catch clause so it is
printed instead of printing e.catch (Exception e)
{
System.out.println(“Error! Your input is out of range!”);
}
instead of
catch (Exception e)
{
System.out.println(e);
}25
Section 4
GUI Driven Programs
26
9.4 GUI programs are event-driven
• GUI programs are event-driven.
– when a program opens, it waits for events
• Events are generated when the user interacts with the GUI
by ….
• entering data in text fields
• clicking buttons
• making selections from menus or other GUI components.
• Events invoke controller classes, which in turn invoke model
classes.
27
9.4 GUI Programs
In many ways, GUI programs provide more user-friendly
interaction with a program. However, some GUI components
are more user-friendly than others. JOptionPane boxes, like
we have used previously, can be limiting and tedious to use if
a lot of input needs to be entered. A JTextField is one GUI
component that is easier to use than a JOptionPane box.
We are going to examine and use the basic components in many
GUI programs … JLabels, JTextFields, JButtons, and
JTextAreas.
We will also look at the basic ways of controlling the placement of
GUI components using border, flow, and grid layouts.
28
9.4 ConvertWithGUI_9_4 Applet Program
The User Interface components of the GUI-based temperature conversion program
Title only available for JFrame programs not Applet programs.JLabels
JTextFields
JButton - note a button can have a name or label on it that isn’t a JLabel
29
9.4 The JLabel Component
JLabels provide labeling of other GUI components, but primarily
labeling or identifying JTextFields. They may be located
anywhere near the component they are identifying, above,
below, to the left, or to the right of a component. The choice is
up to the user and is only limited by the demands of the
particular kind of layout that is being implemented. Placing
JLabels near JTextFields helps the user understand what the
JTextFields are for.
30
9.4 The JTextField Component
JTextFields allow for the input of data into a GUI program, but
also allow for output of data. After data is entered into a
JTextField, if a button is clicked or a menu item selected, then
the data can be received and processed.
All input from a JTextField must be processed first as String data.
If the string data is numeric, it can then be processed using
parsing.
A program can have any number of JTextFields and each can be
set up to receive or display different sets of data in a GUI
program.31
9.4 The JButton Component
JButtons allow for controlling events in a GUI program. As we
just mentioned on the last slide, after data is entered into a
JTextField, if a button is clicked, then the data can be received
and processed.
All JButtons in a program have “listeners” so that the events
specified by the program can take place when the buttons are
clicked. A program can have any number of JButtons with
each button designated to process one of the specific events in
the GUI program.
32
9.4 The JTextArea Component
JTextAreas also allow for the entry of data into a GUI program, but
are mostly used for the output of data.
JTextAreas are usually more appropriate for outputting data in a
GUI program than JTextFields, because they provide more area
for output to be displayed in. Many times more than just a single
number or single word needs to be displayed or you want to
display data in columns. It is possible to concatenate String and
numeric output in JTextAreas and then format it using the
String.format() method, which is similar to System.out.printf.
A program can have any number of JTextAreas each with a
designated purpose within a GUI program.33
9.4 The ConvertWithGUI_9_4 View Class
• ConvertWithGUI_9_4 is the main view class and it will …
– construct and maintain a variable to a Thermometer object.
The Thermometer class is the model class.
– construct and maintain variables for JLabels, JTextFields,
and a JButton and add these GUI components to the
window’s container.
– construct and attach a FahrenheitListener object to the
JButton.
– provide a private inner class named FahrenheitListener that
is the controller class for the program.
This program is a GUI Driven applet program.
34
9.4 The ConvertWithGUI_9_4 View Code
Initial Code of ConvertWithGUI_9_4.java
public class ConvertWithGUI_9_4 extends JApplet
{
// >>>>>>> The model <<<<<<<<
// Declare and instantiate the thermometer
Thermometer thermo = new Thermometer();
// >>>>>>> The view <<<<<<<<
// Declare and instantiate the window objects.
JLabel titleLabel = new JLabel("Temperature Converter Applet");
JLabel fahrLabel = new JLabel(" Degrees Fahrenheit");
JLabel celsiusLabel = new JLabel(" Degrees Celsius");
JTextField fahrField = new JTextField("32.0");
JTextField celsiusField = new JTextField("0.0");
JButton fahrButton = new JButton("Convert >>>");
JButton celsiusButton = new JButton("<<< Convert");
Here we construct the Thermometer object for the program and all of the GUI components. They are all global and are declared and constructed immediately after the class definition.
35
9.4 BorderLayout With Five Regions
north region
south region
east regionwest region
center region
36
Here is a representation of a BorderLayout. The largest region is the Center region, so that is where you usually place the panel with the most components. The other four regions will become larger as components are added to them. You don’t have to use any region.
We will put our GUI components in panels and then add them to the regions we want to use.
9.4 The ConvertWithGUI_9_4 View Codepublic void init (){
// declare title panel and add componentsJPanel titlePanel = new JPanel();titlePanel.add(titleLabel);
// declare data panel and add componentsJPanel dataPanel = new JPanel(new GridLayout(2, 2, 12, 6));dataPanel.add(fahrLabel);dataPanel.add(celsiusLabel);dataPanel.add(fahrField);dataPanel.add(celsiusField);
// declare button panel and add componentsJPanel buttonPanel = new JPanel();buttonPanel.add(fahrButton);
// set up container and add panelsContainer container = getContentPane();container.add(titlePanel, BorderLayout.NORTH);container.add(dataPanel, BorderLayout.CENTER);container.add(buttonPanel, BorderLayout.SOUTH);
// Attach a listener to the convert buttonfahrButton.addActionListener(new FahrenheitListener());
}
The init method for the program
creates panels for the
components and then adds them
to the panels. It also establishes
the placement of the panels in
the BorderLayout. It finally, adds
a listener to the JButton.
37
9.4 ConvertWithGUI_9_4 Applet Program
For this applet, only the north, center, and south regions of the BorderLayout are used. Each of these regions contains a panel and each of the panels contains one or more components.
38
titlePanel in NORTH
buttonPanel in SOUTH
dataPanel in CENTER
9.4 The Private Inner Listener Controller Class
When the user clicks the Convert button, the following code is executed.
// >>>>>>> The controller <<<<<<<<
private class FahrenheitListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String input = fahrField.getText(); // Obtain input
double fahr = Double.parseDouble(input); // Convert to double
thermo.setFahrenheit(fahr); // Reset thermometer
double celsius = thermo.getCelsius(); // Obtain Celsius
celsiusField.setText("" + celsius); // output result
}
} The private inner listener class must implement ActionListener
and needs only one method … the actionPerformed() method.
39
9.4 The getText() JTextField Method
40
The JTextField class has a number of important methods.
One of the most important is the getText() method that
retrieves what has been entered into a JTextField, like
fahrField, as a String. If by program design the value is
intended to be a number, then it must be parsed to the type
of number that is expected. After it is parsed it can be used
as needed in the program.
9.4 The setText() JTextField Method
41
The setText() method erases everything in a JTextField and
then places a String value back in it. If the value is a number, it
must be first converted to a String. Remember this code that
draws the number 10 with g …
g.drawString( "" + 10, 100, 100 );
To convert 10 to a String, we had to concatenate it to empty
string. The same thing is being done with the line of code:
celsiusField.setText("" + celsius);
It converts the number stored in celsius to a String before
placing the String in the JTextField.
9.4 The JTextField and JTextArea MethodsThe most important JTextField and JTextArea methods are:
JTextField or JTextArea Methods What it does
String getText( ) returns the string currently occupying the JTextField or JTextArea.
void setText(String s) displays the String s in the JTextField or JTextArea after erasing it.
void append(String s) concatenates the String s to any other information already being displayed in the JTextField or JTextArea. No erasing!
void setEditable (boolean b) the JTextField or JTextArea is read only by the user if b is false. The user can erase or edit the field if b is true. The default value if this method is not called is true so the it is editable.
void requestFocus (boolean b) makes the cursor go immediately to the JTextField or JTextArea without the user clicking the mouse in it.
42
9.4 Using The setEditable Method
Many times we may want to have a JTextField or JTextArea that
is only for displaying output and we don’t want the user to be
able to delete or edit any of the information. This is where we
can use the setEditable() method. Let’s say we have the
following JTextArea declared:
JTextArea output = new JTextArea ();
output.setEditable(false);
Programmers make JTextAreas un-editable more often than
JTextFields. Typically, JTextFields are used for input and
JTextAreas are used for output.43
9.4 Using The requestFocus Method
You can use requestFocus with either a JTextField or JTextArea,
however, since users aren’t usually typing in a JTextArea it doesn’t
make sense to request the focus for that component. We use
requestFocus when we want to save the user effort by placing the
mouse cursor in an obvious place where something needs to be
entered for input.
So, if you have a JTextField variable named fahrFld and you have
declared and instantiated it in a GUI program, then when it loads you
can make the cursor go immediately to fahrFld, without the user
clicking the mouse in the JTextField, by using the line of code:
fahrFld.requestFocus();
However, there are times when this method doesn’t seem to work. 44
9.4 JTextField ActionListeners
After entering data into a JTextField named fahrFld , if you want
the input to be processed by pressing the “enter” or “return” key
on your keyboard without clicking a GUI button, you can add an
action listener to the JTextField variable.
fahrFld.addActionListener(new FahrenheitListener());
If you have a private inner class already defined named
FahrenheitListener that you are using for a button, then you
simply add an anonymous call to the class constructor as the
parameter for the addActionListener ( ) method as seen above.
45
9.4 Model-View-Controller Pattern• The model-view/controller pattern is used by most
programmers as a way to consistently divide the responsibility
of different parts of an application between the different
classes in an organized manner.– Model: The data that the program uses and the operations that can be
performed on that data. In this program, the Thermometer class serves
as the model.
– View: What the user of the program interacts with. In this program, the
ConvertWithGUI_9_4 class contains the view and sets up the model.
– Controller: Usually a private inner listener class that coordinates
model and view classes by passing messages and data between them.
In this program the controller is the private inner listener class
FahrenheitListener.
– Driver: Since ConvertWithGUI_9_4 is an applet class it acts as a
driver. It is the file you compile to run the program. 46
9.4 Variations of Model-View-Controller
• Finally, GUI programs that are just JFrame programs are
meant to be stand-alone programs that will not appear in a
web page and may include the following files:• model classes
• a view class
• a private inner class that is a listener
• an application class or driver class that starts the program
• However, applet programs usually combine the view class
and are the driver so that many times you have only the
following files:• model classes
• a view class that is also a driver class
• a private inner class that is a listener47
9.4 Variations of Model-View-Controller
Note: it is possible for JFrame or applet programs both to have
only one file. A file that contains both of the following:
• a view class that is also a driver class that doesn’t use a model class
• a private inner class that is a listener
GUI programs like these do not use a model class and may just
contain methods that do mathematical calculations or process
data in a way such that a model class is not needed. In this
case, everything is stored in one file. This will be the case
when you work on the PI_Approximator GUI program.
48
9.4 Handling Exceptions in a GUI Program
In GUI programs, we have to actually explicitly perform the
parsing of input with lines of code that use parseInt() and
parseDouble(), since a user on the internet would not be able
to see any exception errors in a terminal window.
To allow a GUI or terminal program to continue, we can place
our lines that parse the input inside try-catch statements.
The try-catch statement allows exceptions to be caught and
handled appropriately.
49
9.4 Number Format Exceptions in a GUI
Here a try-catch statement is used to process the input from a GUI
program. Notice the input has to be parsed to make sure the input
is of type double. If it is not parsed, an exception will be thrown.try
{
String input = fahrField.getText(); // get the input from a GUI field
double fahr = Double.parseDouble(input); // parse the input to a double
… // other code
}
catch (Exception e)
{
System.out.println(“Bad Number Format!”);
}
More about this on the next slide … 50
9.4 Number Format Exceptions in a GUIAgain, all input from a GUI text field is of type string, even values like 17
or 34.5678. The methods parseInt and parseDouble convert input to an
int or double value unless a value like the string “asdf” is entered. “asdf”
cannot be parsed to an int or double, so either the method parseInt or
parseDouble would throw an exception within the try branch and the catch
clause would be immediately executed.
try
{
String input = fahrField.getText(); // get the input from a GUI field
double fahr = Double.parseDouble(input); // parse the input to a double
… // other code
}
catch (Exception e)
{
System.out.println(“Bad Number Format!”);
}51
9.4 Making ConvertWithGUI_9_4 More Robust
Code that catches number format errors and invalid input.
private class FahrenheitListener implements ActionListener{
public void actionPerformed(ActionEvent e){
try{String input = fahrField.getText(); // Obtain inputdouble fahr = Double.parseDouble(input); // Convert to doubleif (fahr >= -459.67){
thermo.setFahrenheit(fahr); // Reset thermometerdouble celsius = thermo.getCelsius(); // Obtain CelsiusString s = String.format("%,15.5f", celsius); // Format resultcelsiusField.setText(s); // Output result
}else{
JOptionPane.showMessageDialog(ConvertWithGUI_9_4.this, "Impossible! That number is below
absolute zero",Fahrenheit Converter",JOptionPane.ERROR_MESSAGE);
fahrField.setText(""); celsiusField.setText("");
}}catch(Exception ex){
JOptionPane.showMessageDialog(ConvertWithGUI_9_4.this, "Bad number format",Fahrenheit Converter",JOptionPane.ERROR_MESSAGE);
fahrField.setText(""); celsiusField.setText("");
}}
} 52
9.4 The Parsing Code Throws This Exception
Bad Number Format Exception Thrown because of input KCD123 53
9.4 Programmer Set Limit Throws Exception
Illegal Range Exception Thrown because of input -500 degrees F. For this kind of exception, code must be written that throws the exception if a Fahrenheit value below -459.69 is entered into the JTextField.
54
9.4 Layouts for GUI Programs
• The 3 most commonly used simple layouts are:
– BorderLayout
– FlowLayout
– GridLayout
• BorderLayout is the default layout for JFrame and JApplet
programs. So there is no need to set the layout of the GUI.
• To change the layout to a different one use:
Container c = getContentPane();
c.setLayout( new FlowLayout( ) ); or
c.setLayout( new GridLayout(numRows, numCols ) );55
9.4 FlowLayoutWhen a FlowLayout is used, the content pane displays the GUI
components in rows in a left to right fashion based on how wide the
GUI window is. If Java runs out of room when placing a
component, it automatically flows to the next row where it will be
displayed.
In stand-alone JFrame programs that are not applets on line, a
FlowLayout can cause the presentation of the GUI to change if the
user stretches the GUI window wider or narrower.
For applets, however, if you know how wide the GUI window needs to
be to display things the way you want, then you can set the display
size of the applet and then it won’t be able to be resized when it is
embedded in a web page. Then the components won’t move.
FlowLayout is the no-thrills presentation of GUI components. It is
used when exact placement of components may not be required.56
9.4 FlowLayout Output Examples
If the user resizes the GUI window of a FlowLayout, then it will look differently as the components are displayed in the different rows.
57
9.4 BorderLayout
Every container object (frame or panel) uses a layout manager
object to organize and lay out the graphical components
contained in it.
The default layout manager for JFrames and JApplets is an
object of the class BorderLayout.
You can arrange up to five graphical objects in a container in
the following positions:
NORTH, SOUTH, EAST, WEST, and CENTER
If we add fewer than 5 objects to a BorderLayout, the layout
manager stretches some of them to fill the unoccupied areas.58
9.4 BorderLayout With Five Regions
Here is our representation of a BorderLayout again. The largest
region is the Center region, so that is where you what to place
the panel that contains the most components. Any of the
other four regions can be used if desired or excluded.north region
south region
east regionwest region
center region
59
9.4 GridLayout with Rows & ColumnsThis code produces a frame with a grid containing 2 rows and 2 columns of colored panels.package ch02;import javax.swing.*; // To import JFrame and JPanel classesimport java.awt.*; // To import Color, Container, and GridLayout classes
public class GUIWindow4{
public static void main(String[] args) {
JFrame theGUI = new JFrame(); theGUI.setTitle("Fourth GUI Program"); theGUI.setSize(300, 200); theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = new JPanel(); panel1.setBackground(Color.white);
JPanel panel2 = new JPanel(); panel2.setBackground(Color.black);
JPanel panel3 = new JPanel(); panel3.setBackground(Color.gray);
JPanel panel4 = new JPanel(); panel4.setBackground(Color.white);
Container pane = theGUI.getContentPane(); pane.setLayout(new GridLayout(2, 2)); // (2 rows, 2 columns)
pane.add(panel1); pane.add(panel2); pane.add(panel3); pane.add(panel4); theGUI.setVisible(true);
}}
Example from Chapter 2 of a GridLayout that divides a container into rows and columns with equal size cells.
60
9.4 Alternate GridLayout Constructor
Instead of …
JPanel dataPanel = new JPanel(new GridLayout(2, 2));
You can use …
JPanel dataPanel = new JPanel(new GridLayout(2, 2, 5, 3));
This constructor call takes 4 parameters. The first two are still
the number or rows and columns and the third is the
horizontal gap between columns and the fourth parameter is
the vertical gap between rows. For more info on GridLayout:
http://java.sun.com/j2se/1.6.0/docs/api/java/awt/GridLayout.html
61
Because a program may use an overall layout for the container and then contain JPanel objects in each region of a layout, sometimes we place individual layouts inside the panels to more accurately control the overall layout of the GUI. Notice here how we place two JPanels that have GridLayouts in the CENTER and SOUTH regions of a BorderLayout. Here is an example:
JPanel dataPanel = new JPanel(new GridLayout(2, 2);
…. // add the components to this panel
JPanel buttonPanel = new JPanel(new GridLayout(1, 4);
…. // add the components to this panel
Container c = getContentPane();
c.add(dataPanel, BorderLayout.CENTER);
c.add(buttonPanel, BorderLayout.SOUTH);
9.4 Advanced Layouts
62
9.4 Making Temperature Conversion Go Both Ways
Temperature converter program that goes both ways after
modifying the ConvertWithGUI_9_4.java code. There are
now two JTextFields and two JButtons.
63
9.4 Making Temperature Conversion Go Both Ways
• Here are the changes that have to be made:
– Declare and instantiate a second button
– Add second button to button panel
– Create a listener object and attach it to the second button
– Define a second listener class that converts from Celsius to Fahrenheit
You are now going to complete the above changes to the
ConvertWithGUI_9_4.java file so the program works both
ways.
64
9.4 GUI Program JTextAreas
JTextAreas are similar to JTextFields. You can construct a
text area with 10 rows and 20 columns to display textual
information using:
JTextArea output = new JTextArea(10, 20);
65
You can force a JTextArea to display scroll bars by wrapping it
in a JScrollPane as follows:
JTextArea output = new JTextArea(10, 20);
JScrollPane myJScrollPane = new JScrollPane(output);
Now a user can scroll down a text area and view information
that is being displayed beyond the bottom of the window.
The user of the program can then scroll down or up at will to
view any of the information in the window.
9.4 GUI Program JScrollPanes
66
9.4 Setting Wheel Scrolling
You can also make JTextAreas respond to the scroll wheel
on a mouse by using the following code:
JTextArea output = new JTextArea(10, 20);
Code in the init() method:
JPanel textPanel = new JPanel();
JScrollPane myJScrollPane = new JScrollPane(output);
myJScrollPane.setWheelScrollingEnabled(true);
textPanel.add(myJScrollPane);
67
Section 5
More About Printf Statements
and
Using String.format ( )
68
9.5 Sample Unformatted and Formatted Output
69
We’ve learned that println statements don’t allow us to format data in a program easily. However, printf statements do. When we are working with GUI programs and we want to output data to a JTextArea, we can’t use printf. But Java provides a format() method of the String class that works identical to printf. Therefore, we can format a String value first and then send it to a JTextArea.
Output #1 unformatted and less readable
Washington 4000.0Adams 36000.0Jefferson 150000.0
Output #2 formatted and more readable using String.format()
NAME SALARYWashington 4,000.00Adams 36,000.00Jefferson 150,000.00
9.5 DisplayTable Demo Code
Note the %,12.2f in the last printf statement above, the use of the decimal separator flag %, (comma) to place commas every 3 decimal places in the value contained in salary. Run the DisplayTable_9_7.java demo program and view the output to see the commas in the numbers.
public class DisplayTable_9_7{
public static void main(String[] args) throws IOException{
Scanner names = new Scanner(new File("ch09/names.txt"));
Scanner salaries = new Scanner(new File("ch09/salaries.txt"));
System.out.printf("%-16s%12s%n", "NAME", "SALARY");
while (names.hasNext())
{
String name = names.nextLine();
double salary = salaries.nextDouble();
System.out.printf("%-16s %,12.2f %n", name, salary);
} }
}
70
9.5 Formatted Output with printf and format
Since the introduction of Java 5.0, printf statements and String.format
statements have been available for formatting output for left or right
justification. There are two parameters for either of these statements:
1. A format string that contains literal string information and formatting
information called format specifiers.
2. A list of variables or expressions to be formatted. There should
be one variable or expression for every format specifier in the format
string.
The general form of a printf or String.format statement is:
System.out.printf (<format string>, <expression 1>, … <expression n>);
String s = String.format (<format string>, <expression 1>, … <expression n>);
71
9.5 Use of printf Statements
Earlier this year you learned about printf statements and found that
output could be formatted for left or right justification in a console
program. Here is an example you may remember:
System.out.printf("The square of %5d is %10.3f%n", number, square);
You can see how it follows the general form of a printf statement:
System.out.printf (<format string>, <expression 1>, … <expression n>);
In the above printf statement, the first parameter is the format string
and it contains a combination of literal string information, “The
square of” and “is”, and the format specifiers for the expressions,
namely %5d, %10.3f, and %n. (number and square are the expressions)
72
9.5 Why String.format Statements
A String.format statement is appropriate if we want to format
columns in a JTextArea. When we send the string to the
JTextArea, we want it to be nicely formatted. We would only
use System.out.printf if we were going to display things in the
console window NOT in a GUI..
73
9.5 Use of String.format Statements
The parameters of a printf or String.format statement are written
following the exact same rules. Compare the general forms again:
System.out.printf (<format string>, <expression 1>, … <expression n>);
String s = String.format (<format string>, <expression 1>, … <expression n>);
System.format statements are used to format data in the same way as printf
statements, however, the formatted data is not send to output, but rather
returned as a String value that can be stored in a String variable or sent
directly to a GUI JTextField or JTextArea. Here is an example, of how it
might be used if we have a previously defined JTextArea named output:
String s = String.format("The square of %5d is %10.3f%n", number, square);
output.setText(s); // erases the entire JTextArea and then displays s
or
output.append(s); // add s to the already existing output without erasing it
74
9.5 Format Specifiers
The format string consists of one or more format specifiers.
Each format specifier …
begins with a ‘%’ character
which is followed by a number and
ends with a letter that indicates the format type.
Example format specifiers: “%5d” “%5.2f “%12s”
For integers the letter that indicates the format type is d.
For doubles the letter that indicates the format type is f.
For strings the letter that indicates the format type is s.
75
9.5 Left & Right Justification of Output
“%5d” - right justifies the int value in a field width of 5
“%7.2f - right justifies the double value in a field width of 7
“%12s” - right justifies the String value in a field width of 12
“%-5d” - left justifies the int value in a field width of 5
“%-7.2f - left justifies the double value in a field width of 7
“%-12s” - left justifies the String value in a field width of 12
76
9.5 Printf Example of formatting int values
for (int i = 1; i <= 5; i++){
System.out.print(“Enter the age: ”);int age = reader.nextInt();System.out.printf("%5d", age);
}
1 format specifier in the format string
variable to be formatted
Screen output is 5 ages all on one line.
Here the “%5d” tells us that we have a field width of 5.
77
9.5 Printf Example of formatting double values
for (int i = 1; i <= 5; i++){
System.out.print(“Enter the average: ”);double average = reader.nextDouble();System.out.printf("%5.2f", average);
}
1 format specifier in the format string
variable to be formatted
Screen output is 5 averages all on one line.
Here the “%5.2f” tells us that we have a field width of 5 with a precision of 2 decimal places.
78
9.5 Printf Example of formatting String values
for (int i = 1; i <= 5; i++){
System.out.print(“Enter the name: ”);String name = reader.nextLine();System.out.printf("%12s", name);
}
1 format specifier in the format string
variable to be formatted
Screen output is 5 names all on one line.
Here the “%12s” tells us that we have a field width of 12.
79
9.5 Printf Example of formatting All values
for (int i = 1; i <= 5; i++){
System.out.print(“Enter the name: ”);String name = reader.nextLine();System.out.print(“Enter the age: ”);int age = reader.nextInt();System.out.print(“Enter the average: ”);double average = reader.nextDouble();System.out.printf("%12s%5d%5.2f%n", name, age, average);
}
4 format specifiers in the format string
variables to be formatted
Note the %n that produces a new line
80
9.5 Non-Specific Double Format Specifiers
• Non-Specific format specifiers are always left justified instead of
right justified. So if you need them right justified, then you need
to use a field width. In this example, the field width is not given:
double dollars = 25;
double tax = dollars * 0.125;
System.out.printf(“Income: $%.2f%n ”, dollars);
System.out.printf(“Tax owed: $%.2f%n ”, tax);
%.2f allows as many spaces to the left of the decimal point as are
needed to display that portion of the double value in the variables
dollars and tax.
Or in one line of code:System.out.printf(“Income: $%.2f%nTax owed: $%.2f%n”, dollars, tax);
Note: no field width just precision
81
9.5 %n and %%
• Symbol %n embeds an new-line character in a format string.
• Symbol %% produces a literal '%' character.
• When compiler sees a format specifier, it attempts to match
that specifier to an expression following the string.
– It must match in type and position or your program or you
will get a ...
java.util.IllegalFormatConversionException
82
9.5 The Comma Format Flag
83
printf and String.format can justify text and produce tabular
output and make use of other format flags. One key format flag,
the comma, will place a comma every three places in a number.
For example, the lines of code:
int num = 20345000;
System.out.printf("%,10d", num);
String s = String.format("%,10d", num);
output.setText(s); // where output is a JTextArea
will display 20,345,000 when sent to either output.
9.5 Formatting Columns of Data• To output data in formatted columns:
– Establish the width of each field.
– Choose appropriate format flags and format specifiers to use with printf.
• The width of a field that contains a double appears before the decimal point in the format specifier f, as in “%5.2f”.
• So 5 is the overall field width. This means that the floating point value will be displayed with two decimal places and one of the five spaces will be used for the decimal point. So there will be only 2 spaces reserved for the part of the number to the left of the decimal point. If java needs more spaces to display that part of the number, then the system will use whatever spaces are needed and the output will end up left justified, instead of right justified. So be sure and pick a large enough field width.
84
Section 6
Processing Numerous
ActionListeners
85
9.6 Processing Numerous ActionListeners
Let’s say a GUI program has 5 buttons and they all need an
actionListener. There is an easier way to process button
mouse clicks than writing a private inner class for each
button.
In the PI_Approximator program, the class definition line was
public class PI_Approximator extends JApplet
We then added an actionListener to the computeButton in the
init() method and then wrote the code for a private inner class
that had an actionPerformed() method that would respond to
mouse clicks. This worked fine because we only had one
button to process the calculation of π.
86
9.6 Processing Numerous ActionListeners
In the ConvertWithGUI_9_4 program, we had two action
listeners, one for each of the two buttons, because different
things happened when we clicked each one of the buttons.
So we had to have two private inner classes with each one
having an actionPerformed method.
This approach is sufficient for having two or maybe three
buttons, because its not too hard to write private inner
classes, but what if you have 5 or 10 buttons.
Well, there is a simpler approach when you have a lot of buttons
and that is what we are going to show you.
87
9.6 Processing Calculator ActionListeners
In the Calculator sample GUI program, there are 5 JButtons in
the program that have actionListeners added in the init()
method:
addBtn.addActionListener(this);
subBtn.addActionListener(this);
multBtn.addActionListener(this);
divBtn.addActionListener(this);
clearBtn.addActionListener(this);
However, notice the class definition line of Calculator has a
different form:public class Calculator extends JApplet implements ActionListener
Notice the addition of … implements ActionListener
88
9.6 One ActionPerformed Method
When your JApplet class implements ActionListener, then you
don’t have to have any private inner classes! All you have to
do is provide one actionPerformed method and process the
different possible action events with an extended-if statement.
In each branch of the extended if statement, we can implement
code that needs to be executed for each different
actionListener (button).
So if we have 5 buttons, then we need 5 branches in our
extended if statement. (See next slide)
89
9.6 Processing Calculator ActionListeners
So, after the init() method we only need an actionPerformed() method
that has some code and an extended if like this:public void actionPerformed(ActionEvent e){
// other code with clearBtn, etc.if (e.getSource() == addBtn){
}else if (e.getSource() == subBtn){
}else if (e.getSource() == multBtn){
}else if (e.getSource() == divBtn){
}
With this approach to detecting mouse clicks, Java looks at the source of the ActionEvent e, which is the parameter of the method.
In other words, when the mouse is clicked on any one of the buttons, the method actionPerformed is immediately called and the source of the mouse click is pinpointed because it is returned by e.getSource() and then the appropriate branch of code is executed.
90
9.6 The CalculatorOneOperand Approach
You will take this approach when writing the code for the
CalculatorOneOperand program. More details on that later.
91