©nabg
GUI
abstract windows toolkit
swing
©nabg
GUI
• Graphical User Interface
– let user enter data for application
– let user control processing steps
– display a view of data to user
©nabg
Graphical User Interface
• Mostly or entirely made up using instances of
concrete classes provided in a graphics library
– “Window” class (Frame, JFrame in Java packages) – subregions (Panel, JPanel in Java packages, positioning using
“layout managers”)
– controls (scrollbars, radio-buttons, check-boxes, action-buttons, popup-menus, …)
– input fields (textfield)
– rich display formats (e.g. javax.swing has styled text, html text, tables, views of tree structures, …)
• Limited use of an application defined subclass of
some system class, used to render picture of
application data
©nabg
GUIs:
the problems
• Windows and graphics had been a major problem for
developers of applications that ran on multiple
platforms.
• Some concepts are common to all systems, but
implementation mechanisms vary substantially.
• Typically graphics/windowing code got interwoven into
application; major rewrite needed for reimplementation
on alternative platform.
©nabg
Common concepts
• Window hierarchy
– “framewindow”communicates with OS’s window manager
– subwindows
• Specialised controls
– usually (but not always) “subwindows” – button, checkbox, radio cluster, scrollbar, ...
• Graphics environment
– associated with each window
• Menu-bar with drop down menus
©nabg
Different implementations
• Windows
– Mac only the main window was known to OS – PC subwindows within main frame window
– Unix even things like thumb and arrows of scroll bar can be separate windows
• Controls
– slightly different functionality, eg scroll bars with/without proportional “thumbs”
• Graphics
– PC “graphics context”, Unix-X Graphics, and Macintosh Port have similar roles but differ in properties and associated function libraries
1996 – Java AWT
Graphics that will run everywhere!
AWT
objectives
• Platform independent application code
–
write once, run anywhere™
• Support “look and feel” of each
platform
write once, debug everywhere?
©nabg
AWT
• Define “Java” window classes
– limited, “lowest common denominator” of
different target platforms
• Write applications that work in terms of these
classes
• Objects that are instances of these classes are
essentially “proxies” - they interface to actual
worker objects that are platform specific.
©nabg
AWT
“peer” classes
Button Radio Checkbox Java Button Radio Checkbox Button Radio Checkbox Button Radio Checkbox Mac PC Unix created and used inyour Java application in Java code
created and used by the C code of the JVM
©nabg
AWT
“peer” classes
• java.awt.peer
– defines a set of “interfaces”
public abstract interface ButtonPeer extends ComponentPeer { public abstract void setLabel(String label);
}
• Each platform’s run-time system defines a
set of component classes that implement the
appropriate interfaces
– Mac’s button uses Quickdraw button – PC’s button uses Window’s button – X’s button uses Motif or OpenLook button
©nabg
AWT
“peer” classes
• Instance of java.awt classes created along with
instances of peer classes with which to work
• Runtimes for individual platforms include a
“component factory object” (the Toolkit object)
that has
– createButton(...), createCanvas(...),
createCheckbox(...), ...
• This run-time object creates the local version of
button (
or whatever other element was needed)
©nabg
AWT & peers
• Peer mechanism provides
– required “look and feel”
– platform independence for rest of code
• Imperfect
– variation of functionality for “standard” GUI
components on different platforms makes total
“work alike” very difficult to achieve
©nabg
Swing!
• Different approach, less reliant on underlying OS.
• Essentially
– Swing asks OS for single window area
– Swing then takes total responsibility for window (does not take advantage of any ability that OS may have for rendering and handling events for subwindows) – Swing
• Get low-level details of events on its single window, sort out which conceptual subwindow (button, scrollbar, whatever) was involved, create Java event for that subwindow
• Get full access to entire window when drawing, draw buttons and other controls in accord with user preferences
©nabg
Swing – visual styles
• Swing can draw controls in different styles
• Default styles mimic appearance of controls
on host platform
• Can set user preferences to specify desired
style
©nabg
Swing caution
•
Swing GUI elements should only be
accessed via the thread supplied by the GUI
package.
•
So?
©nabg
Swing – thread issue
•
Usually this is not a problem.
–
Mainline thread constructs interface.
–
Mainline thread shows interface.
–
Subsequently, swing GUI elements are
automatically accessed via GUI thread.
•
But, sometimes, …
©nabg
Dynamic swing interface
•
Sometimes things are more dynamic
–
construct part of interface,
–
display it,
–
add more elements later
–
(can happen in JApplets when building
interface in JApplet.init())
•
Then
Dynamic interface – thread collision
•
Sometimes (
not when you are testing your code, when the marker – or your boss – is trying it) get situation where
GUI thread does update at same time as
other thread tries to add an element to GUI
•
Result
–
possibly chaos
–
possibly deadlock
Fix – SwingUtilities.invokeLater
•
Ugly bits of code
–
Code to build interface essentially defines a
little runnable object that will make the changes
that add (or remove) GUI elements.
–
Reference to this thing passed in “invokeLater”
request to GUI framework.
–
Code gets run by GUI thread; eliminating risk
of deadlocks etc
©nabg
Ignore Swing problem for now
•
Too convoluted to bother with in our simple
exercises.
•
See:
http://java.sun.com/products/jfc/tsc/articles/thr
eads/threads1.html
•
NetBeans will help you build a safe swing
interface
©nabg
Graphics object
When you really need to draw a
picture!
Drawing basics – class Graphics and friends
©nabg
Graphics object
• Graphics object encapsulates details of drawing
environment for a window
public abstract class Graphics extends Object {
public abstract void clearRect(int x, int y, int width, int height); ...
}
• Concrete “Graphics” subclasses defined on
individual platforms
Same for Swing and AWT
Drawing basics – class Graphics and friends ©nabg
Graphics
• Different platforms do share
– similar coordinate models
• use ‘pixel’ coordinates for drawing to screen (printer driver will deal with changes in resolution)
• (0,0) is top left corner, x increases to right, y increased down
– similar range of functions
• draw: lines, outlines of rectangles and ovals, filled rectangles and ovals, outline and solid arcs, text strings
– similar (r, g, b) colour space
©nabg
Graphics
• Functionality provided by Graphics object
is less than typically available in “native”
graphic APIs for various platforms
– eg can’t specify line thickness (even though all
platforms do support such a concept)
Drawing basics – class Graphics and friends ©nabg
Graphics
• Graphics class defines methods
– draw
• drawArc(), drawBytes(), drawChars(), drawImage(), drawLine(), drawOval(), drawPolygon(), drawString(), drawRect(), drawRoundRect()
– fill
• fillArc(), fillOval(), fillPolygon(), fillRect(), ...
– set & get
• setColor(), getColor(), setFont(), getFont(), ...
– misc.
• clipRect(), clearRect(), copyArea(), setPaintMode(), ...
Check the package interface on line documentation for function prototypes and full list of properties Drawing basics – class Graphics and friends
©nabg
Graphics
• Related classes
– Font and FontMetrics
– Color
– Rectangle, Point, Polygon
– Image (and MediaTracker)
Drawing basics – class Graphics and friends ©nabg
Color, Font and Graphics
Text in selected font
Polygon, filled rectangle, oval, and arc, rect3D Outlines (rect, oval, round-cornered rect) and line Output to browser status bar Colours selected from “palette” Coord (0,0) Coord (400,450) ©nabg
Fonts
• Fonts are selected by name, size, and style
– create a new Font object as needed (
typical sloppy Javaprogramming, just forget about it when not needed; the garbage collector will tidy up for you
)
fFontName = fFontNames[n];
fFont = new Font(fFontName, Font.BOLD, 14);
Drawing basics – class Graphics and friends ©nabg
Fonts
• Java will have
-– Serif, SanSerif, Monospaced, Dialog, DialogInput
• Your system may have more, but if you are trying
to be portable then you had better not rely on there
being other Fonts.§
• Size is “point size”
• Styles defined by Font constants
– FONT.BOLD, FONT.ITALIC, FONT.PLAIN §Java can use Windows fonts, and there are lots installed by WindowsColors
• Colors (
Colours for those who spell in English
)
– several different approaches to specifying colours)
• “red”, “green”, “blue” • hue, saturation, brightness • luminance and two chrominance
– computer terminals usually employ rgb
• Create Color objects as needed, specify rgb
values (each in range 0...255)
-fColor = new Color(135, 206, 235); // sky blue
Drawing basics – class Graphics and friends
Colors
• Class Color has some predefined color
constants
– black, blue, cyan, darkGray, gray, green,
lightGray, magenta, orange, pink, red, white,
yellow
• SystemColor class has colors used by default for things like color of window frame, border color for caption text, ...
Drawing basics – class Graphics and friends
©nabg
Colors
• There are several hundred “standard colors” (
egpalette defined for Xlib, but not provided as inherent part of Java libraries
)
• “Standard” colours, defined by rgb values (
see
/usr/openwin/lib/rgb.txt on Unix
)
255 235 205 blanched almond 255 228 196 bisque 255 218 185 peach puff 255 222 173 navajo white ...Drawing basics – class Graphics and friends ©nabg
GraphicsDemo
• Trivial applet,
<HTML><TITLE>A Graphic Demo</TITLE> <BODY>
<APPLET ALIGN=MIDDLE CODE="GraphicDemo.class" WIDTH=400 HEIGHT=350>
</APPLET></BODY></HTML>
• GraphicDemo extends Applet impements Runnable
– this one has a “thread” that every second redraws the
image using a different colour and font
Drawing basics – class Graphics and friends
©nabg
GraphicsDemo
• Using a separate thread (locus of control)
• Main thread just sitting in code that handles
user interaction, updates of screen etc
• Second thread in loop with following form
– pick next colour
– pick next font
– force a repaint
– sleep for two seconds
Drawing basics – class Graphics and friends ©nabg
import java.awt.*; import java.applet.*;
public class GraphicDemoextends Applet implements Runnable
{
public void paint(Graphics g) { ... }
public void run() { ... } public void start() { ... } public void stop() { ... } public void init() { ... }
private String[] fMessageList = { "Hello World", "Hi mom", "Buy now",
"Fresh Java", "Write once, run everywhere", "Hype", "WWW rules OK" };
private String[] fFontNames = { "SansSerif", "Serif", "Monospaced",
"Dialog" };
// Color palette names and matching r, g, b values
©nabg
public class GraphicDemo extends Applet implements Runnable {
...
// Color palette names and matching r, g, b values private String[] fColorPalette = {
"lemon chiffon",..., "rosy brown", };
private int fR[] = { 255, ..., 188, };
private int fG[] = { 250, ..., 143, };
private int fB[] = { 205, ..., 143, };
// private data members ...
Drawing basics – class Graphics and friends ©nabg
public class GraphicDemo extends Applet implements Runnable {
...
// private data members private String fMessage; private Color fColor; private String fColorName; private Font fFont; private String fFontName; private Thread fThread; private boolean fRunning; private Polygon fPoly; }
Drawing basics – class Graphics and friends
©nabg
public void paint(Graphics g) {
if(!fRunning) return; // watch out for initial drawing
g.setFont(fFont); g.setColor(fColor); g.drawString(fMessage, 40, 50); g.drawString(fFontName, 40, 80); g.drawString(fColorName, 40, 110); g.setColor(Color.black); g.drawRect(10, 5, 25, 30); g.drawRoundRect(20, 130, 100, 40, 8, 8); g.drawRoundRect(20, 180, 100, 40, 16, 16); g.drawOval(150, 130, 40, 40); g.setColor(fColor); g.fillRect(210, 130, 25, 19); g.fillOval(210, 150, 30, 80); Parameters control curvature of corners
Drawing basics – class Graphics and friends ©nabg
public void paint(Graphics g) { ...
g.fillOval(210, 150, 30, 80);
g.drawLine(5, 190, 300, 100); g.fillArc(160, 210, 50, 50, 15, 170);
if(Math.random()>0.5) g.drawPolygon(fPoly);
else g.fillPolygon(fPoly);
if(Math.random()<0.5) g.draw3DRect(260, 260, 40, 30, Math.random() > 0.5); else g.fill3DRect(260, 260, 40, 30, Math.random() > 0.5); } Bounding box
Initial & size arc angles
Drawing basics – class Graphics and friends
©nabg
Color, Font and Graphics
Text in selected font
Polygon, filled rectangle, oval, and arc, rect3D Outlines (rect, oval, round-cornered rect) and line Output to browser status bar Colours selected from “palette” Drawing basics – class Graphics and friends
©nabg
public void start() {
fThread = new Thread(this); fThread.start();
}
public void stop() {
fThread.stop(); }
public void init() { fRunning = false;
fPoly = new Polygon();
fPoly.addPoint(210,10);
...
fPoly.addPoint(208, 72); }
public void run() {
for(int i=0;i<50;i++) { int n;
showStatus("loop " + i);
n = i % fMessageList.length; fMessage = fMessageList[n]; n = i % fFontNames.length; fFontName = fFontNames[n]; fFont = new Font(fFontName, Font.BOLD, 14);
n = i % fColorPalette.length; fColorName = fColorPalette[n]; fColor = new Color(fR[n], fG[n], fB[n]);
fRunning = true;
repaint();
try { Thread.sleep(2000); } catch (InterruptedException ie) { }
} }
Drawing basics – class Graphics and friends
FontMetrics
• Unlikely to need to use this class in routine
graphics displays.
• Use Font.getFontMetrics() to get FontMetrics
object for chosen font.
• FontMetrics object can then provide detailed
information relating to
– length of a String (displayed in that Font) – height of a character
– position (to text base-line) of top/bottom of character – ...
Drawing basics – class Graphics and friends
©nabg
FontMetrics
• Used mainly with relatively complex text
passages
where
you need text in different
fonts
,
sizes, and styles
styles.
• Such text gets output as several strings,
each with specified font settings.
• Need to know position of end of one piece
of text before can position next piece.
Drawing basics – class Graphics and friends ©nabg
FontMetrics
Font myFont = new Font(“Serif”, Font.BOLD, 32); FontMetrics measure = new FontMetrics(myFont); int spacewidth = measure.stringWidth(“ ”); ...
int height = 50; int pos = left;
g.drawString(s1, pos, height);
pos = pos + spacewidth + measure.stringWidth(s1); int len2 = measure.stringWidth(s2);
if(pos + len2 > limit) { pos = left; height+= vspace; } g.drawString(s2, pos, height);
Drawing basics – class Graphics and friends
©nabg
FontMetrics
• Positioning of text can be more elaborate
– varying line spacing to suit text etc.
This is text with some odd characters
like ∫
and
fi
fi
fl
§, ¢, Ç, T, g,™, ¿, pq
Â
And more
ζ
ξ
p
⎟⎟ ⎞ ⎞⎞
A
baseline, height, ascent, descent, leading, ...
Drawing basics – class Graphics and friends ©nabg
Use swing if you need fancy text
•
You can do your own fancy text output
using FontMetrics
•
but, if you are just displaying text (and not
some complex mixture of text and other
graphics), you will find it much easier to
use a styled text output class from the swing
libraries
©nabg
Images
• Images
– gif or jpeg pictures
– loaded from file (local, or accessed via network)
• Image can be drawn in original size, or you can
specify size and system will scale image for
you
Graphics.drawImage(Image, int x, int y, ImageObserver)
Graphics.drawImage(Image, int x, int y, int width, int height, ImageObserver)
Drawing basics – class Graphics and friends ©nabg
Images
• Oddity
– getImage()
doesn’t get an Image!
It starts the process of fetching image then
returns (bytes for image may take some time to
arrive across net)
• Code has to deal with this behaviour
– “ImageObserver” gets called regularly as data
arrive, can then repaint a bit at a time
– “MediaTracker” can be set to delay main
thread until data are complete
Drawing basics – class Graphics and friends
©nabg
Watching images load
• Originally, I had a little demonstration at this point that showed a picture being loaded
• You could actually see successive lines of the image being drawn
• Networks and computers are so fast these days that the demo no longer works!
The picture appears “instantaneously”.
• Still have to use ImageObservers
• Still have to use MediaTrackers
– Often best approach is to load all images during program initialization, using a MediaTracker to make program wait until all are loaded
Drawing basics – class Graphics and friends ©nabg
MediaTracker
• Create a MediaTracker to work with the
ImageObserver object that is loading.
• Give MediaTracker a reference to each of
the images that it is to monitor
– associate an ID with each
– ID can act as a priority (lower numbered IDs should get dealt with first)
• Tell MediaTracker to delay until specified
Image has arrived (or delay until all arrived)
Drawing basics – class Graphics and friends
©nabg
MediaTracker
public void init(){
String picture = getParameter("picture"); if(picture == null) return;
fImage = getImage(getDocumentBase(), picture);
MediaTracker waitForIt = new MediaTracker(this); waitForIt.addImage(fImage, 1);
try { waitForIt.waitForID(1); } catch (InterruptedException ie) { }
}
Drawing basics – class Graphics and friends
Code fragment from an Applet – “this” references the Applet, which is an ImageObserver
©nabg
Superimposing images
---animations etc
• Typically, an animation (e.g. a computer
game) will have irregularly shaped objects
moving across a fixed background.
• Images typically are defined by rectangles.
• Don’t want a blacked out rectangle
surrounding each game piece.
Superimposing images
---animations etc
• Graphics systems allow you to avoid this by
defining
– not just red, green, blue values of each pixel
– but also “transparency”
• If a pixel is completely transparent, you see the
colour of any background pixel.
• If pixel is completely opaque, you see its r,g,b
colour
• Otherwise you see some mixture of colours
Drawing basics – class Graphics and friends
Superimposing images
---animations etc
• The “transparency” is the “alpha channel” of a
pixel
– red, green, blue, alpha
• It is possible to adjust an Image in your Java
code
– create a PixelGrabber from your Image
– make vectors of r,g,b and a values (each horizontal scanline appends to vector), fill using PixelGrabber
– you adjust ‘alpha’ values of chosen pixels – you create a new Image using modified array
Drawing basics – class Graphics and friends
©nabg
Superimposing images
---animations etc
• Often easier to use one of tools that works
with “gif” files and defines a (single)
chosen colour as being transparent.
Picture supposedly represents leaping frog
(it is a 32x32 block, blacked out, then picture drawn in a paint program)
Define “black” as transparent (this will be an option in a “gif” manipulation program)
This demo doesn’t work in all browsers (it should though).
Drawing basics – class Graphics and friends ©nabg
Superimposing images
---animations etc
• “Frog” can now be imposed on any
background picture
+
=
Drawing basics – class Graphics and friends
©nabg
HTML for Animation
<HTML>
<TITLE>A simple animation/transparent gif demo</TITLE> <BODY>
<APPLET ALIGN=MIDDLE CODE="AnimDemo.class" WIDTH=400 HEIGHT=350>
<PARAM NAME="actor" VALUE="./images/frog.GIF"> <PARAM NAME="bkgd" VALUE=
"./images/background.GIF"> </APPLET>
</BODY></HTML>
Drawing basics – class Graphics and friends ©nabg
Animation
• Load background and moving image(s) (sprite)
• Wait till both loaded
• Create thread
• Run thread
– move sprite (here just has approximate sine wave to define motion)
– force repaint – sleep
©nabg
Animation
• Need to do own “clipping”
- don’t want sprite
to appear outside of background image
• Flicker?
– use double buffering scheme if do have flicker
problems
• “Continuous motion”?
– aim for about 24 repaints per second and small motions
Drawing basics – class Graphics and friends ©nabg
import java.awt.*; import java.applet.*;
public class AnimDemo extends Applet implements Runnable{
public void paint(Graphics g) { ... } public void start() { ... }
public void stop() { ... } public void run() { ...} public void init() { ... }
// private data ... }
Drawing basics – class Graphics and friends
©nabg
public void start() { fThread = new Thread(this); fThread.start(); } public void stop() { fThread.stop(); }
public void run(){
for(;;) {
dX += deltaX; if(fX+dX > getSize().width) dX = 0; dY += deltaY;
if(dY <= -32) deltaY = 8; else if(dY >= 16) deltaY =- 8; repaint();
try { Thread.sleep(500); } catch (InterruptedException ie) { } }
}
Move “frog” across full width of Applet’s window (maybe wider than background).
Position defined by dX, dY offsets to start point; limited ranges defined.
Two frames per second. Drawing basics – class Graphics and friends ©nabg
public void init() {
String picfilename = getParameter("actor"); fActor = getImage(getDocumentBase(), picfilename); picfilename = getParameter("bkgd");
fBackground = getImage(getDocumentBase(), picfilename);
MediaTracker waiter = new MediaTracker(this); waiter.addImage(fActor,1);
waiter.addImage(fBackground, 2); try { waiter.waitForAll(); } catch (InterruptedException ie) { }
fX = -32; fY = 48; dX = dY = 0; deltaX = 8; deltaY = -8; }
Drawing basics – class Graphics and friends
©nabg
public void paint(Graphics g){
g.clipRect(0, 0, fBackground.getWidth(this), fBackground.getHeight(this));
g.drawImage(fBackground, 0, 0, this); g.drawImage(fActor, fX+dX, fY+dY, this); }
Drawing basics – class Graphics and friends ©nabg
Animations
• Typical animation would use set of slightly
different images
• Each repaint operation would change to next
image from sequence
• Synchronisation mechanisms may be needed
– one thread will be updating record of where program has reached in sequence
– other thread may be trying to use image
Animations
• Part of new “Media” API
– sprites
• images that move across the background
– scripting
• specify how sprites
– get created/removed – move
– change through sequence of images – interact
– ...
Drawing basics – class Graphics and friends
Subwindow for drawing …
©nabg
Where to draw?
• Those examples simply output to the applet’s main
window (
equivalent for an application would be drawing on“Frame”
)
• Generally, main window or frame has to hold many
different controls, output regions etc.
• Most programs will use a “Canvas” subclass for
graphic output
-– Canvas simply defines a drawing area occupying some part of enclosing window
– you subclass Canvas to provide an effective paint() function
©nabg
MyCanvas extends Canvas
• MyCanvas
– owns connection to data object (model in
model-view-control); data object has reciprocal
link back to MyCanvas
– has size set
– gets told to paint(), relays request to data object
• Associated data object
– when changed, invokes repaint() on associated
MyCanvas
©nabg
awt and swing again
• AWT –
– designers thinking of • frame
• some standard controls
• Canvas where draw application specific data
• Swing
– different view, most Java is used in “enterprise” (business) computing, need is for lots of displays of text in tables etc
• frame • standard control • fancy text outputs
• No provision for drawing application specific data
©nabg
No Canvas in swing
•
Swing omits canvas
•
Can use JPanel
–
some issues about setting size
•(a Panel, or JPanel, is a container for other components; it recomputes its size when overall window size changed; it recomputes its size by asking the components it contains for their sizes; JPanels with no components can get zero size!)
©nabg
User interface
©nabg
User interface
• Most of user interface made up from library
supplied classes
– controls – input fields
• Canvas (or javax.swing.JPanel) displaying
application data would only be a limited part (
and may not be needed at all if application is conventional business data processing one with form entry and tabular results displays)
©nabg
User interface
• Typical user interface has main window
with multiple subwindows
– output subwindows
• scrollable text, canvas for graphics, ...
– data input
• text input field, canvas again (can pick up mouse clicks and have program interpret as drawing action)
– control
• checkboxes, action buttons, radio selection, scroll bars, menus, ...
©nabg
Interface design
placing elements within window
©nabg
“Layout managers”
•
How can you arrange subwindows?
• Traditionally, programmers used absolute coordinates
and sizes.
• This did not suit AWT
– size of a “checkbox” (and almost every other control) would differ from one platform to another
– area occupied by text strings, bounding boxes etc vary
• An arrangement that looked fine on one platform
might be unusable on another.
©nabg
Layout managers
• Somewhat similar problems had been encountered
earlier with the Xlib- libraries for graphics outputs
on Unix systems.
• There solution had been for programmers to
surrender (to code provided with the library) some
the fine control of arrangement of components.
• AWT adopted this approach (swing follows, adds
Layout managers
• When building interface (awt or swing)
– you choose one of a small number of standard
arrangements for subwindows
– you create a “layout manager” object - an instance
of a class that
• keeps track of subwindows and their (minimum) sizes • chooses how to position them in the enclosing window
– you associate this layout manager with the window
It is possible to specify that you do not want to employ a layout manager, and position subwindows yourself. Generally regarded as hacking.Layout managers
• The different “Window” classes (Frame,
Panel/Applet etc) have default layout
managers.
– layout manager actually associated with “container” level in class hierarchy (superclass to window)
• Container has
– setLayout(LayoutManager m)
– add(Component c)
– add(Component c, constraints)
©nabgFlowlayout
Frame with a FlowLayout manager components rearrange if user resizes FrameCanvas No Yes Maybe Canvas No Yes Maybe ©nabg
BorderLayout
• Add components specifying region names
as “constraints” (
forgot the name? put in center)
North South Center E a s t W e s t ©nabg
Advanced Layouts
• GridLayout
(
illustrated later in calculator example)
–
n x m
array of slots for components
– successive add() operations fill out rows
• CardLayout (
not illustrated)
– displays one component from a set,
– functions like first(), next(), previous(), last(), to
cycle through components
©nabg
Advanced Layouts
• GridBagLayout (
illustrated later in dialog example)
– complicated layouts,
best used in conjunction
with an interface builder tool
– grid of cells, but individual components can
occupy different number of cells
©nabg
GridBagLayout
• Component is added to container along with a
“GridBagConstraints” object
• GridBagConstraints specifies
– number of grid cells allocated to component (gridwidth,
gridheight constraint properties)
– position of component within its area defined (achor
property)
– fill property (does component resize to fit display area
horizontally, vertically, or both)
– padding around components (insets and ipadx, ipady)
– how display areas resize if enclosing window changes
©nabg GridBagConstraint x =0, y =0 width = 1, height =2 GridBagConstraint x =0, y =2 width = 3, height =1 GridBagConstraint x =3, y =0 width = 2, height =3 ©nabg
Swing and layouts
• Swing shares all AWT’s standard layouts
• Swing defines a few additional ones
– e.g. BoxLayout
• Better than JPanel (or AWT Panel) for grouping several components and arranging them (vertically or horizontally)
– others like SpringLayout, ViewPortLayout –
see Sun’s examples for use
©nabg
Create your user interface
©nabg
Creating your user interface
• Development environment (
eg NetBeans
) may
provide an editing tool that helps you arrange
parts of your interface
• If you don’t have an editing tool, or you want
more control, you will need to compose the
code that builds your interface
– create components, place within layout managers ...
Create your user interface ©nabg
Be aware of restrictions
• Container may only allow one component
North South Center E a s t W e s t Each of areas, North …Center can be empty or hold one nested component
Use nested containers
North South Center E a s t W e s tYou want two labelled buttons here (4 components)? Have to add a nested Panel (JPanel) container
Create your user interface
Use nested containers
North South Center E a s t W e s t
Overall frame with BorderLayout
Added Panel (JPanel)
(J)Label (J)Button (J)Label (J)Button
Controls added to Panel (which has FlowLayout)
Create your user interface
©nabg
Creating your user interface
• There is a nesting hierarchy
– you choose a layout for top-level frame
• you place a “Panel” as one of components in this frame, (occupying one of positions in its ‘slots’ as defined by chosen layout manager)
– you select a layout for the Panel
• you place other components inside Panel
• This allows complex interfaces with large
output areas, arrays (palettes) of controls,
status information lines etc
Create your user interface ©nabg
Creating your user interface
• Events from controls
– you handle your controls by attaching
“listeners” to them when you create them
Create your user interface
©nabg
Only listener for events you want to
handle
• Things like textboxes, scrollbars, checkboxes etc
generate events for every change.
• Rare for your application to need to be aware of
these changes –
– A text box will look after all editing operations without your intervention.
• Typically you only want final values
• Listen only to the ActionButtons
– when user clicks “Do It Now” button, your application interrogates text boxes, checkboxes, scrollbars etc for chosen values
Create your user interface ©nabg
So, creating an interface
©nabg
Two issues to consider
•
Needs of your application
– GUI’s role
• Input of data • Controls on processing • Output of results
– What are you inputs?
– What processing controls do you need? – What output data must you display?
•
Building blocks available in GUI library
Create your user interface ©nabg
GUI library
• Containers and simple components
• You start with one container
– The Window (Frameor JFrameclass)
• You divide up area of window
– Area for input fields and controls – Area for outputs
• Each such area has many components, so it must
be represented by another container (Panel,
JPanel, Box
or other container used for
sub-window)
Create your user interface
©nabg
GUI interface – first decisions
• Frame’s area is split in areas
– Each area usually occupied by another
container (Panel, whatever)
– Arrangement of areas in main Frame dictated
by a layout manger
Create your user interface ©nabg
GUI interface - next
• Your needs for input data and controls
– Select some processing option?
• Select from pop-up list? • Select using check boxes?
– Text data input?
• Simple text input? • Large area of text?
– Select file?
• Action button displays file dialog
– Start processing
• Action button
Create your user interface
©nabg
Compose input & control elements
• Many input elements?
– “Container” (Panel) used for input elements
must be given some layout manager
– Different input components must be selected to
handle inputs required by application
– Input components must be added to container,
layout manager given “hints” on layout
Create your user interface ©nabg
Outputs
• What are the output data?
• Do you really have one output field or many?
• For each output field
– Can you use one of standard data display classes
• TextArea (possibly scrolling if a lot of text) • Table
• Tree
• How can you arrange outputs
– Container again (Panel) – Layout manager
Building blocks for interfaces
Containers
Containers
• Container
– Panel
• Applet
– ScrollPane
– Window
• Dialog
– FileDialog
• Frame
AWT,javax.swing has JPanel, etc
©nabg
Containers
• Window
– A Window object is a top-level window with no borders and no menubar.
• Frame
– A Frame is a top-level window with title and border; default layout is BorderLayout.
• Dialog
– A window that takes input from the user. – FileDialog
• Mimics “standard” modal file selection dialog as commonly used on platform.
• Panel
– Panel is the simplest container class. A panel provides space in which an application can attach any other component. The default layout manager for a Panel is FlowLayout.
©nabg
Components
• Component
– Button
– Canvas
– Checkbox
– Choice
– Label
– List
– Scrollbar
– TextComponent
• TextArea • TextField AWT,javax.swing has JLabel, etc
©nabg
Components - Button
• Button
– owns two strings (
label, action name; same by default)
• set/get ... …Label(), …ActionCommand() • normal constructor sets both: Button(String s)
– addActionListener(...)
– simple request for action by program (
like earlier example where had North, East, ... buttons that movedfigure that was displayed in Canvas
)
©nabg
class DataObject implements ActionListener { }
class MyCanvas extends Canvas { ... }
class Display implements WindowListener { ...} public class EventDemo1 {
public static void main(String args[]) { ... } } ©nabg
class DataObject {
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
if(s.equals("North")) { fY0 -= 5; fCanvas.repaint(); } ... else if(s.equals("West")) { fX0 -= 5; fCanvas.repaint(); } } ©nabg
class Display
public Display(DataObject d) {fFrame = new Frame();
fFrame.setLayout(new FlowLayout()); fCanvas = new MyCanvas(d);
d.LinkToCanvas(fCanvas); fFrame.add(fCanvas); Button b;
b = new Button("North");
b.addActionListener(d); ... ©nabg
• Component
–
Button
– Canvas
– Checkbox
– Choice
– Label
– List
– Scrollbar
– TextComponent
• TextArea • TextField ©nabgComponents – Canvas
• Canvas (
must be subclassed!
)
– just a blank rectangular drawing area
• paint data objects • trap mouse actions
– typically MyCanvas extends Canvas will add a
pointer to some data object(s) that is(are) to be
displayed, and will override paint()
class MyCanvas extends Canvas {
public MyCanvas(DataObject d) { fData = d; setSize(400, 400); } public void paint(Graphics g) { fData.paint(g); }
private DataObject fData; }
©nabg
Components – Canvas
• Canvas used directly in program?
– You will see textbook examples where programmer
• creates Canvas
• gets Graphics object associated with Canvas • arranges for data structure to draw on Graphics
– I don’t think this is really correct
• it probably won’t handle updates properly (eg when window hidden then re-exposed) - as simply get call to Canvas.paint() { } • violates normal convention of not drawing directly, instead notifying
display of need for update then being asked to draw when display ready
No JCanvas?
•
Swing doesn’t include anything directly
equivalent to Canvas
–
have to subclass JPanel
•provide link to data object
•overwrite paint function
•mess around with setSize, setPreferredSize, and setMinimumSize (JPanels aren’t like Canvases, they try to recompute their sizes based on what they contain and have a habit of shrinking!)
• Component
–
Button
–
Canvas
– Checkbox
– Choice
– Label
– List
– Scrollbar
– TextComponent
• TextArea • TextField ©nabgComponents - Checkbox
• Checkbox handles two roles:
– ordinary check box (a choice that is either
selected or not selected; selection independent of
other choices)
– “radio button” (an instance of a mutually
exclusive set of choices)
• Differentiate roles according to whether
Checkbox has an associated CheckboxGroup
©nabg “Stopwatch” example ©nabg Frame BorderLayout ©nabg FlowLayout South – a Panel Frame East – a Panel FlowLayout BorderLayout
©nabg FlowLayout South – a Panel Frame East – a Panel FlowLayout Canvas BorderLayout ©nabg FlowLayout South – a Panel Frame East – a Panel FlowLayout Canvas Two checkboxes Three buttons BorderLayout ©nabg
Stopwatch
(“ComponentsDemo1”)
• Illustrating
– border layout
• panels (with default flow layout) as subcomponents
– action buttons
– canvas
– mutual exclusion “radio buttons” in a
CheckboxGroup
– also more “Threads” (
to be explained in detail later)
©nabg
import java.awt.*; import java.awt.event.*;
class StopWatch implements ActionListener, ItemListener, Runnable { … }
class MyCanvas extends Canvas { … }
class GUI implements WindowListener { … } public class ComponentsDemo1 {
public static void main(String[] args) { StopWatch c = new StopWatch(); GUI g = new GUI(c);
g.show(); } } ©nabg
ComponentsDemo1 : Application
• ComponentsDemo1
– simply provides main()
• create principal objects • get things run
• MyCanvas
– the usual, subclass Canvas to get something
with effective paint()
– uses double buffered update()
©nabg
ComponentsDemo1 : Application
• GUI
– builds the interface
• create Frame (with default BorderLayout) • create
– MyCanvas, places MyCanvas in center
– three action buttons, panel to hold buttons, places panel in “south”
– two Checkboxes, with CheckboxGroup, another panel to hold them, places panel in “east”
– and handles closing of window by termination
application
ComponentsDemo1 : Application
• StopWatch
– handles
• actions involving stop, start, reset buttons • changes to “Analog” / “Digital” choice items
– has internal thread
• suspended and resumed as needed
• while running does (sleep (1000/60), update ticks
etc, maybe force repaint)
– draws clock in analog or digital form
1000/60 ≈16, don’t expect it to keep perfect timeComponentsDemo1 : Application
• StopWatch
– 60 ticks per second, 60 seconds per minute
– digital display
• as string, • minutes:seconds, • only updated every second
– analog display
• three hands • updated at each tick
©nabg
“Stopwatch” example
©nabg
import java.awt.*; import java.awt.event.*;
class StopWatch implements ActionListener, ItemListener, Runnable { … }
class MyCanvas extends Canvas { … }
class GUI implements WindowListener { … } public class ComponentsDemo1 {
public static void main(String[] args) { StopWatch c = new StopWatch(); GUI g = new GUI(c);
g.show(); }
}
©nabg
class MyCanvas extends Canvas {
public MyCanvas(StopWatch c) { fStopWatch = c; setSize(400, 400); }
public void paint(Graphics g) { fStopWatch.paint(g); }
public void update(Graphics g) {
Graphics gr; if (fOffScreenBuffer==null || (! (fOffScreenBuffer.getWidth(this) == this.getSize().width && fOffScreenBuffer.getHeight(this) == this.getSize().height))){ fOffScreenBuffer = this.createImage( getSize().width,getSize().height); } gr = fOffScreenBuffer.getGraphics();
gr.clearRect(0,0, getSize().width, getSize().height); paint(gr);
g.drawImage(fOffScreenBuffer, 0, 0, this); }
private Image fOffScreenBuffer; private StopWatch fStopWatch; }
uses “double buffering”
Make sure have buffer Use it copy ©nabg
Offscreen buffer code
• Check whether have an offscreen buffer
with the same dimensions as drawing area,
if don’t have one at all (or its size is wrong)
then create offscreen buffer.
• Get a Graphics object associated with the
offscreen buffer.
• “Draw” data using that Graphics.
• Copy completed image to screen
©nabg
Double buffering – why?
•
Problem
–
Your data is changed
–
You must erase the existing display
–
You must draw the new data
•
The screen flickers irritating users.
• Only really an issue if you are composing a picture of your own data and you update this frequently; very rare to have to worry about it if your interface is entirely made up of standard awt/swing classes.
©nabg
Double buffering – how?
•
Create an “image” in memory – one pixel (4
bytes in memory) for each pixel on screen
•
“Erase” the in-memory image
•
Draw into the in-memory image
•
Paint to screen
•
Result – no flicker
©nabg
class GUIimplements WindowListener {
public void windowClosing(WindowEvent e) { System.exit(0); }
public void windowClosed(WindowEvent e) { } public void windowIconified(WindowEvent e) { } public void windowOpened(WindowEvent e) { } public void windowDeiconified(WindowEvent e) { } public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e) { }
public GUI(StopWatch c) { … } public void show() { fFrame.show(); } private Frame fFrame;
private MyCanvas fCanvas; private StopWatch fStopWatch; }
WindowListener stuff as previously illustrated
©nabg
public GUI(StopWatch c) {
fStopWatch = c;
fFrame = new Frame();
fFrame.setLayout(new BorderLayout()); fCanvas = new MyCanvas(c);
c.LinkToCanvas(fCanvas);
fFrame.add(fCanvas, "Center"); Panel p = new Panel();
fFrame.add(p,"South"); Button b; b = new Button("Start"); b.addActionListener(c); p.add(b); b = new Button("Stop"); b.addActionListener(c); p.add(b); b = new Button("Reset"); b.addActionListener(c); p.add(b); …
Setting layout manager explicitly; didn’t need to, BorderLayout is default for Frame
©nabg South – a Panel Frame Canvas fFrame.setLayout(new BorderLayout());ut fCanvas = new MyCanvas(c); c.LinkToCanvas(fCanvas); fFrame.add(fCanvas, "Center");
Panel p = new Panel();
fFrame.add(p,"South"); Button b; b = new Button("Start"); b.addActionListener(c); p.add(b); … ©nabg
GUI building code
• Start with a Frame (a Window with all the
trimmings!)
• Set your layout manager
• Create the canvas class
• Add to the frame – hint to layout manager, this
goes in center
• Two Buttons each with Labels,
– need a Panel to group them
– Create labels and buttons, add to panel, listen to buttons
public GUI(StopWatch c) {
…
b = new Button("Reset"); b.addActionListener(c); p.add(b);
p = new Panel(); fFrame.add(p,"East");
CheckboxGroup grp = new CheckboxGroup();
Checkbox analog = new Checkbox("Analog",
grp, false);false
Checkbox digital = new
Checkbox("Digital", grp, truetrue); p.add(analog); p.add(digital); analog.addItemListener(c); digital.addItemListener(c); fFrame.pack(); fFrame.addWindowListener(this); } South – a Panel Frame East – a Panel Canvas
CheckboxGroup grp = new CheckboxGroup(); Checkbox analog = new Checkbox("Analog",
grp, falsefalse);
Checkbox digital = new Checkbox("Digital",
grp, truetrue);
p.add(analog); p.add(digital);
fFrame.add(p,"East");
©nabg
class StopWatchimplements ActionListener,
ItemListener, Runnable{ public StopWatch() { … }
public void LinkToCanvas(Canvas c) { fCanvas = c; } private void DoStart() {… }
private void DoStop() { … } private void DoReset() { … } public void paint(Graphics g) { … } public void run() { … }
public void itemStateChanged(ItemEvent e) {… } public void actionPerformed(ActionEvent e) { … } Thread fThread;
Canvas fCanvas;
boolean fAnalogStopWatch = false; boolean fRunning = false; int fMinutes, fSeconds, fTicks; }
©nabg
public StopWatch(){
fCanvas = null; DoReset();
fThread = new Thread(this); fThread.start(); }
public void LinkToCanvas(Canvas c) { fCanvas = c; } private void DoStart() {
if(fRunning) return;
fRunning = true; fThread.resume(); }
private void DoStop(){ if(!fRunning) return;
fRunning = false; fThread.suspend(); }
private void DoReset(){ if(fRunning) return;
fMinutes = fSeconds = fTicks = 0; if(fCanvas != null) fCanvas.repaint(); }
©nabg
public void paint(Graphics g) { if(!fAnalogStopWatch) {
String time = "" + fMinutes + ":" + fSeconds; g.drawString(time,40,40); }
else {
g.drawOval(20,20, 181, 181); double angle, armlength, x, y; armlength = 90;
angle = 6.0*fTicks; angle = angle*Math.PI/180.0; x = armlength*Math.sin(angle); y = armlength*Math.cos(angle); g.drawLine(111,111, 111+(int)Math.round(x),111-(int)Math.round(y)); g.setColor(Color.blue); armlength = 70; angle = 6.0*fSeconds; ... g.setColor(Color.red); armlength = 50; angle = 6.0*fMinutes; ... g.setColor(Color.black); } } ©nabg
paint
• Either
– output string with digits
– Draw a “clock face” working out where the
clock-hands should be for minutes, seconds etc
©nabg
public void run() { fThread.suspend(); for(;;) {
try { Thread.sleep(16); }
catch (InterruptedException ie) { } fTicks++; if(fTicks == 60) { fTicks = 0; fSeconds++; if(fSeconds == 60) { fSeconds = 0; fMinutes++; } } if(fAnalogStopWatch) fCanvas.repaint(); else if(fTicks == 0) fCanvas.repaint(); } } ©nabg
Thread
• (More on threads soon)
• Here
– Forever
• Sleep a bit • Update time
• Request repaint of display
©nabg
public void actionPerformed(ActionEvent e) { String s = e.getActionCommand(); if(s.equals("Start")) DoStart(); else if(s.equals("Stop")) DoStop(); else if(s.equals("Reset")) DoReset(); } ©nabg
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.DESELECTED) return;
String s =
(String) e.getItem();
if(s.equals("Analog")) fAnalogStopWatch = true; else fAnalogStopWatch = false;
if(!fRunning) fCanvas.repaint(); }
Will get double notification on change: deselect old, select new. Here only need to bother with the select new.
©nabg
Components - Checkbox;
continued!
• Independent choice Checkboxes used in
much the same way - just don’t provide a
CheckboxGroup.
• Arrange for an ItemListener that will deal
with ItemEvents as these are generated by
changes to individual Checkboxes.
©nabg
•
Component
–
Button
–
Canvas
–
Checkbox
– Choice
– Label
– List
– Scrollbar
– TextComponent
• TextArea • TextFieldComponents - Choice
• “Choice” is an alternative to having an interface
involving a large set of “radio buttons”.
• Choice
– holds a set of items (Strings)
– displays as a form of pop-up menu
– only allows one item to be selected
– sends itemEvents to ItemListener when selection
changed (
though usually easier to handle differently)
– can be asked for current selection
©nabg ©nabg
Components - List
• List is a variation on Choice
– has a little scrolling subwindow showing some of
possible choices (you select how many)
– permits multiple selections (
mechanism depends onplatform – “shift-click”, “control-click”
)
– if single selection, can be asked for current
selection
– if multiple selections permitted, can be asked to
return array with Strings identifying items selected
©nabg
Components - Label
• Lists and Choices do not inherently possess
any identifying information in display.
• Usual to employ Labels to identify them.
• Place Label and Choice (List) in a Panel.
• Label
– displays a non-editable string (can be changed
by program)
©nabg
Example with labels, choices, lists
• “Breakfast order” dialog (
like those printed lists you find inhotel rooms where you tick the items you want for breakfast
)
• No real layout – just a series of choices, lists, text
inputs in a window with FlowLayout
– But trying to keep Label/Choice, Label/List etc together – So do have extra Panel components to hold such pairs
©nabg
Swing
• List => JList
• Choice => JComboBox
• (Some Microsofty person – combo-box was the VisualBasic equivalent)
©nabg
(action) Button Choicefrom pop-up menus (single item)
List(multiple selection enabled, showing 3 items from range of ≈9) Applet using “FlowLayout”
TextAreaused for output (set to ‘non-editable’) Labels ©nabg import java.awt.*; import java.awt.event.*; import java.applet.*;
public class ComponentsDemo2 extends Applet
implements ActionListener
{
public ComponentsDemo2() { ... }
public void actionPerformed(ActionEvent e) {... }
private Choice fChoice1; private Choice fChoice2; private List fList;
private TextArea fTextOutput; }
©nabg
public ComponentsDemo2() {
add(new Label("Pick one item in choices, many in list"));
Button b = new Button("Serve my meal");
add(b); b.addActionListener(this);
Panel p; p = new Panel(); add(p); p.add(new
Label("First course"));
Choice c; c = new Choice();
c.add("Grapefruit"); c.add("Orange juice"); c.add("Melon");
c.add("Corn flakes");
c.select("Corn flakes");
fChoice1 = c; p.add(c);
Can define a default selection
©nabg
Panel p; p = new Panel();
add(p); p.add(new Label("First course"));
Choice c; c = new Choice();
… p.add(c);
©nabg
Creating the elements
• Button
– Give it a label – Add a listener
• Group : Label – “First course”, Choice – with
options
– Create Panel to keep the two together – Create Label with string, add to Panel
– Create choice, create string options in choice, add choice to Panel, add Panel to Applet
...
p = new Panel(); add(p); p.add(new Label("Cooked course"));
List ll = new List(3, true);
ll.add("Boiled egg"); ... ll.add("Toast"); ll.select(0); ll.select(8); fList = ll; p.add(ll);
p = new Panel(); add(p); p.add(new Label("Beverage"));
c = new Choice(); c.add("Tea with lemon"); ... c.add("Coffee");
c.select("Coffee"); fChoice2 = c; p.add(c);
fTextOutput =
new TextArea("Breakfast: ",2, 60); fTextOutput.setEditable(false); add(fTextOutput);
}
Specify number of choices displayed, & whether multi-selections allowed
List & choice
• Generally similar in use
– Different appearance
– List has option of multiple selections
• Here
– Create List object (java.awt.List – a GUI component, not “List” as in datastructures!)
– Add elements (strings for choices offered by list) – Some can be marked as pre-selected
– Add to Panel etc
©nabg
public void actionPerformed(ActionEvent e){ String s = e.getActionCommand();
if(!s.equals("Serve my meal")) return; fTextOutput.append(
fChoice1.getSelectedItem()); fTextOutput.append(", ");
String[] mains = fList.getSelectedItems();
for(int i=0; i<mains.length;i++) { fTextOutput.append(mains[i]); fTextOutput.append(", "); } fTextOutput.append( fChoice2.getSelectedItem()); } ©nabg
actionPerformed
• Only one action button, so don’t need to see
what action requested.
• Read data from input fields.
• Use data to compose output.
• Display output text in TextArea
©nabg
ComponentsDemo2 example
• Approach illustrated is usually easiest
– have an action button to act when user has
made choices
– have references to Choice & List components,
ask for selections when needed
• Alternative implementation implements
ItemListener - get events for each selection
(and deselection)
©nabg
©nabg
NetBeans - awt
private void initComponents() { label1 = new java.awt.Label(); b = new java.awt.Button(); panel1 = new java.awt.Panel(); label2 = new java.awt.Label(); c = new java.awt.Choice(); c.add("Grapefruit"); …
©nabg
NetBeans GUI editor - swing
©nabg
NetBeans swing
• Has extra component editors for things like
tables, combo-boxes, lists
– Let you populate the control with a set of data
• Useful if set of options is fixed
• If generating content of control
dynamically, tell NetBeans to “Reset to
default” and use custom coding
©nabg
•
Component
–
Button
–
Canvas
–
Checkbox
–
Choice
–
List
– Scrollbar
– TextComponent
• TextArea • TextField ©nabgComponents - ScrollPane
• ScrollPane
– A container which implements automatic
horizontal and/or vertical scrolling of a single
child component.
– use
• create a ScrollPane • create a canvas • put canvas in ScrollPane
©nabg
Components - Scrollbar
• Scrollbar
– Allows user to select from a range of values
– Define as “HORIZONTAL” or “VERTICAL”
– Provide minimum, maximum (and initial value)
– Need an AdjustmentListener that will pick up
ComponentsDemo3
• Applet to display a large image such as a
map.
• Image displayed in a ScrollPane.
• Scrollbar used to provide zoom effect
– can scale basic image up or down
– ScrollPane adjusts to resized image
Scrollbars belonging to
ScrollPane (select position in map)
Scrollbar used tochange map’s own scale
©nabg
Effects of scaling the map –
©nabg
ComponentsDemo3
• Simple Applet (implements AdjustmentListener)
– init()
• select BorderLayout, add a label
• load the image (wait for loading to complete, can be slow for large map)
• create “MyCanvas”, ScrollPane, and Scrollbar • establish links amongst items
– adjustmentValueChanged()
• get user selected value (range [1...9], 5=>standard size, 4 is half size, 3 is quarter size, 6 is double size etc) • get “MyCanvas” to rescale
©nabg
import java.awt.*; import java.awt.event.*; import java.applet.*;
class MyCanvas extends Canvas {
public MyCanvas(Image i, ScrollPane s) { ... } public void paint(Graphics g) { ... }
public void setScale(int scl) { ... } // private data
... }
public class ComponentsDemo3 extends Applet implements AdjustmentListener
{
public void init() { ... }}
public void adjustmentValueChanged(AdjustmentEvent e)
{ ... }
private MyCanvas fCanvas; }
©nabg
public class ComponentsDemo3 extends Applet implements AdjustmentListener {
public void init() {
setLayout(new BorderLayout());
add(new Label("Map display", Label.CENTER), "North"); String picture = getParameter("picture");
if(picture == null) return;
Image i = getImage(getDocumentBase(), picture); MediaTracker waitForIt = new MediaTracker(this); waitForIt.addImage(i, 1);
try { waitForIt.waitForID(1); } catch (InterruptedException ie) { } ScrollPane s = new ScrollPane(
ScrollPane.SCROLLBARS_AS_NEEDED); fCanvas = new MyCanvas(i, s);
s.add(fCanvas); s.setSize(400,400); add(s, "Center");
Scrollbar b = new Scrollbar(
Scrollbar.HORIZONTAL, 5, 1, 1, 10); add(b, "South"); b.addAdjustmentListener(this); }
©nabg
Creating the scrollable canvas
• Create scroll pane, specifying it is to use scrollbars
only when needed
• Add canvas
• Set size for display in applet
ScrollPane s = new ScrollPane(
ScrollPane.SCROLLBARS_AS_NEEDED);
fCanvas = new MyCanvas(i, s);
s.add(fCanvas); s.setSize(400,400);
©nabg
public void adjustmentValueChanged(AdjustmentEvent e) {
int val = e.getValue(); fCanvas.setScale(val); }
©nabg
class MyCanvas extends Canvas {
public MyCanvas(Image i, ScrollPane s) { fImage = i; fSPane = s;
fEX= fX = i.getWidth(this); fEY = fY = i.getHeight(this);
setSize(fX, fY); }
public void paint(Graphics g) {
g.drawImage(fImage, 0, 0, fEX, fEY, this); } public void setScale(int scl) {... } private ScrollPane fSPane;
private int fScale = 5; private int fX, fY; private int fEX, fEY; private Image fImage; }
©nabg
public void setScale(int scl) { fScale = scl;
int posX = fSPane.getScrollPosition().x; int posY = fSPane.getScrollPosition().y; int oldfEX = fEX; int oldfEY = fEY; switch(scl) {
case 1: fEX = fX/16 ; fEY = fY/16 ; break; ...
case 9: fEX = fX*16; fEY = fY*16 ; break; }
setSize(fEX, fEY); fSPane.doLayout();
posX = (posX*fEX) / oldfEX; posY = (posY*fEY) / oldfEY;
fSPane.setScrollPosition(posX, posY); repaint(); } ©nabg
•
Component
–
Button
–
Canvas
–
Checkbox
–
Choice
–
List
–
Scrollbar
– TextComponent
• TextArea • TextField ©nabgTextComponents
• TextComponent
– owns text, by default is editable
– does
• return current text as String • set insertion point
• select subset of text (by program) • get current selection (as made by user) • can pass on details of changes to text to a