Graphics
Graphics
-
So what do you do inside a Container? Well the most basic thing you can
do is draw in it.
-
For example, you may find yourself in a situation in which you want to
draw various shapes, lines, or points inside of your application. Perhaps
you will want to draw three-dimensional lines that surrounding a component.
You can draw a raised 3D border by simply drawing
a light line on the top and left of a component and dark lines on the right
and bottom. |
-
Or perhaps you will want to graph points along a curve from data you receive
from outside of your application. Either way, when you need to draw within
a window, the JDK provides a host of supporting classes to help you.
-
Graphics manipulation is handled by the java.awt.Graphics class which you
can study using the online documentation. As you can see, there is a vast
array of tools you can use for drawing.
-
So how do you draw?
-
To draw using the JDK, you first need something to draw on. Most commonly,
you will draw in the visible window of a component or in a container.
-
All components and containers (since containers are actually components)
in the JDK have two methods that are called by the system to paint their
surface. These are the paint() and update() methods. Their signatures are
provided below:
public void paint(FxGraphics g);
public void update(FxGraphics g);
To cause a drawing to appear in a window, you normally override either
or both of the paint() and the update() methods.
The paint() method
-
When a component needs to draw itself, its paint() method is called to
do the work. Whether the component draws a letter, a line, a circle, or
a check box, the process is the same.
-
Since every time the component is drawn its paint() method is called, the
component's paint() method can be called hundreds of times in the life
of an applet. After all, there are many reasons for the component to be
redrawn. The component must draw itself when it first becomes visible.
The component must also use its paint() method if the user drags a window
over the component to paint the area when it' is re-exposed.
-
The most simple paint() method looks like the following:
public void paint(Graphics g)
{
}
Notice that the method takes a Graphics object as a parameter. This object
represents the graphics surface that needs to be painted. We'll talk more
about Graphics objects in just a bit.
Thus, in order to draw on a Panel, we could subclass panel and override
the paint method as follows:
import java.awt.*;
class MyPanel extends Panel
{
public void paint(Graphics g)
{
g.setColor(Color.green);
g.fillRect(10, 10, 50, 50);
}
}
If we used this new subclass of Panel instead of the default Panel for
the example in Exercise Six, we would get the following interface:
![[Example]](paint_example.gif)
Update
-
The second method that you need to understand which is called by a component
to paint its surface is the update() method.
-
The update() method clears the surface of the component to its background
color and then calls the paint() method to paint the rest of the component.
This is quite convenient because you don't have to draw the whole component
within a paint() method, the background is filled for you. Then, when you
override paint() you only need to draw what should appear on top of the
background.
-
Of course, there are times when you may want to override update(). Consider
the case in which you want to draw a large, white rectangle inside a control.
If you don't override update(), the control's entire background will be
drawn by the update() method, and then the white rectangle will be drawn
by the paint() method. A large area of one color is first drawn and then
the large area of the rectangle in another color is redrawn. This could
cause a user to see some slight flickering on the display, especially if
the rectangle needs to be drawn a number of times in succession.
-
You can overcome this problem by overriding update(). You would override
the update() method so that it calls paint(), and then have paint() first
draw only the background areas that surrounding the white rectangle-- (and
not the rectangle itself--) and then draw the white rectangle. This would
remove flicker by eliminating the drawing of two overlapping objects of
different colors.
Repainting
-
As we said previously, when a component is created and displayed, its update()
and paint() methods are called to paint the component to the surface of
the screen. If you hide and show the component or drag another window over
the component, the system handles calling update() and paint() to repaint
areas which require repainting.
-
However, there are times when you may want to force an on-screen component
to repaint manually. For example, if you change certain properties on a
component you may want it to repaint to reflect its new appearance. To
accomplish this repaint you can call the repaint() method.
-
Here is an example:
text.setBackground(Color.green);
text.repaint();
Calling the repaint() method causes the whole component to repaint. You
may find times when you only want a section of a given component to repaint.
You can perform this by calling repaint() and giving a specific portion
of the area to redraw.
For example, the following code repaints only a 50x50 portion of a component
starting at the origin:
comp.repaint(0, 0, 50, 50);
There are a few more things that you should know about repainting. First,
when you call repaint, the paint() method on the given component does not
immediately get called to paint its surface. The call to repaint() tells
the system that the component needs to be repainted. The system can collect
a number of repaint requests and perform them by repainting the component
a single time. So, if you make 10 requests for a component to repaint,
its paint() method may only be called once.
This does not normally cause any problems, but you may find cases where
you need the system to paint a surface immediately. For example, if you
had a loop in your program where you wanted a surface to paint 10 times
in a loop to perform an animation, calling repaint() in the loop could
cause all the paint requests to be combined into one paint operation.
In these cases, you may want to call the update() method directly on a
component to cause it to paint immediately. You can do this by creating
your own graphics object and then calling update() directly. The getGraphics()
method Component allows you to create a Graphics object for the surface
of a given component. For example the following code will forces an immediate
repaint of a component:
Graphics g = comp.getGraphics();
if (g != null)
{
comp.update(g);
g.dispose();
}
Notice that we call the dispose() method on the graphics
object after its use. As with AWT graphics objects, you should call dispose()
on any graphics object you create after you have completed using it. You
should not call dispose() on graphics' objects that you have not explicitly
created yourself. Specifically, do not dispose of a graphics object passed
by the AWT itself. For example, when an applet needs to repaint itself,
it will pass a graphics object to the paint() method. This is all handled
behind the scenes and you don't need to worry about it. The only time you
need to worry is if you create a graphics object yourself. |
The Coordinate System
-
Each component in the JDK has its own coordinate system. This means that
when you add a component to your application and implement a paint() method
in that component, a drawing position of 0, 0 is the upper, left- hand
corner of the component, not the upper left of the screen or frame the
component is contained in.
-
But the upper, left- hand corner is only half of what you need to know
about the coordinate system in order to draw correctly. You also need to
know the bottom, right corner of the coordinate system if you want to place
lines and points correctly within your component when painting.
-
To determine the bottom, right corner of the coordinate system in the component,
you can use the getSize() method to determine the width and height of the
component.
-
For example, the following paint() method draws a blue rectangle in the
center of the component (10 in from all sides)
public void paint(Graphics g)
{
Dimension size = getSize();
g.setColor(Color.blue);
g.fillRect(10, 10,
size.width - 20,
size.height - 20);
}
Graphics by Example
-
Let's look at an example. All of the methods used here are readily accessible
by referencing the online documentation.
import java.awt.*;
public class GraphicsExample extends Frame
{
public static void main(String[] args)
{
Frame f = new GraphicsExample();
f.setTitle("Graphics Example");
f.reshape(10,10,200,300);
f.setBackground(Color.yellow);
f.setForeground(Color.black);
f.show();
}
public void paint(Graphics g)
{
Font f = new Font("Arial", Font.BOLD +
Font.ITALIC, 10);
Font f1 = new Font("TimesRoman",
Font.BOLD, 20);
String s = "Hello Cyberspace";
Color purple = new Color(200,0,255);
g.setFont(f);
g.drawString("Hello Cyberspace",10, 50);
g.setColor(purple);
g.setFont(f1);
g.drawString("Hello Cyberspace",10, 80);
g.setColor(Color.blue);
g.drawLine(20,90,40,110);
g.setColor(new Color(0,0,0));
g.drawArc(90,90,40,40,30,200);
g.drawRect(10,120,20,40);
g.drawRoundRect(50,120,20,40, 10,10);
g.drawOval(100,120,30,40);
g.setColor(Color.blue);
g.fillRect(10,180,30,40);
g.setColor(Color.green);
g.fillOval(50,180,40,40);
Image image =
Toolkit.getDefaultToolkit().getImage
("afraid_icon.gif");
g.drawImage(image,110,180,this);
}
}
Additional Resources:
Layouts
Table of Contents
Exercise Seven
|