A close look at the Graphics class and the drawing primitives it provides, and a demonstration of its use
A variety of factors inspire people to write software programs. I believe that for many, motivation springs from a desire to create graphics, to manipulate images, or to animate. Whether they want to create arcade games, flight simulators, or CAD packages, developers often begin by learning to draw.
The graphics toolbox within the Abstract Windowing Toolkit (or AWT) makes it possible for a Java programmer to draw simple geometric shapes, print text, and position images within the borders of a component, such as a frame, panel, or canvas.
This column is my first on the topic of graphics. It will focus on the Graphics class and its methods for drawing simple geometric shapes, and will introduce the process by which painting (and repainting) occurs.
Let's begin at center stage -- the Graphics class.
The Graphics class
It's essential that programmers understand the Graphics class before they attempt to draw images via Java. The Graphics class provides the framework for all graphics operations within the AWT. It plays two different, but related, roles. First, it is the graphics context. The graphics context is information that will affect drawing operations. This includes the background and foreground colors, the font, and the location and dimensions of the clipping rectangle (the region of a component in which graphics can be drawn). It even includes information about the eventual destination of the graphics operations themselves (screen or image). Second, the Graphics class provides methods for drawing simple geometric shapes, text, and images to the graphics destination. All output to the graphics destination occurs via an invocation of one of these methods.
In order to draw, a program requires a valid graphics context (represented by an instance of the Graphics class). Because the Graphics class is an abstract base class, it cannot be instantiated directly. An instance is typically created by a component, and handed to the program as an argument to a component's update() and paint() methods. These two methods, along with the repaint() method, are discussed in the next section.
The methods
The following three methods are involved in displaying graphics. Default versions of each are provided by class Component. Methods update() and paint() should be redefined to perform the desired graphics operations.
repaint()
public void repaint() public void repaint(long tm) public void repaint(int x, int y, int w, int h) public void repaint(long tm, int x, int y, int w, int h)
The repaint() method requests that a component be repainted. The caller may request that repainting occur as soon as possible, or may specify a period of time in milliseconds. If a period of time is specified, the painting operation will occur before the period of time elapses. The caller may also specify that only a portion of a component be repainted. This technique is useful if the paint operation is time-consuming, and only a portion of the display needs repainting. The code in Listing 1 illustrates how the repaint() method might be used in a program.
boolean mouseDown(Event e, int x, int y) { selected_object.move(x, y); repaint(); }
Listing 1: Mouse-down event handler
The code in the mouseDown() event handler recalculates the position of an object in a display based on the position of the mouse and calls the repaint() method to indicate that the display should be repainted as soon as possible.
update()
public void update(Graphics g)
The update() method is called in response to a repaint() request, or in response to a portion of the component being uncovered or displayed for the first time. The method's sole argument is an instance of the Graphics class. The Graphics instance is valid only within the context of the update() method (and any methods it calls), but is disposed of soon after the update() method returns. The default implementation provided by the Component class erases the background and calls the paint() method (below).
paint()
public void paint(Graphics g)
The paint() method is called from an update() method, and is responsible for actually drawing the graphics. The method's sole argument is an instance of the Graphics class. The default implementation provided by class Component does nothing.
How components are repainted
To reduce the time required to repaint the display, the AWT takes two shortcuts:
First, the AWT repaints only those components that need repainting, either because they have been uncovered, or because they asked to be repainted.
Second, if a component was covered and is uncovered, the AWT repaints only the portion of the component that was previously covered.
The applet in Figure 1 allows you to observe this process as it occurs. Ignore the text area at the top of the applet for a moment, and watch only the colored portion of the display. Using another window, momentarily cover and then uncover part of the applet. Notice that only the portion of the applet that was covered is repainted. Furthermore, only those components that were covered are repainted, no matter what their position in the component hierarchy. By deliberately using different colors, the applet makes this subtle effect noticeable. The source code for this figure is available here.
Todd Sundsted has been writing programs since
computers became available in desktop models. Though originally
interested in building distributed object applications in C++, Todd
moved to the Java programming language when Java became the obvious
choice for that sort of thing. In addition to writing, Todd
provides Internet and Web consulting services to companies in the
southeastern United States. :END_BIO
This story, "Using the Graphics class" was originally published by
JavaWorld.