Given by Nancy J. McCracken,Geoffrey C. Fox at CEWES Tutorial on July 22-25 1997. Foils prepared 19 July 97
Outside Index
Summary of Material
In Part 1 and 2 of the Tutorial We Covered:
|
In This Part of the Java Tutorial We Cover: |
Introduction to Threads |
Graphics in more detail
|
Abstract Windowing Toolkit
|
And in the Remaining Part of the Java Tutorial We Cover:
|
Outside Index Summary of Material
Instructors: Geoffrey Fox , |
Nancy McCracken |
Syracuse University |
111 College Place |
Syracuse |
New York 13244-4100 |
java.awt has several important classes including Graphics, Color, Font and FontMetrics |
Graphics class has primitives to construct basic two dimensional images with methods |
drawString (text), drawLine, |
drawArc, fillArc, drawRect, fillRect, drawOval, fillOval, drawRoundRect (for a rectangle with rounded corners!), draw3DRect (to get shadow effect as in buttons), drawPolygon (general polygon) (and fill versions of last 3) |
There are also Image, Font, Color operations |
In every applet or windows application, the windowing system creates an Image with a Graphics object to keep track of the state of the window. |
In order to draw or write text to the window, you must override the paint method:
|
In this method you put everything you want to draw in the window. The Graphics object g has things like a current color and current font, and there are methods for you to change these as well as draw. |
The window system can be interrupted for various reasons - the user resized it or some other window was put on top of it and then removed - and it does not save a copy of the pixels. Instead it calls a method called update, which blanks the screen and then calls paint(g). So even if you only draw one window, paint can be called many times. |
Most applets and windows applications want to change what is drawn on the screen over its lifetime. This can be a sequenced animation, response to user input or mouse events, and so on. |
Whenever you want to redraw the screen, call
|
Repaint gets the graphics context and creates a thread to call update, which calls your paint function. So all your drawing changes can also be put into paint. |
One draws a sequence of text and shapes to define the screen, where the position of the object in the screen is given by pixel coordinates. If one object overlaps another, the latest one drawn covers up the area of overlap.
|
Graphicsinstance.setFont(particularFont) will set the current Font in the instance Graphicsinstance of graphics class to the value particularFont of class Font. There are several other such Font related methods in the Graphics class |
The class Font has an important constructor used as in |
Font MyFont = new Font("TimesRoman", Font.PLAIN ,36);
|
FontMetrics fm = getFontMetrics(particularFont); // allows one to find out about the font
|
The method applet.size() returns a dimension object, which has width and height variables. FontMetrics has variables for various attributes of the font, including width and height. |
Color c = new Color (redvalue, greenvalue, bluevalue); // red/green/bluevalue can be specified as integers in 0.....255 or floating point numbers from 0 to 1. |
c is generated as a Color in RGB format. |
graphicsobject.setColor(c); // sets current color in graphicsobject which is used for all subsequent operations |
graphicsobject.setFont(particularFont); // similarily sets font hereafter as on previous page |
There are particular Color instances already defined such as |
Color.white equivalent to Color(255,255,255) |
Color.black as equivalent to Color(0,0,0) |
Color.pink as equivalent to Color(255,175,175) |
A thread is a single sequential flow of control within a process. |
If a process has more than one thread, then each thread executes concurrently. |
Any Java applet which has extensive execution or loops to repaint the window must run as a concurrent thread with the browser window. |
To make an applet with a thread, which is almost always recommended:
|
These applet start and stop methods can always be used to start and stop the thread. |
The body of the applet is in the run method, in this case a loop to keep showing the date. |
The Applet class provides a method getImage, which retrieves an image from a web server and creates an instance of the Image class. |
Image img = getImage(new URL("http://www.tc.com/image.gif")); |
Another form of getImage retrieves the image file relative to the directory of the HTML or the directory of the java code. |
Image img = getImage(getDocumentBase(), "images/image.gif"); |
Image img = getImage(getCodeBase(), "images/image.gif"); |
The Graphics class provides a method drawImage to actually display the image on the browser screen. |
You can also scale the image to a particular width and height. |
When drawImage is called, it draws only the pixels of the image that are already available. |
Then it creates a thread for the imageObserver. Whenever more of the image becomes available, it activates the method imageUpdate, which in turn which call paint and drawImage, so that more of the image should show on the screen. |
The default imageUpdate doesn't work if you are double buffering the window in which the image appears. |
More control over showing the image as it downloads can be obtained by working with the MediaTracker class, using methods which can tell you when the image has fully arrived.
|
This example shows how to get the actual height and width of the image to use in scaling the image under java program control. |
Unless you are careful, dynamic applets will give flickering screens |
This is due to cycle |
paint(g) |
update(g) clearing screen |
paint(g) drawing new screen ..... |
where flicker caused by rapid clear-paint cycle. |
There are two ways to solve this problem which involve changing update in different ways
|
This sets background color and initializes applet bounding rectangle to this color
|
getBackground() and getForeground() are methods in component class |
fillRect() is a method in Graphics class |
Here you have two "graphics contexts" (frame buffers of the size of the applet), and you construct the next image for an animation "off-line" in the second frame buffer. |
This frame buffer is then directly copied to the main applet Graphics object without clearing image as in default update() |
In init(), you would create the frame buffer:
|
In paint(), one will construct applet image in offscreenGraphics as opposed to the argument g of paint(). So one would see statements such as:
|
Finally at end of paint(), one could transfer the off-screen image to g by
|
One would also need to override the update() method by |
public void update(Graphics g) {
|
This technique is most effective in eliminating flicker, but does take longer and use more memory. |
Events ( distinguish these from Exceptions!) are the way the AWT interacts with the user at mouse or keyboard. |
The AWT calls particular event handlers (analogous to exception or interrupt handlers) when user interacts with system in particular ways. |
The handling is defined in packages java.awt and java.awt.peer (the machine dependent stuff) with method handleEvent() in class Component(peer) |
One could add additional capability here for systems with nifty virtual reality and other user interfaces but we won't cover this here! |
The Event class has various special class (static) variables defined including
|
The Component class (grandparent of Applet) has a rich set of Event handlers which you should override if you wish to process particular input. In this section, we cover the keyboard and mouse events which are reported to subclass Canvas (used for Graphics) |
public boolean mouseDown(Event evt, int x, int y) {
|
Other handlers are mouseDrag, mouseEnter (enters current component), mouseExit, mouseMove (with its button up), keyUp, keyDown |
We set up a test program that creates 3 movable objects, a rectangle, circle and triangle, as in the earlier example. In this program, we start with them all red. Whenever the mouse is detected to be over one of the objects, its color is changed to cyan. If the mouse button is used to drag the object, we move the object to the mouse location. |
Note that it is not necessary to introduce a thread for this applet since it is not running continuously - it is mostly waiting for mouse events. |
In this example, update does all the drawing. It also sets a background color rectangle with a 1 pixel border in the foreground color. |
Whenever the user moves the mouse, a message is sent from the client workstation to the Java system. It generates a form of interrupt called an event. Your Java applet can choose to provide a method which does appropriate response for any event. This is called an event handler - you must return true to show the general event handler that you have intervened. |
These handle the sequence of: the user clicks the mouse (mouse down), moves the mouse (mouse drag) and releases the mouse button (mouse up). |
We add methods to detect when the mouse is inside an object, and a more general method moveTo for large moves under dragging. |
You may also choose to respond to individual keys being pressed from the keyboard. (Later we will learn of a more general way to handle text input.) |
In Java, the GUI (Graphical User Interface) is built hierarchically in terms of Components -- one Component nested inside another starting with the smallest Buttons, including Menus, TextFields etc. and ending with full Window divided into Frames, MenuBars etc. |
Not all useful Classes are inherited from Component. For instance Menu inherits from MenuComponent (interface) --> MenuItem --> Menu |
One also needs a set of methods and classes to define the layout of the Components in a particular Panel |
LayoutManager is a java.awt interface with several particular layout strategies implemented as classes under this interface |
The Container class has methods to interact with LayoutManager classes |
In the simplest use of AWT, one could add a Button to an Applet (grandchild of Container) using in the init() method for Applet
|
The various added Components are put in the panel by the LayoutManager using order in which they were added |
A Final critical part of the AWT is the actions generated by these components which are processed by overriding the action() method in Component
|
We define extra events -- such as those connected with scrolling or selecting buttons to those of basic mouse/keyboard |
This is incomplete! |
add(new Label("aligned left")); // default alignment |
produces a text string using constructor Label of Label class |
add(new Button("Grade is A")); |
add(new Button("Grade is B")); // surely this is lowest grade for a course on such an easy language? |
Checkbox's are on-off toggles implemented as |
add(new Checkbox("Red")); |
add(new Checkbox("Green")); |
add(new Checkbox("Blue"),null, true); |
The first two are initially set to "false" as the optional third argument is not given. The last one is initially set to "true". |
The state of a checkbox, i.e. whether it is checked, is given by the method, getState: |
Checkbox cb = new Checkbox("Red"); |
add (cb); |
. . . |
if (cb.getState()) . . .; |
Radio buttons are identical to Checkbox's but grouped so that only one checkbox in a group can be on at a time. They use same class for buttons but add CheckboxGroup class |
CheckboxGroup cbg = new CheckboxGroup(); |
cb1 = new Checkbox("Red", cbg, false)); |
cb2 = new Checkbox("Green", cbg, false)); |
cb3 = new Checkbox("Blue", cbg, true)); |
add(cb1); add(cb2); add(cb3); |
In addition to checking the state of checkboxes in a group, the method getCurrent returns the one checkbox which is on:
|
We already discussed handling Mouse and Keyboard Events. These AWT components come with new actions which need to be handled with an action() method in your applet (and a few events which are reported directly to handlevent().) |
Put action ( a method of class Component) in Container instance that is at lowest possible level so you can customize action to things in that Container |
action(Event evt, Object arg)'s are looked for in same fashion as exceptions. Scan up Containers looking for a method of this name. Scanning stops when you find an action and that method returns true |
evt.target holds the object that caused the Event |
Object Arg returned depends on particular Component invoked |
There are further evt.id's associated with the various peculiar Components -- see description of class Event for current detailed description. |
Suppose we have a bunch of buttons in a particular Container saying Red, Green, Blue as we illustrated earlier. Then an action method would be
|
In general, declare names for all components such as labels, buttons and textfields, and use the variable evt.target to distinguish which component generated the action. |
Choice is a class that gives a menu where you choose from various items |
TextField is a simple class where user can enter information into fields (more details on next page) |
TextArea is a somewhat more sophisticated text entry area which are scrollable and so useful where amount of data to be entered is unlimited |
List is another child of Component that is similar in use to Choice but gives a fixed size list which can be scrolled and where you can select one or more entries |
Scrollbar is a class that defines a horizontal or vertical scrollbar. Note this is distinct from scrollbars that come with TextArea and List |
To add a text field for display or input one line of text (in this case, 30 characters wide):
|
The text which is displayed can be changed:
|
If the user can type input into the text field, it can be obtained:
|
Or you can disallow the user to type:
|
The TextArea class also has these methods, but it can display multiple lines. |
Canvas is a simple class which are used to draw on as in artist's canvas. They cannot contain other components. This is the class on which you use the graphics methods. |
Upto now, we have described how to build typical Applet panels inside browser window. There are classes that allow one to generate complete windows separately from the browser window |
Window Class has subclasses Frame and Dialog |
Frame("TitleofWindow"); // creates a window with given title
|
A Frame has a set of classes to define MenuBars and Menus:
|
Another type of separate window is the Dialog box, which is not so elaborate as a frame.
|
Dialog boxes are used for transient data
|
The various panels in a container are laid out separately in terms of their subcomponents |
One can lay components out "by hand" with positioning in pixel space |
However this is very difficult to make machine independent. Thus one tends to use general strategies which are embodied in 5 LayoutMangers which all implement the LayoutManager Interface. One can expect further custom LayoutManager's to become available on the Web |
setLayout(new FlowLayout()); // creates a basic flow layout in your panel -- actually unnecessary as default |
Other available LayoutManager's are GridLayout(), BorderLayout() (default for Frame's), CardLayout() (Used for dynamic layouts) and GridBagLayout() (the most flexible) |
BorderLayout has five cells called North South East West Center and components are assigned to these cells with the add method. As used in a window, one would naturally use:
|
Remember this is default for a Frame Container |
FlowLayout is a one dimensional layout where components are "flowed" into panel in order they were defined. When a row is full up, it is wrapped onto next row |
GridLayout is a two dimensional layout where you define a N by M set of cells and again the components are assigned sequentially to cells starting at top left hand corner -- one component is in each cell |
GridBagLayout uses a new class GridBagConstraints to customize positioning of individual components in one or more cells |
CardLayout lays out in time not space and each card (Displayed at one time) can be laid out with one of spatial layout schemes above |
This simple layout manager starts putting components in the window from the top left, continues across the row until there is no more room, starts the next row, and so on. The components can be aligned, and space between them given by the arguments hgap and vgap. |
setLayout(new FlowLayout(FlowLayout.LEFT, 5, 1); |
setLayout(new FlowLayout(FlowLayout.CENTER); |
setLayout(new FlowLayout(FlowLayout.RIGHT); |
Layout's can be made very sophisticated using an hierarchical approach |
setLayout(new GridLayout(1,3,10,5));
|
subpanel1 = new MysubpanelClass(); // Add arguments to make subpanel1 special |
subpanel2 = new MysubpanelClass(); |
add(Some Simple Component such as a Button); |
add(subpanel1); |
add(subpanel2); |
. . . . . |
Class MysubpanelClass extends panel { // has constructor |
MysubpanelClass() { // that includes another layout such as |
setLayout(new GridLayout(2,2,5,5); // etc. |
A simple example of using the Abstract Windowing Toolkit divides the applet space into two components. One is a Canvas for drawing graphics or images; one is a Panel which has three buttons. We choose to draw the Canvas within the Applet and to create the Panel in another class. |
At top level, the panel is divided into two components. |
The initialization of the Canvas was done in the applet init method; the other method for painting the Canvas simply changes the background color. About the only thing a Canvas can do is explicit drawing and graphics. |
This class does not need to be a subclass of Applet - like all components except Canvas, you don't need to paint, just add components and handle events and actions. |
The Button component generates an action whenever the button is clicked on. In this example, we call the method that changes the color of the Canvas in another part of the layout. |