GSAMS’ Undistinguished Lecture Series presents... Graphical User Interfaces: Applets, Graphical...
-
Upload
leslie-ryan -
Category
Documents
-
view
239 -
download
4
Transcript of GSAMS’ Undistinguished Lecture Series presents... Graphical User Interfaces: Applets, Graphical...
GSAMS’GSAMS’UnUndistinguished distinguished
Lecture SeriesLecture Seriespresents . . .presents . . .
Graphical User Interfaces:Applets, Graphical
Applications,Events & Interfaces
Lecture Contents• GUIs and the Java AWT
– “Graphical User Interfaces” / “Abstract Windowing Toolkit”
• Components as elements of presentation and interaction
• Composition of UIs with containers of components
• Layout of components within containers• Interaction with GUIs through event-driven
programming
Graphical User Interface Graphical User Interface (GUI)(GUI)
• The name for one variety of “user interface” (UI).
• An interface in which the user interacts with objects on the screen (icons, buttons, scroll-bars, etc.) via mouse clicks or keyboard actions. (Expressed in the Seeheim model.)
• Popularized in 1980s by the Macintosh.
•Now state of the practice, and not final word in UI
•Replaced text-based “command line” and “function key” interfaces.
•Despite similarities, GUIs are typicallyplatform-specific (Windows 95/98/NT, MacOS, Xt, NeWS)
The AWTThe AWT((Abstract Windowing Toolkit)
• How Java implements a platform-independent GUI (Graphical User Interface) on different platforms.
• API to the JVM’s “virtual” user interface
• Java 1.0 & 1.1 GUIs were quite bland because of the need to be platform-independent.
• Related: Java 1.2’s “Swing” classes create fully-functional GUIs for Java
Steps to GUI ConstructionSteps to GUI ConstructionIn Java, to create a GUI, you (1):
• Specify a Container, using . . .• a Layout Manager to . . . • place Components and/or Containers of Components . . .
• on the screen as desired.
In Java, to make a GUI act as the interface for a program, you (2)
• Design human/computer dialog, using Listeners and component-generated events
I.e. UI form andappearance
I.e. UI interactionand behavior
Lecture Contents• GUIs and the Java AWT
– “Graphical User Interfaces” / “Abstract Windowing Toolkit”
• Components as elements of presentation and interaction– Classes of components & the AWT class
hierarchy– Example declaration & presentation Java
code• Composition of UIs with containers of
components• Layout of components within containers
• Most interactions in a Java GUI are with Components.
• Another generic term for Component in other GUIs (e.g. X Windows) is "widget".
• Different types of components for different types ofinteraction (e.g. buttons, etc.)
•User interactions with components create events (thus, event-driven programming)
• As a rule, components cannot have other components added to them
• Exception to rule: pop up menus may have menu items added to them.
GUI ComponentsGUI Components
Component - generic widget that you can interact with Button - a widget that you can press
Canvas - a widget that you can draw on
Checkbox - a widget that is checked or not checked
Choice - an option menu that drops down
Container - a generic class that contains Components
Panel - a container to be used inside another container; used to split an existing window
Label - a single line of read-only text
List - a list of Strings
Scrollbar - a horizontal or vertical scrollbar
TextComponent
TextArea - multi-line editable text
TextField - single-line editable text
The AWT Component The AWT Component ClassClass Hierarchy Hierarchy
CanvasCanvas: : • typically a drawing surface on which shapes, graphs, pictures, etc can be drawn.
• utilize mouse events and mouse motion events to interact with the user to accomplish the drawing tasks.
TextField:TextField:• a one-line data entry area
• theoretically infinite in length
• can generate Key events to indicate that the user has typed a key
• more typically, it generates an Action event when the user finishes the data entry and hits Return in the TextField.
Components--ExamplesComponents--Examples
ButtonButton:: • simply a clickable label-like component
• appears as a standard button on whatever graphical environment the user happens to be running at the time
• generates an Action event when clicked
Label:Label:• a one-line field of text.
• user cannot change this text directly; program changes text with setText( ) method.
• usually not used to capture events (but could)
• usually used as a one-way information source to provide a message to the user.
Components--ExamplesComponents--Examples
• Containers are special components that may contain other components with which the user interacts.
Examples of Containers: • Panels• Frames• Applets
Note: Containment is not the same as extension.
A Frame may contain buttons,but buttons are not subclasses of Frame.
GUI ContainersGUI Containers
Containers are components which can have:
• Layouts set on them • Other components or containers added to them.
The types of containers include:
1. Applet: • Generally (but not always) embedded in HTML; • Is automatically created for you as the area of the web browser or appletviewer in which the applet loads.
A class that extends Applet:• Is automatically an Applet container,• Can have a layout set on it and components/containers added to it.
ContainersContainers
2. Frame: • Represents a window on the screen. • Can have Menu bars on them for pull-down menus• Can be positioned on the screen via such methods:
public void setBounds(int x, int y, int width, int height) public void setLocation(int x, int y);
3. Panel: • Is intended as a container/component that can be added to another container's layout to produce an embedded or multi-level layout.
Clever use of panels and layouts withinthe panels can produce professional and complex interface designs.
ContainersContainers
Selecting a ContainerSelecting a ContainerCommon Top-Level Containers:
Frame -- familiar window object with scrollbars, etc.Window -- more basic window object, no scrollbars, etc.Applet -- embedded byte code inside HTML document.
Instantiation:Note: Frames and Windows not self-disposing.(GUI components use more than just memory: Only memoryis garbage-collected by the JVM. Other resources have tobe reclaimed manually by dispose() )
Frame myFrame = new Frame();myFrame.setLayout(new FlowLayout());myFrame.add(myButtonInstance); . . . /* when done */myFrame.dispose();/* (event handling to come shortly . . .) */
Special types of containers -- embedded inside HTML document, between tags:
<HTML> <APPLET code = “MyApplet.class”
WIDTH = 400 HEIGHT = 300> </APPLET> </HTML>
Applets have no main(String arg[]) method -- supplied by browser instead -- Applet lifecycle:
public void init () /* a main() ‘substitute’ */ public void start () public void paint (Graphics g) public void stop () public void destroy ()
Containers -- AppletsContainers -- Applets
Minimumparams;
otherspossible
import java.applet.Applet;import java.awt.*;class myApplet extends Applet { public void init () { //define what happens here } public void start () { //define what happens here } public void paint (Graphics g) { //define what happens here } public void stop () { //define what happens here } //...etc... }
Containers -- SubclassingContainers -- Subclassing
Generally:Applets use
inheritance whileFrames use
composition and/or inheritance
The Applet ‘Sandbox’ Model
Applet code runs in 'sandbox’ within the VM, with significant restrictions on what it can do.
This is enforced by the SecurityManager class
Work-arounds for applet security restrictions include digitally signing code, servlettes, etc.
Applications can similarly invoke SecurityManager objects
The Applet ‘Sandbox’ ModelUntrusted code cannot:
– Read files (except from host URL) – List Directories – Obtain file information (existence, size, date, etc.) – Write, Delete, Rename files or directories – Read or write from FileDescriptor objects – Listen/Accept on any privileged port <= 1024 – Call System.exit() or Runtime.ext() – Create new processes with Runtime.exec() – Start a print job, access clipboard or event queue
Get full access to System.getProperty(), but it can use getProperty() to find:
java.version, java.class.version, java.vendor,java.vendor.url, os.name, os.version os.arch, file.separator, path.separator, line.separator
Remaining weak-spot: Denial of Service Attacks
Applet Example/** * * ReadsFromURL.java -- a trivial applet demonstrating * how to read server-side data via a URL stream * * The applet also uses heavyweights, causing * slow redraws * */import java.awt.*; import java.applet.*;import java.net.*; import java.io.*;
public class ReadsFromURL extends Applet { protected URL fileURL; protected String result; protected TextArea ta; protected int off = 15;
/** * Default constructor * */public ReadsFromURL() { // default constructor for some fussy VMs}
/** * initialize the applet * * @see#readInURL() -- called to initialize data */
public void init(){ setBackground(Color.lightGray); ta = new TextArea(); ta.setFont(new Font("Courier", Font.BOLD, 12));
/* * Set server to read applet source code */try { fileURL = new URL (getCodeBase() + "/ReadsFromURL.java");} catch(MalformedURLException e){ showStatus("Error!");}/* * Layout the container */this.setLayout(null); // necessitates setBounds()add(ta);ta.setBounds(getSize().width/8, getSize().height/8, getSize().width*3/4, getSize().height*3/4);readInURL();}// init
/** * paint the applet, including borders, bevels, and * screws * */
public void paint(Graphics g) { // bevels for (int w=0; w<getSize().width; w+=12) { for (int h=0; h<getSize().height; h+=12) { g.setColor(Color.white); g.drawLine(w,h,w+1,h); g.drawLine(w+1,h,w+5,h+4); g.drawLine(w+8,h+10,w+12,h+6); g.drawLine(w+12,h+6,w+13,h+6); g.setColor(Color.darkGray); g.drawLine(w,h+2,w+5,h+7); g.drawLine(w+5,h+7,w+6,h+7); g.drawLine(w+9,h+12,w+13,h+8); }}
/* borders */ g.setColor(Color.gray); g.fillRect(0, 0, getSize().width, off); g.fillRect(0, 0, off, getSize().height); g.fillRect(getSize().width-off,0, off,getSize().height); g.fillRect(0,getSize().height-off, getSize().width, off); g.fillRect(0,0,2*off, 2*off); g.fillRect(getSize().width-2*off,0, 2*off, 2*off); g.fillRect(0, getSize().height-2*off, 2*off, 2*off); g.fillRect(getSize().width-2*off, getSize().height-2*off, 2*off, 2*off); int dX, dY; int x1=off; int x2=2*off; int x3=getSize().width-(1+2*off); int x4=getSize().width-(1+off); int y1=off; int y2=2*off; int y3=getSize().height-(1+2*off); int y4=getSize().height-(1+off);
g.setColor(Color.black);g.drawLine(x4,y2,x3,y2); g.drawLine(x3,y1,x2,y1);g.drawLine(x2,y1,x2,y2); g.drawLine(x2,y2,x1,y2);g.drawLine(x1,y2,x1,y3); g.drawLine(x2,y3,x2,y4);g.setColor(Color.white);g.drawLine(x3,y1,x3,y2); g.drawLine(x4,y2,x4,y3);g.drawLine(x4,y3,x3,y3); g.drawLine(x3,y3,x3,y4);g.drawLine(x3,y4,x2,y4); g.drawLine(x2,y3,x1,y3); //raised outer edgeg.setColor(Color.black);g.drawRect(0,0, getSize().width-1, getSize().height-1);g.setColor(Color.white);g.drawLine(0,0, getSize().width-1,0);g.drawLine(0,0,0, getSize().height-1);
//screwsfor (int x=2;x-->0;){ for (int y=2;y-->0;){ dX=(x==1)?0:x3; dY=(y==1)?0:y3; g.setColor(Color.white); g.drawArc(dX+off/2+1,dY+off/2+1, (int)1.5*off,(int)1.5*off,90,100); g.drawLine(dX+(int) (1.25*off)+2, dY+(int) (.75*off), dX+(int) (.75*off)-1, dY+(int) (1.5*off)-1); g.setColor(Color.black); g.drawOval(dX+off/2,dY+off/2, (int)1.5*off,(int)1.5*off); g.drawLine(dX+(int) (1.25*off)+1, dY+(int) (.75*off)-1, dX+(int) (.75*off)-2, dY+(int) (1.5*off)-2); } }}// paint
public void readInURL() { try { String strTemp; java.io.InputStream input = fileURL.openStream(); BufferedReader buff = new BufferedReader (new InputStreamReader(input)); while((strTemp = buff.readLine()) != null) ta.append(strTemp+"\n"); /* Be a good net neighbor and close the stream! */ buff.close(); } catch(IOException darn){ showStatus("Exception: " + darn); } }// readInURL
}// class ReadsFromURL
The problemThe problem
• How should components be laid out within a container?
• (Why is this a problem? Because platforms may differ in screen size / resolution)
AWT SolutionAWT Solution• Layout Managers are AWT classes that encapsulate policies for laying out components in a container
•Can ensure that the arrangement of objects within a window will remain proportional regardless of changes in window dimensions.
•Example of general OOD strategy of putting rules/policies in a coordinator/referee class.
•A layout manager is always associated with a container
GUI LayoutGUI Layout
• One could specify the location of a Component by specific x and y coordinates. The Component class contains the method setLocation(int width, int height):
Button myButton = new Button (“Click”);add(myButton); // adds to whatever ‘this’ container ismyButton.setLocation(25, 75);
Layout Managers -- MotivationLayout Managers -- Motivation
Click
75 pixels down
25 pixels over
NOTE: Origin 0,0 at top left
Note: Button’s x and y coordinate starts from top left
Layout Managers -- MotivationLayout Managers -- Motivation
Problems with specifying x, y coordinates for Component:Problems with specifying x, y coordinates for Component:
• Tedious for even mildly complex GUIs.
• Addition of more components requires recalculation of every component’s x, y coordinate
• If container resizes (e.g., user expands window), calculations have to be redone!
Solution:Solution:
• Position components based on a percentage of available container size. Or create an algorithm to place components . . .
But Java already does this for you . . .
• Java provides several layout managers.
• We will concentrate here on two of them:• BorderLayout• GridLayout
• To tell a container which layout manager to use, invoke the method: setLayout( );
and specify a type of layout.
For example:
To specify a BorderLayout:
setLayout (new BorderLayout());
Layout Managers -- AWT BasedLayout Managers -- AWT Based
LayoutManagers:LayoutManagers: Two General Flavors Two General Flavors
• One can conceptually divide layout managers into two types:– Those that attach constraints to their components.– Those that do not.
• What does this mean?
If a manager attaches constraints to a component, then information
about a component’s location (e.g., compass points) is generated with the object.
LayoutManagers: LayoutManagers: ConstraintsConstraints
• BorderLayout specifies constraints corresponding to compass
regions of a container:
NORTH
SOUTH
CENTER EASTWEST
LayoutManagers: LayoutManagers: ConstraintsConstraints
• BorderLayout then appends constraint information on all components, e.g.:
this.setLayout (new BorderLayout());
Button e = new Button (“East”);
Button w = new Button (“West”);
Button n = new Button (“North”);
add(e, “East”); // deprecated
add(“West”, w); // works; deprecated
//add(n, BorderLayout.NORTH); // better
LayoutManagers: LayoutManagers: ConstraintsConstraints
LayoutManagers: Another LayoutManagers: Another ExampleExample
import java.awt.*;import java.applet.*;public class test extends Applet { String Compass[] = {"North", "South", "East",
"West", "Center"}; public void init() { /* ALWAYS call super init! */ super.init(); /* set layout */ setLayout(new BorderLayout()); for (int i = (Compass.length) - 1; i >= 0; i- -){ Button temp = new Button (Compass[i]); add (temp, Compass[i]); } // for loop} // test
LayoutManager: ExampleLayoutManager: Example
Giving:
LayoutManager: LayoutManager: No ConstraintsNo Constraints
• The second type of LayoutManager does not specify constraints for the objects it holds.
• Examples:– GridLayout()– FlowLayout()
• Without constraints, you cannot accurately predict layout behavior across platforms
LayoutManager: No ConstraintsLayoutManager: No Constraints
import java.awt.*;
import java.applet.*;
public class test extends Applet {
public void init() {
super.init();
String Labels[] = {"Short", "Short", "Long Label", "Really Long Label", "Really, really long"};
setLayout(new FlowLayout());
for (int i = (Labels.length - 1); i >= 0; i- -){
Button temp = new Button (Labels[i]);
add (temp);
} // for
} //init
} //class test
LayoutManager: No LayoutManager: No ConstraintsConstraints
Giving:
LayoutManager: No LayoutManager: No ConstraintsConstraints
And also:
LayoutManager: No Constraints
• Note:– Since pixels, fonts and insets vary with each platform,
layout without constraints will vary greatly.• Lesson:
– Use layout managers without constraints only when you have one or few components
LayoutManager: No LayoutManager: No ConstraintsConstraints
• Don’t think that layout managers without constraints are not useful!
• One of the most useful constraint-free layout manager is “GridLayout”.
public GridLayout();
public GridLayout(int rows, int cols);
public GridLayout(int rows, int cols,
int hgap, int vgap);
GridLayout specifies a grid pattern via:
setLayout (new GridLayout (rows, columns));
For example:
setLayout (new GridLayout(2,3));
generates:
GridLayoutGridLayout
• To add components (or containers) to a GridLayout, particular locations are not specified (unlike BorderLayout).
• Instead, the components (or containers) are positioned by the sequence in which they are added, as indicated by numerals below.
1 2 3
4 5 6
GridLayoutGridLayout
setLayout (new GridLayout (rows, columns, hspace, vspace));
where hspace specifies horizontal size, and vspace specifies vertical size, e.g.,
setLayout (new GridLayout (2, 2, 7, 5));
Optionally, two additional parameters may be used with GridLayout to specify the horizontal and vertical spacing (in pixels) between grid elements:
GridLayoutGridLayout
GridLayout: ExampleGridLayout: Exampleimport java.awt.*;import java.applet.*;
public class test extends Applet {public void init() {
super.init();setLayout(new GridLayout(4,3,5,5));int off[]={-2,2,0};for (int i=9; i >= 1; i--)
// this is “clever” but hard to grok // thus, is ill-advised:
add (new Button (""+(i+off[i%3])));add (new Button ("."));add (new Button ("0"));add (new Button ("+/-"));add (new MyPanel(null));
}// init}//test
GridLayout: ExampleGridLayout: Example
Giving:
A Layout ExampleA Layout Example
Label One
Label Two
Label 3
Label Four Button Two Button Three
TextArea1 is here {no label displayed}
Button One
Imagine that we wish to create an Applet with the following interface layout . . .
(dotted lines do not really appear; shown for reference)
Because this is an Applet, the entire layout is defined in the init( ) method of the Applet.
Doing this implies three activities:
• Sketching the layout on paper.
• Declaring instance variables of the visible components.
• Arranging the components as appropriate using a combination of nested containers.
A Layout ExampleA Layout Example
Step One:Step One: Sketching the layout on paper
As shown on earlier slide.
Step Two:Step Two: Declaring instance variables of the visible components:
TextArea TextArea1 = new TextArea( ); Label Label1 = new Label ("Label One"); Label Label2 = new Label ("Label Two"); Label Label3 = new Label ("Label 3"); Label Label4 = new Label ("Label Four"); Button Button1 = new Button ("Button One"); Button Button2 = new Button ("Button Two"); Button Button3 = new Button ("Button 3");
A Layout ExampleA Layout Example
Step Three: Step Three: Arranging the components using nested containers:
• Consider the overall design in terms of one or more Layout Managers (for this example, GridLayout is sufficient).
• The Applet itself is a container. Begin there, and create appropriate subdivisions of screen space:
• For this design, the main container is split into 4 quadrants, each of equal size.
• This suggests a grid layout on the Applet, with 2 rows and 2 columns, i.e.,
setLayout (new GridLayout (2,2));
A Layout ExampleA Layout Example
A Layout ExampleA Layout Example
The first quadrant of the GridLayout:• Contains a Text Area component.• To allocate the instance variable TextArea1 to the first quadrant, simply add it first:
add (TextArea1);
Label One
Label Two
Label 3
Label Four
Button Two Button Three
TextArea1 is here {no label displayed}
Button One
The second quadrant of the GridLayout:• Contains two Labels. • Since we can have only one container or component per area, we subdivide the quadrant into two areas.• To do so, we declare a new Panel, then divide it as two areas, one for each Label:
// create new panelPanel Panel1 = new Panel();
// add it to GridLayout // at next positionadd (Panel1);
// subdivide Panel1 // as 2 rows, 1 columnPanel1.setLayout (new GridLayout (2,1));
// add the first two LabelsPanel1.add (Label1); // 1st area: row 1Panel1.add (Label2); // 2nd area: row 2
Label One
Label Two
Label 3
Label Four
Button Two Button Three
TextArea1 is here {no label displayed}
Button One
The third quadrant of the GridLayout:• Contains nothing. • To "skip a space" in a GridLayout, we add a "throw-away" panel:
add (new Panel());
Label One
Label Two
Label 3
Label Four
Button Two Button Three
TextArea1 is here {no label displayed}
Button One
The fourth quadrant of the GridLayout:• Contains several components. • Because only one component is permitted per area, we subdivide the space as needed:
// create a second PanelPanel Panel2 = new Panel();
// add it to the next positionadd (Panel2);
// divide it into 4 rows, 1 columnPanel2.setLayout (new GridLayout (4,1));
// add the componets, row by rowPanel2.add (Label3);Panel2.add (Button1);Panel2.add (Label4);
But Panel 2’s 4th row holds two items, so . . .
Label One
Label Two
Label 3
Label Four
Button Two Button Three
TextArea1 is here {no label displayed}
Button One
The fourth quadrant (continued):Create room for Button2 and Button3 by:• creating a new Panel3, • then adding it to Panel2, • then subdividing Panel3 into 1 row of 2 columns:
// create the new Panel3Panel Panel3 = new Panel();
// add Panel3 to Panel2Panel2.add (Panel3);
// subdivide Panel3// into 1 row, 2 columnsPanel3.setLayout (new GridLayout (1,2));
// add the Buttons to Panel3Panel3.add (Button2);Panel3.add (Button3);
Label One
Label Two
Label 3
Label Four
Button Two Button Three
TextArea1 is here {no label displayed}
Button One
The final code:// declaration section - usually instance variablesTextArea TextArea1 = new TextArea();Label Label1 = new Label ("Label One");Label Label2 = new Label ("Label Two");Label Label3 = new Label ("Label 3");Label Label4 = new Label ("Label Four");Button Button1 = new Button ("Button One");Button Button2 = new Button ("Button Two");Button Button3 = new Button ("Button 3");Panel Panel1 = new Panel();Panel Panel2 = new Panel();Panel Panel3 = new Panel();
// set up the layout (inside a constructor or init( ))setLayout (new GridLayout (2,2));
// quadrant 1 - just a textarea.add (TextArea1);
// quadrant 2 - panel with two labelsadd (Panel1);Panel1.setLayout (new GridLayout (2,1));Panel1.add (Label1);Panel1.add (Label2);
// quadrant 3 - empty and not usedadd (new Panel());
// quadrant 4 - Panel containing 4 rows, last of which// is a Panel containing two buttonsadd (Panel2);Panel2.setLayout (new GridLayout (4,1));Panel2.add (Label3);Panel2.add (Button1);Panel2.add (Label4);Panel2.add (Panel3);Panel3.setLayout (new GridLayout (1,2));Panel3.add (Button2);Panel3.add (Button3);
Lecture Summary• GUIs and the Java AWT• Components as elements of presentation and interaction• Composition
• Layout of components within containers– Layout managers encapsulate layout policy
• Containers “delegate” this responsibility.– Border layout fits elements close to edges/center– Grid & flow layouts layout spatially if there’s room
– For “clustered” components, use panels as sub-containers
• components arranged in panels, arranged in panels, in panels...
GSAMS--Java CourseGSAMS--Java Course
Interfaces &Interfaces &
EventsEvents
Java Interfaces• Multiple inheritance issues• Adding functionality to a hierarchy• Adding functionality and a shared interface to multiple hierarchies• Using interfaces as types
Event-driven Programming• Basic model• Applets• Events• Handling Events• Registering Event Handlers• Writing Event Handlers• Debugging Strategies
Java InterfacesJava Interfaces
Java InterfacesJava InterfacesMeans of solving many problems thatseem to call for multiple inheritance.
Object Drawable
Shape
Circle Rectangle Triangle
Example: Want to draw Shapes on a Graphics object.
Multiple inheritance:• Introduces many annoying complexities.• Java does not support it.
Square
Java Interfaces--Partial Solution Java Interfaces--Partial Solution #1#1
• We could make a new base class (e.g., DrawableShape), giving us both:
Shape
Circle Rectangle Triangle
and:
• Bad idea: much redundancy, is anti-OO.
Square
DrawableShape
DrawableCircle DrawableRectangle DrawableTriangle
DrawableSquare
Java Interfaces--Partial Solution #2Java Interfaces--Partial Solution #2
Drawable
Shape
Object
Circle Rectangle Triangle
• We could insert a new class into the object hierarchy . . .
• Bad idea: Drawable need not be a propertyof Shapes, are imposing functionality where it might not be needed.
Square
JavaJava Interfaces InterfacesBest: create interface that allow us to extend functionality without disturbing class hierarchies . . .
Shape
Object
CircleRectangle Triangle
DrawableCircle
Drawable
DrawableRectangle
DrawableTriangle
Square
DrawableSquare
Makes our diagrammore complex, but makes everything else simpler!
Example: add functionality without disturbing existing Shape hierarchy, e.g., make our existing Squares drawable.
public interface Drawable { // no constructors! no default methods! just method headers! public void drawMe (Graphics g);} // of Drawable
public class DrawableSquare extends Square implements Drawable {
// "extends": we inherit everything that Square has - no need to // re-write any constructors, accessors, modifiers;
// “implements”: must have code for drawMe( ) (or at least // declare it as abstract) in order to satisfy interface requirements
public void drawMe (Graphics g) { g.drawRect (0,0,iSideSize,iSideSize); } // of drawMe} // of DrawableSquare
Java InterfacesJava Interfaces
• Do just what they say: provide interfaces.
• Typically concerning shared logical properties.
• Can use to provide shared interface/functionality to multiple independent class hierarchies.
• Typically, interface identifiers end in -able or -ible: Drawable Printable Edible Purchasable
PrintableGraphics
Graphics TextFile
PrintableText
Printable
Java InterfacesJava Interfaces
public interface Printable{ public void printMe( );} // of interface
public class PrintableText extends TextFile implements Printable{ // inherits from TextFile // must have printMe( ) method to implement Printable public void printMe( ) { // code to print the text file goes here } // printMe} // PrintableText
public class PrintableGraphics extends Graphics implements Printable { // inherits from Graphics // must have printMe( ) method to implement Printable public void printMe( ) { // code to print the Graphics object goes here } // printMe} // PrintableGraphics
Interface ExampleInterface Example
• Can now use Printable as a type, e.g., . . .
• Can implement a PrinterQueue as an array of Printables:
Printable[ ] printerQueue = new Printable[10];
• The array printerQueue can now handle anything that implements the Printable interface.
• This is an example of polymorphism at work.
Interface ExampleInterface Example
Syntax notes re: interface methods:
• They must be public (cannot be private or protected).
• They must be instance methods (cannot be static).
• They are abstract by default (no need to explicitly declare them to be abstract).
• No variables may be inherited from interfaces.
Interface DetailsInterface Details
Java InterfacesJava Interfaces
Are independent from class hierarchies.
Can now consider both:• Are you a <ClassName>?• Can you do <Functionality>?
Use interfaces when: • you want to factor out commonalities among classes, but• you do not want a relationship between those classes.
Example Interface: Example Interface: EnumerationEnumeration
• Enumeration is an interface, not a class.
• Implemented by class Vector and others (e.g. Hashtable).
• May be implemented by any other classes which are defined to implement it (e.g., linked list, BST, graph, etc.).
• The interface specifies that all classes which implement Enumeration must implement the two methods:
public boolean hasMoreElements( );
public Object nextElement( );
• Defines methods needed to enumerate (or iterate through) a set of values.
• Typically, use methods in a loop to see if there’s another element to return and, if so, to return a reference to it.
Makes no promises about the order in which elements are encountered.
• Values may be iterated through only once; there is no way to reset to the beginning.
Example Interface: EnumerationExample Interface: Enumeration
Event Driven ProgrammingEvent Driven Programming
Traditional programming:
• The program’s main algorithm governs the flow of control throughout the program
• The general model:
“do step A, then do step B, then do C or D, then…”
Event-driven programming:
• The program waits for the user to do something, processes that event, then waits for the user again.
• The general model:
loop
get user event
process user event
do something that responds
to that event
endloop
• A type of event-driven programming.• A type of application that uses graphics.
An applet:• Waits for the user to do something, e.g.,
• move the mouse• click the mouse• press a key
• Processes that event• Does something based on that event
For example: • the program waits until you press a button, • the program sees that you pressed a button, • the program then does something based on the fact that you pressed that button, e.g.,
• clear the screen• restart a game
Event Driven Programming: Applet ExampleEvent Driven Programming: Applet Example
Recall the specific stages in an applet’s lifecycle.
• public void init( ) Called by browser or applet viewer: tells applet that it has been loaded into the system. Is called once per applet.
• public void start( ) Called by browser or applet viewer, tells applet to execute.
• public void paint(Graphics g) Paints the component (draws the component): tells applet to paint (draw) the contents of a component.
• public void stop( ) Called by browser or applet viewer: tells it to stop execution.
• public void destroy( ) Called by browser or applet viewer: tells applet that it is being killed, that it should destroy resources that it has allocated so that they can be reclaimed for other use.
Event Driven Programming: Applet ExampleEvent Driven Programming: Applet Example
EventsEventsPackage java.awt.event features common event methods:
actionPerformed(ActionEvent) // Called if an action occurs in the // Component. keyPressed(KeyEvent) // Called if a character is pressed. keyReleased(KeyEvent) // Called if a character is released.
mousePressed(MouseEvent) // Called if the mouse is down. mouseDragged(MouseEvent) // Called if the mouse is dragged mouseEntered(MouseEvent) // Called when the mouse enters // component. mouseExited(MouseEvent) // Called when the mouse exits the // component. mouseMoved(MouseEvent) // Called if the mouse // moves (button is up) mouseReleased(MouseEvent) // Called if the mouse // button is released.
Handling EventsHandling Events
Any component, such as • a Button• a Canvas• a Menu, etc.
can have events happen to it.
For example, a user can:• select a menu item from a Menu • drag the mouse over a Canvas• type text into a Text Field• click on a Checkbox• etc., etc.
To avoid slow-downs in program execution, Java does not automatically "handle" any of these events . . . unless the programmer explicitly tells Java to do so.
In order to capture an event, you need to have an appropriate “event listener".
An event listener is an interface which specifies some event-handling methods for the particular type of event to be handled.
For example: an ActionListener specifies the method:
public void actionPerformed(ActionEvent <eventName>)
For a complete listing of the listeners and the methods they require, refer to p.151 of Java in a Nutshell, or the java.awt.event.* package.
Handling Events -- HowHandling Events -- How
Registering Event HandlersRegistering Event Handlers
• To have Java use the event listener, you must tell Java to do so by registering the event
• To register a specific event, use addListener methods built into each component.
For example, a Button or MenuItem has the method:
addActionListener(ActionListener a)
to add an action listener to itself.
• Adding an action listener specifies that, whenever that Button or MenuItem gets an action event, it will call the method actionPerformed( ) on all the actionListeners that have been added to it
• Because interfaces are contracts, Java guarantees that any class that implements the ActionListener interface must provide code for actionPerformed( )
Writing Event HandlersWriting Event Handlers
To write an event handler:
• Have a class that implements one or more of the Listener interfaces.
To "catch" the event:
• Write code for the appropriate event handler specifying the response to the event.
• Then, register your event handler class with the addListener method of the component whose event you want to catch.
Example follows
import java.applet.Applet;import java.awt.*;import java.awt.event.*;
public class simpleApplet extends Applet implements ActionListener { Button other, printHello; Canvas myCanvas;
public void init( ) {
// set up "other" button; have its action event go here other = new Button( "other" ); other.addActionListener (this);
// set up "printHello" button; action event go here printHello = new Button( "Print ‘Hello World’" ); printHello.addActionListener (this);
Writing Event Handlers: ExampleWriting Event Handlers: Example
continued
// set up Canvas to draw on myCanvas = new Canvas( );
// place components on screen setLayout( new BorderLayout( ) ); add( printHello, "North" ); add( other, "South" ); add( myCanvas, "Center" ); } // init
public void actionPerformed ( ActionEvent evt ) { // print a simple message to see what button was pressed // getSource( ) returns a reference to the object that // caused the event to happen if ( evt.getSource( ) = = other ) System.out.println( “other pressed.” ); else System.out.println( “Print 'Hello World' pressed.” ); repaint( ); } // actionPerformed continued
public void paint( Graphics g ) { System.out.println( "paint( ) called" );
myCanvas.getGraphics( ).drawString( "painting!", 0, 115 );
myCanvas.getGraphics( ).setColor( Color.magenta ); myCanvas.getGraphics( ).fillOval( 220, 220, 50, 50 ); myCanvas.getGraphics( ).setColor( Color.black ); myCanvas.getGraphics( ).drawOval( 220, 220, 50, 50 );
} // paint
} // simpleApplet
Event Handling: General OptionsEvent Handling: General Options
Four general options for event handling:
1. Event Listeners
-- use interfaces. Good for low-level control.
2. Event Adapters
-- use objects. More selective.
3. Semantic Events
-- for simple event handling.
4. ‘Old’ JDK 1.02 events
--not recommended; useful in rare circumstances
Option #1: Event ListenersOption #1: Event Listeners
As noted, one can ‘addXYZListener’ to a component, e.g.:
class TestApplet extends Applet implements MouseListener{ Button myButton; public void init(){
myButton = new Button(“Click”); myButton.addMouseListener(this);
. . . } // TestApplet When using listener interfaces, one must code all event methods--even those we are not interested in. Wasted code arises:
public void mouseEntered(MouseEvent e){;}public void mouseExited(MouseEvent e){;}public void mouseClicked(MouseEvent e){;}public void mouseReleased(MouseEvent e){;}
public void mousePressed (MouseEvent e){
/* handle mouse event */}
“no-op”methods
Single method wedo something in
Option #2: Event AdaptersOption #2: Event Adapters
In addition to interfaces, the java.awt.event.* package provides“adapter” classes that can be subclassed.
No need to code every method; just override the method you need:
public void mouseEntered(MouseEvent e){;}public void mouseExited(MouseEvent e){;}public void mouseClicked(MouseEvent e){;}public void mouseReleased(MouseEvent e){;}
public void mousePressed(MouseEvent e){ /* handle mouse event */}
Public class EventHandler extends MouseAdapter {
Less wasted code; but you use up your single inheritance!
Event Adapters: RegistrationEvent Adapters: Registration
public class TestApplet extends Applet{private Button myButton;private EventHandler handle;public void init(){
handle = new EventHandler(this);myButton = new Button(“Click”);myButton.addMouseListener(this);
. . . . . . . . . public void takeActions() { . . . . }
public class EventHandler extends MouseAdapter{TestApplet myApplet;public EventHandler(TestApplet myApplet){ this.myApplet = myApplet ;
}public void mousePressed(MouseEvent e){
myApplet .takeActions();}
Passing ‘this’allows forcall-backs
Event handledby accessing
applet
Option #3: Semantic EventsOption #3: Semantic Events
The foregoing options (interfaces and objects) involvedlow-level events.
Event processing may also occur through the use of semantic events.
Unlike listeners/adapters, these are high-level, component-based events.
They essentially ‘funnel’ a variety of low-level events into a single method.
NOTE: You lose ability to catch small, granular events (e.g., mouseEntered/Exited are not possible).
Since ALL events delivered to a few methods, event handling relies on complex, linear if/else structures.
Semantic Event Components and Firing Event
ActionEvent Button (activated)List (double-clicked)MenuItem (selected)TextField (typed)
AdjustmentEvent Scrollbar (moved)
ItemEvent Checkbox (toggled)CheckboxMenuItem (selected)Choice (selected)List (selected)
TextEvent TextComponent (text changes)
Semantic EventsSemantic Events
• An earlier version of Java used “boolean” return values to indicate consumption of events
• Not recommended; still used for some web development
• Do not mix JDK 1.1 and JDK 1.02 event handlers--the component ceases to function.
• Rare use: JDK 1.02 guarantees which event will arrive first to a component.
(non) Option #4: JDK 1.02 Events(non) Option #4: JDK 1.02 Events
Event Listeners(interfaces)
Event Adapters(inheritance)
Semantic Events
Costs Benefits
Must code allmethods; wastefulno-ops result
Uses up singleinheritanceopportunity
Simplifiesevent handling
Loss ofgranularcontrol;linear code
Keep allevents insingle class
Good abstraction;override those methodsyou need
Event Handling Options: How to DecideEvent Handling Options: How to Decide
DebuggingDebugging re: Event Handlersre: Event Handlers
• Debugging an event-driven program (whether applet or graphical application) is more tricky than debugging a non-event-driven program.
• With an event-driven Java program, you don't explicitly code any kind of event-handling loop that "polls" for occurring events, then calls the appropriate handler(s) for those events.
• Instead, the Java internals handle this polling action for you. Debugging becomes trickier because now you have to make sure that your event handling code works correctly.
• You also have to make sure you're handling the
correct events in the first place! For example,
your code for mouseEntered( ) may work perfectly,
but if you're expecting it to get called when the user clicks a mouse button, it won't be!
Debugging re: Event HandlersDebugging re: Event Handlers
So, in debugging event-driven programs written with Java, the steps are:
• Be sure you're handling the appropriate events: Map out on paper what events get thrown from what components, and what class(es) handle them.
• Handle the events appropriately: This is the kind of debugging you're already familiar with: Once you're sure the appropriate events are getting handled, the rest is being sure the event-handling code (and the code that the event handlers call) work.
Example: Create a Paint AppletExample: Create a Paint Applet
Goal:Goal: create applet that:
Allows user to draw with mouse
Mouse drag draws
Mouse up stops drawing
Pen color selectable
Button to clear canvas
Will show three versions, each using different event handling techniques
CLEAR RedPenColor:
1. List Basic1. List Basic Components/Containers:Components/Containers:
java.applet.Applet --java.awt.Canvas
--java.awt.Panel ---java.awt.Button
---java.awt.Choice ---java.awt.Label
2. List Basic Behaviors:2. List Basic Behaviors:
mouse drag draws
button clears canvas
choice changes pen color
canvas knows whether to draw (mouse drag) or not (mouse is up)
Design #1: Interfaces OnlyDesign #1: Interfaces Only
3. Outline classes, assigningfrom two lists
a. Drawing: Canvas subclass -- paint method draws -- has reference to controls -- boolean flags for clear/draw
b. Control panel: Panel subclass -- has Button, Label, Choice -- sets flags in canvas to clear/
change color, etc. -- has reference to canvas
c. Top container: Applet subclass -- BorderLayout -- Introduces classes to each other -- Sets some initial values
Design #1: Interfaces OnlyDesign #1: Interfaces Only
CANVAS
General LayoutGeneral Layout
Applet (BorderLayout)
-- add Canvas to CENTER
-- add ControlPanel to SOUTH
-- set initial values (size of
canvas, pen color)
Widgets (Button, Label, Choice)
ControlPanel (GridLayout)
MANDATORY: MANDATORY: Plan your Plan your cross-class communicationscross-class communicationsIn this version, events arehandled by a Control Panel
In such a case, how to send events to Canvas?
Cross-class communications!The control panel has a referenceto the DrawCanvas, and the canvashas a reference to the ControlPanelinstance (ver #1). Alernatively (ver #2), both have reference to Applet, which provides reference to components
Q:Q:
A:A:
D raw A p p le t C la ss S tru ctu re
D ra w C an v asC a nv a s su bc la ssb o o lea n f lag s fo r
c lea r , d ra w ing
C on tro lP a ne lP a ne l S ub cla ssB u tto n to cle a r
ch o ice to ch an g e p en co lo r
D raw A p p le tA p p le t su b cla ss
Design #1: Class StructureDesign #1: Class Structure
Calls (ver #2)calls
(ver
#2)
calls (ver #1)
import java.applet.Applet;import java.awt.*;public class DrawApplet extends Applet {
private ControlPanel controls; private DrawCanvas canvas;
public void init() { this.setLayout(new BorderLayout()); canvas = new DrawCanvas( (int) (getSize().width *.75), (int) (getSize().height *.75) ); controls = new ControlPanel(); /* introduce the components to each other */ canvas.setControls(controls); controls.setCanvas(canvas); canvas.setColor(Color.red);
add(canvas, BorderLayout.CENTER); add(controls, BorderLayout.SOUTH); } // init
}// class DrawApplet
Version #1:
Version #1:
Interfaces
Interfaces
import java.awt.*;import java.awt.event.*;public class ControlPanel extends Panel implements MouseListener, ItemListener { private DrawCanvas canvas; private Button clearButton; private Label label; private Choice colorChoice;
public ControlPanel() { this.setLayout(new GridLayout(1, 3)); clearButton = new Button("Clear"); label = new Label("Select Pen Color:"); colorChoice = new Choice(); colorChoice.add("Red"); colorChoice.add("Blue"); colorChoice.add("Green"); colorChoice.addItemListener(this); clearButton.addMouseListener(this); add(clearButton); add(label); add(colorChoice); } // constructor
public void setCanvas(DrawCanvas canvas) { this.canvas = canvas; } // setCanvas
/* class ControlPanel (cont’d) . . . */ public void mousePressed(MouseEvent e) { if (e.getSource() == clearButton) { canvas.setClear(true); canvas.repaint(); } // if } // mousePressed
public void itemStateChanged (ItemEvent e) { int index = colorChoice.getSelectedIndex(); switch(index) { case 0://red canvas.setColor(Color.red); break; case 1: // blue canvas.setColor(Color.blue); break; case 2: canvas.setColor(Color.green); break; } // switch (what’s wrong with it?) } // itemStateChanged
/* wasted code */ public void mouseReleased (MouseEvent e){ ; } // mouseReleased
public void mouseClicked (MouseEvent e){ ; } // mouseClicked
public void mouseExited (MouseEvent e){ ; } // mouseExited
public void mouseEntered (MouseEvent e){ ; } // mouseEntered
}// class ControlPanel
import java.awt.*;import java.awt.event.*;public class DrawCanvas extends Canvas implements MouseMotionListener, MouseListener{
private int mouseX, mouseY, oldX, oldY; private boolean bClear, bDrawing; private Color color; private ControlPanel controls;
public DrawCanvas(int width, int height) { this.setSize(width,height); this.addMouseListener(this); this.addMouseMotionListener(this); } // constructor
public void setControls(ControlPanel controls) { this.controls = controls; } // setControls
public void updateCoordinates(MouseEvent e) { updateCoordinates(e.getX(), e.getY()); } // updateCoordinates
/* class DrawCanvas (cont’d) . . . */ public void updateCoordinates(int x, int y) { oldX=mouseX; oldY = mouseY; mouseX=x; mouseY=y; repaint(); } // updateCoordinates
public void setDrawing(boolean bDrawing) { this.bDrawing = bDrawing; } // setDrawing
public void setClear(boolean bClear) { this.bClear = bClear; } // setClear
public boolean getDrawing() { return bDrawing; } // getDrawing
public boolean getClear() { return bClear; } // getClear
/* class DrawCanvas (cont’d) . . . */
public Color getColor() { return color; } // getColor
public void setColor(Color color) { this.color = color; } // setColor
public void update(Graphics g) { paint(g); } // update
public void paint (Graphics g) { if (getClear()) { g.setColor(Color.white); g.fillRect(0,0,getSize().width,
getSize().height); setClear(false); } // if if (getDrawing()) { g.setColor(getColor()); g.drawLine(oldX, oldY, mouseX, mouseY); } // if } // paint
/* class DrawCanvas (cont’d) . . . */public void mouseMoved(MouseEvent e) { updateCoordinates(e);} // mouseMoved public void mouseEntered(MouseEvent e) { updateCoordinates(e);} // mouseEntered
public void mousePressed(MouseEvent e) { setDrawing(true); updateCoordinates(e); repaint();} // mousePressed
public void mouseReleased (MouseEvent e) { setDrawing(false); updateCoordinates(e); repaint();} // mouseReleased
public void mouseDragged (MouseEvent e){
updateCoordinates(e); repaint(); } // mouseDragged
/* below is wasted code */ public void mouseClicked (MouseEvent e){ } // mouseClicked
public void mouseExited (MouseEvent e){ } // mouseExited
}// class DrawCanvas