Painting


There are many reasons why a frame's contents may need to be redrawn:

  • The frame has become visible for the first time.

  • The contents have changed due to user input (as when you moved a scrollbar in Color Lab).

  • The frame has deiconified.

  • The frame has moved to the front of the desktop, after having been covered or partially covered by another frame.

When any of these occur, the underlying windowing software notifies the frame, and a call is made to the frame's paint() method. The great thing about this arrangement is that you never have to detect these changes to the frame. The environment takes care of all that for you. All you have to do is subclass Frame and provide a paint() method that draws the frame's interior. In other words, you have to think about what to paint, but you don't have to think about when to paint.

When the environment decides that a frame needs painting, the frame's interior is cleared to its background color. By default, the background color is white. But as you saw in the previous section, you can call setBackground() to set any background color you like. After that, the environment calls the frame's paint() method. The paint() version inherited from Frame does nothing at all. You are about to learn how to override paint() so that it does interesting things.

The argument of paint() is an instance of java.awt.Graphics. You might hear people call this object a graphics context, but it's more correct to call it a graphics object, and that is the name we will use. The graphics object is like an artist with a paintbrush, ready to paint the interior of a frame. It isn't a very talented artist (it only knows how to draw a few shapes), but it's very accurate. And as you'll see, it has excellent penmanship. You never have to construct an instance of Graphics; that's done for you by the environment. You just have to tell it what to paint.

An artist at work dips his brush in paint, brushes the paint onto paper, dips, brushes, and so on. The color that goes on the paper is, of course, the last color that the brush was dipped into. A graphics object works the same way. It has a method called setColor(), whose argument is a Color. It also has methods that draw shapes, including lines, rectangles, circles, and text messages. The shapes appear in the color that was the argument of the most recent setColor() call. So you can see that calling setColor() is like dipping your paintbrush into new paint. Another way to think of it is this: When you call setColor(), you set the color of all shapes to be drawn until the next setColor() call.

Now let's take a look at the different shapes that a graphics object can paint.

Drawing and Filling with a Graphics Object

The shapes that you can draw with the Graphics class include the following:

  • Lines

  • Squares and rectangles

  • Circles and ovals

There are also methods that fill the interior of a square, rectangle, circle, or oval. All drawing happens in the color of the most recent setColor() method, as you saw in the previous section. The methods have varying arguments that specify the size and location of the shape. All arrays are in units of pixels, not inches or millimeters. Horizontal positions are always called x, and are measured from the left edge of the frame. Vertical positions are called y, and are measured from the top of the frame. The location of a point is denoted by (x, y), as shown in Figure 14.4.

click to expand
Figure 14.4: Pixel coordinates

The point at (0, 0) is called the origin. A frame's origin is its top-left pixel. Note that x increases from left to right, and y increases from top to bottom. This is different from the Cartesian coordinates that you may have learned about in school, where y increases upward. The y-increases-downward scheme is standard in graphical programming, and it often causes confusion until people get used to it. It probably got its start in word-processing software, where line numbers increase from the top to the bottom of a document. Whatever its derivation might be, the scheme is here to stay.

To draw a line from (x0, y0) to (x1, y1), call the following on your graphics object:

drawLine(x0, y0, x1, y1);

The following code displays a frame with a black line on a white background:

1. import java.awt.*;  2.  3. public class BlackLineOnWhite extends Frame  4. {  5.   BlackLineOnWhite()  6.   {  7.     setSize(150, 180);  8.   }  9. 10.   public void paint(Graphics g) 11.   { 12.     g.setColor(Color.black); 13.     g.drawLine(60, 115, 120, 70); 14.   } 15. 16.   public static void main(String[] args) 17.   { 18.     BlackLineOnWhite blonw = new BlackLineOnWhite(); 19.     blonw.setVisible(true); 20.   } 21. }

Figure 14.5 shows the frame.


Figure 14.5: A black line on a white background

The constructor just sets the frame's size. There's no need to set the background color explicitly, since you want the white default. Line 12 actually isn't required, because when paint() is called, the graphics object is set up to draw in black automatically.

To draw a rectangle, call the drawRect() method. Its four arguments are the x, y, width, and height of the rectangle, where (x, y) is the location of the rectangle's upper-left corner. The following code draws a blue rectangle that is 100 pixels wide by 35 pixels high, with its upper-left corner at (25, 50):

 1. import java.awt.*;  2.  3. public class BlueRect extends Frame  4. {  5.   BlueRect ()  6.   {  7.     setSize(150, 180);  8.   }  9. 10.   public void paint(Graphics g) 11.   { 12.     g.setColor(Color.blue); 13.     g.drawRect(25, 50, 100, 35); 14.   } 15. 16.   public static void main(String[] args) 17.   { 18.     BlueRect br = new BlueRect(); 19.     br.setVisible(true); 20.   } 21. }

Figure 14.6 shows the frame.


Figure 14.6: A rectangle

There is no separate method for drawing a square. You just call drawRect() with equal values for the width and height.

To draw an oval, you call drawOval() and specify the oval's bounding box. A bounding box is the smallest rectangle that encloses the oval. Figure 14.7 shows several ovals and their bounding boxes.

click to expand
Figure 14.7: Ovals and bounding boxes

Notice that one of the shapes in Figure 14.7 looks like a circle, not an oval. Actually, a circle is a kind of oval whose bounding box is a square.

The following code draws three ovals (shown in Figure 14.8), one of which is a circle:

 1. import java.awt.*;  2.  3. public class ThreeOvals extends Frame  4. {  5.   ThreeOvals ()  6.   {  7.     setSize(150, 220);  8.   }  9. 10.   public void paint(Graphics g) 11.   { 12.     g.setColor(Color.black); 13.     g.drawOval(20, 40, 100, 35); 14.     g.drawOval(20, 85, 50, 60); 15.     g.drawOval(90, 105, 25, 25); 16.   } 17. 18.   public static void main(String[] args) 19.   { 20.     ThreeOvals throv = new ThreeOvals (); 21.     throv.setVisible(true); 22.   } 23. } 


Figure 14.8: Three ovals

In the drawOval() calls, the arguments are the x, y, width, and height of the bounding box. Notice that in line 15, which draws the circle, the width and height are the same.

The fillRect() method draws a rectangle and fills its interior. The fillOval() method draws an oval and fills its interior. The following code displays two filled ovals and a filled rectangle:

 1. import java.awt.*;  2.  3. public class Filled extends Frame  4. {  5.   Filled ()  6.   {  7.     setSize(200, 150);  8.   }  9. 10.   public void paint(Graphics g) 11.   { 12.     g.setColor(Color.black); 13.     g.fillOval(20, 50, 50, 20); 14.     g.fillRect(90, 40, 20, 70); 15.     g.fillOval(130, 50, 50, 20); 16.   } 17. 18.   public static void main(String[] args) 19.   { 20.     Filled f = new Filled(); 21.     f.setVisible(true); 22.   } 23. }

The result is shown in Figure 14.9.


Figure 14.9: Filled rectangle and ovals

Our last example in this section draws a filled oval that is centered in its frame. The oval is half as high and half as wide as the frame. The code uses the frame's getSize() method, which is inherited from one of the superclasses of java.awt.Frame. This method returns an instance of Dimension, which is a tiny class with two public ints called width and height:

 1. import java.awt.*;  2.  3. public class CenteredOval extends Frame  4. {  5.   CenteredOval ()  6.   {  7.     setSize(200, 150);  8.   }  9. 10.   public void paint(Graphics g) 11.   { 12.     g.setColor(Color.black); 13.     Dimension size = getSize(); 14.     g.fillOval(size.width/4, size.height/4, 15.                size.width/2, size.height/2); 16.   } 17. 18.   public static void main(String[] args) 19.   { 20.     CenteredOval cenOv = new CenteredOval (); 21.     cenOv.setVisible(true); 22.   } 23. }

Figure 14.10 shows the frame in its original size.


Figure 14.10: Original CenteredOval

If you replace line 7 with setSize(400, 300);, you get Figure 14.11.

click to expand
Figure 14.11: Resized CenteredOval

No matter what size is assigned to the frame in line 7, the paint() method always draws an oval with the correct proportions.

Now you know how to use a graphics object to do the following:

  • Draw lines.

  • Draw rectangles, including squares.

  • Fill rectangles, including squares.

  • Draw ovals, including circles.

  • Fill ovals, including circles.

In the next section, you'll learn how to draw text.




Ground-Up Java
Ground-Up Java
ISBN: 0782141900
EAN: 2147483647
Year: 2005
Pages: 157
Authors: Philip Heller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net