Working with Graphics |
The Graphics class defines methods for drawing the following kinds of shapes:Except for polygons and lines, all shapes are specified using their bounding rectangle. Once you understand rectangles, drawing other shapes is relatively easy. For this reason, this page concentrates on rectangle drawing.
- Lines (
drawLine()
, which draws a line in the Graphics object's current color, which is initialized to the Component's foreground color)- Rectangles (
drawRect()
,fillRect()
, andclearRect()
-- wherefillRect()
fills a rectangle with the Graphics object's current color, andclearRect()
fills a rectangle with the Component's background color)- Raised or lowered rectangles (
draw3DRect()
andfill3DRect()
)- Round-edged rectangles (
drawRoundRect()
andfillRoundRect()
)- Ovals (
drawOval()
andfillOval()
)- Arcs (
drawArc()
andfillArc()
)- Polygons (
drawPolygon()
andfillPolygon()
)Example 1: Simple Rectangle Drawing
The applet on the previous page used thedraw3DRect()
andfillRect()
methods to draw its interface. Here's the applet again:
Below is just the drawing code:
Note: Because some old browsers don't support 1.1, the above applet is a 1.0 version (here is the 1.0 code; here's the 1.1 code). To run the 1.1 version of the applet, go toexample-1dot1/CoordinatesDemo.html
.The applet creates (and contains) a FramedArea object, which in turn creates (and contains) a CoordinateArea object. The first call to//In FramedArea (a Panel subclass): public void paint(Graphics g) { Dimension d = size(); Color bg = getBackground(); //Draw a fancy frame around the applet. g.setColor(bg); g.draw3DRect(0, 0, d.width - 1, d.height - 1, true); g.draw3DRect(3, 3, d.width - 7, d.height - 7, false); } //In CoordinateArea (a Canvas subclass): public void paint(Graphics g) { //If user has clicked, paint a tiny rectangle where click occurred if (point != null) { g.fillRect(point.x - 1, point.y - 1, 2, 2); } }draw3DRect()
creates a rectangle as big as the FramedArea's drawing area. Thetrue
argument specifies that the rectangle should appear to be raised. The second call todraw3DRect()
creates a second rectangle just a bit smaller, withfalse
specifying that the rectangle should appear to be sunken. Together, the two calls produce the effect of a raised frame that contains the CoordinateArea. (FramedArea implements theinsets()
method so that the CoordinateArea's drawing area is a few pixels inside of the FramedArea.)The CoordinateArea uses
fillRect()
to draw a two-by-two-pixel rectangle at the point that the user clicks.Example 2: Using a Rectangle to Indicate a Selected Area
Here's an applet that you could use as a basis for implementing selection in a drawing program. When the user drags the mouse, the applet continuously displays a rectangle. The rectangle starts at the cursor position where the user first pressed the mouse button and ends at the current cursor position.
Note: Because some old browsers don't support 1.1, the above applet is a 1.0 version (here is the 1.0 code; here's the 1.1 code). To run the 1.1 version of the applet, go toexample-1dot1/RectangleDemo.html
.Below is the significant new code:
As you can see, the SelectionArea keeps track of the currently selected rectangle, using a Rectangle object calledclass SelectionArea extends Canvas { . . . public boolean mouseDown(Event event, int x, int y) { currentRect = new Rectangle(x, y, 0, 0); repaint(); return false; } public boolean mouseDrag(Event event, int x, int y) { currentRect.resize(x - currentRect.x, y - currentRect.y); repaint(); return false; } public boolean mouseUp(Event event, int x, int y) { currentRect.resize(x - currentRect.x, y - currentRect.y); repaint(); return false; } public void paint(Graphics g) { Dimension d = size(); //If currentRect exists, paint a rectangle on top. if (currentRect != null) { Rectangle box = getDrawableRect(currentRect, d); controller.rectChanged(box); //Draw the box outline. g.drawRect(box.x, box.y, box.width - 1, box.height - 1); } } Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) { . . . //Make sure rectangle width and height are positive. . . . //The rectangle shouldn't extend past the drawing area. . . . } }currentRect
. As implemented, thecurrentRect
keeps the same origin (currentRect.x
,currentRect.y
) for as long as the user drags the mouse. This means that the height and width of the rectangle can be negative.However, the
drawXxx()
andfillXxx()
methods don't draw anything if either the height or width is negative. For this reason, when the SelectionArea draws the rectangle, it must specify the upper left vertex of the rectangle so that the width and height are positive. The SelectionArea class defines agetDrawableRect()
method to perform the necessary calculations to find the upper left vertex. ThegetDrawableRect()
method also makes sure that the rectangle doesn't extend beyond the boundaries of its drawing area. Here, again is a link to the source code. You'll find the definition ofgetDrawableRect()
at the bottom of the file.Note: It's perfectly legal to specify x, y, height, or width values that are negative or cause a result larger than the drawing area. Values outside the drawing area don't matter too much because they're clipped to the drawing area. You just won't see part of the shape. Negative height or width results in the shape not being drawn at all.
Example 3: A Shape Sampler
The following applet demonstrates all the shapes you can draw and fill.
Unless your applet viewer's default font is very small, the text displayed in the above applet might look ugly in places. Words might be drawn on top of each other. And because this applet doesn't use the
Note: Because some old browsers don't support 1.1, the above applet is a 1.0 version (here is the 1.0 code; here's the 1.1 code). To run the 1.1 version of the applet, go toexample-1dot1/ShapesDemo.html
.insets()
method to protect its boundaries, text might be drawn on top of the frame around the applet. The next page improves on this example, teaching you how to make sure text fits within a given space.Here's just the code that draws the geometric shapes. The
rectHeight
andrectWidth
variables specify the size in pixels of the area each shape must be drawn in. Thex
andy
variables are changed for every shape, so that the shapes aren't drawn on top of each other.Color bg = getBackground(); Color fg = getForeground(); . . . // drawLine() g.drawLine(x, y+rectHeight-1, x + rectWidth, y); // x1, y1, x2, y2 . . . // drawRect() g.drawRect(x, y, rectWidth, rectHeight); // x, y, width, height . . . // draw3DRect() g.setColor(bg); g.draw3DRect(x, y, rectWidth, rectHeight, true); g.setColor(fg); . . . // drawRoundRect() g.drawRoundRect(x, y, rectWidth, rectHeight, 10, 10); // x, y, w, h, arcw, arch . . . // drawOval() g.drawOval(x, y, rectWidth, rectHeight); // x, y, w, h . . . // drawArc() g.drawArc(x, y, rectWidth, rectHeight, 90, 135); // x, y, w, h . . . // drawPolygon() Polygon polygon = new Polygon(); polygon.addPoint(x, y); polygon.addPoint(x+rectWidth, y+rectHeight); polygon.addPoint(x, y+rectHeight); polygon.addPoint(x+rectWidth, y); //polygon.addPoint(x, y); //don't complete; fill will, draw won't g.drawPolygon(polygon); . . . // fillRect() g.fillRect(x, y, rectWidth, rectHeight); // x, y, width, height . . . // fill3DRect() g.setColor(bg); g.fill3DRect(x, y, rectWidth, rectHeight, true); g.setColor(fg); . . . // fillRoundRect() g.fillRoundRect(x, y, rectWidth, rectHeight, 10, 10); // x, y, w, h, arcw, arch . . . // fillOval() g.fillOval(x, y, rectWidth, rectHeight); // x, y, w, h . . . // fillArc() g.fillArc(x, y, rectWidth, rectHeight, 90, 135); // x, y, w, h . . . // fillPolygon() Polygon filledPolygon = new Polygon(); filledPolygon.addPoint(x, y); filledPolygon.addPoint(x+rectWidth, y+rectHeight); filledPolygon.addPoint(x, y+rectHeight); filledPolygon.addPoint(x+rectWidth, y); //filledPolygon.addPoint(x, y); g.fillPolygon(filledPolygon);
Working with Graphics |