Software Development

Learn what the Java 2D API graphics package offers

The Java 2D API is an API for drawing two-dimensional graphics in Java, as well as an extension of the capabilities of Sun's Abstract Window Toolkit (AWT). Learn about the most interesting features of Java 2D.

The Java 2D API is an API for drawing two-dimensional graphics in Java, as well as an extension of the capabilities of Sun's Abstract Window Toolkit (AWT). Since Java 2D extends the AWT hierarchy, existing programs will work; even new Java programs can compatibly mix new and existing classes. In addition, as one of the Java Media APIs, Java 2D can help provide an ideal platform for creating enterprise-scale Java applications and applets that take full advantage of rich media to enhance communications.

The following features characterize the Java 2D API:

  • The usage of AWT: Java 2D compatibly extends java.awt. This means that you don't need to change the structure of your programs to use Java 2D since it follows the same programming model as existing classes in the java.awt and java.awt.image packages.
  • Extensible architecture: Java 2D consists of a set of interfaces and base classes that provide the foundation for extensibility. This structure allows you to manage simple and complex drawing operations with the same basic framework.
  • Text handling: You can do almost everything with any text from the simple use of fonts to professional quality handling of character layout and font features.
  • Image processing: Java 2D supplements the image-handling classes in the java.awt.image package, providing an array of image processing and display features. These features include image rescaling, thresholding, computing, manipulating lookup tables, and channel combining. These capabilities are useful in contrast filtering, high- and low-pass filtering, image sharpening, and enhancement. In simpler terms, you can write a not-so-simple graphical editor with minimal effort.
  • Color processing: Java 2D helps solve the consistency and accuracy problems of device dependent color descriptions such as RGB and CMYK. For example, Java 2D allows you to create images in color spaces other than RGB color; it also allows you to characterize colors for more accurate reproduction.

Graphics class

The java.awt.Graphics class encapsulates capabilities that satisfy applications developers' most common requirements. The Graphics2D class extends the java.awt.Graphics class to provide more sophisticated control over geometry, coordinate transformations, color management, and text layout. Most methods of the Graphics class can be divided into two basic groups: draw and fill; this enables you to render basic shapes, text, and images, as well as attribute settings methods, which affect how that drawing and filling appears. Drawing methods include the following:

  • drawString("Hello world", 100, 100): This is for drawing a string at specific coordinates.
  • drawImage(img, 0, 0, width, height, 0, 0, imageWidth, imageHeight, null): This is for drawing an image at specific coordinates and having specified boundaries.
  • drawLine(100,100,200,200): This is for drawing a line from one point to another.
  • fillRect(x0,y0,x1,y1): This is for drawing a rectangle filled with the specified color.

Attribute setting methods, like setFont() and setColor(), are just as descriptive. For a complete list of operations available in the Graphics class, look at JavaDoc documentation.

The general approach to using Java 2D's capabilities is to cast the Graphics object to a Graphics2D object in any AWT method working with the Graphics object, like this:

public void paintComponent(Graphics g) {

super.paintComponent(g); // Typical Swing approach

Graphics2D g2d = (Graphics2D)g; g2d.doSomeStuff(...);

...

}

Now you can create any shape object, text string, or an image. Then you have to modify the drawing parameters that you need, such as font, scale, rotation, thickness, etc. Finally, you draw or fill it with the draw() or fill() method.

Drawing shapes

A typical code snippet for drawing any shape looks similar to this example:

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2d = (Graphics2D)g;

// Assume x, y, and diameter are instance variables

Ellipse2D.Double circle =

new Ellipse2D.double(x, y, diameter, diameter);

g2d.fill(circle);

... }

With the AWT, you usually draw a shape by calling the drawXxx or fillXxx method of the Graphics object. In Java2D, you usually create a Shape object and then call either the draw() or fill() method of the Graphics2D object, supplying the Shape object as an argument. Arguments to the Graphics2D draw and fill methods must implement the Shape interface. You can create your own shapes or use the built-in shapes, which include: Arc2D, Area (a shape built by adding/subtracting other shapes), CubicCurve2D, Ellipse2D, GeneralPath (a series of connected shapes), Line2D, Polygon, Rectangle2D, and RoundRectange2D.

Paint styles

When you fill a Shape, the current Paint attribute of the Graphics2D object is used. This can be a Color (solid color), a GradientPaint (gradient fill gradually combining two colors), a TexturePaint (tiled image), or a new version of Paint that you write. If you want to change and retrieve the Paint settings, you use setPaint and getPaint. (Note that setPaint and getPaint supersede the setColor and getColor methods used in Graphics.)

For a gradient fill, you set the GradientPaint object as an argument for the setPaint() method, like this:.

private GradientPaint gradient =

new GradientPaint(0, 0, Color.red, 175, 175, Color.yellow,

true); // true means to repeat pattern

public void paintComponent(Graphics g) {

clear(g);

Graphics2D g2d = (Graphics2D)g;

drawGradientCircle(g2d);

}

protected void drawGradientCircle(Graphics2D g2d) {

g2d.setPaint(gradient); g2d.fill(getCircle());

g2d.setPaint(Color.black);

g2d.draw(getCircle());

}
Figure A provides an example of the results. Figure A

Figure A

As a fill pattern, besides solid colors and gradient fills, you can use tiled images. To do so, you create a TexturePaint object and specify its use via the setPaint method of Graphics2D. The TexturePaint constructor takes a BufferedImage and a Rectangle2D as arguments. The BufferedImage specifies what to draw, and the Rectangle2D specifies where the tiling starts.

It's relatively straightforward to create a BufferedImage to hold custom drawings: You call the BufferedImage constructor with a width, a height, and a type of BufferedImage.TYPE_INT_RGB and then call createGraphics() method with these properties set up to get a Graphics2D with which to draw. It is a bit harder to create a BufferedImage from an image file. Follow these steps:

  1. Load an Image from an image file.
  2. Use MediaTracker to be sure it is done loading.
  3. Create an empty BufferedImage using the Image width and height.
  4. Get the Graphics2D via createGraphics.
  5. Draw the Image onto the BufferedImage.

Java 2D permits you to assign transparency (or alpha) values to drawing operations so the underlying graphics partially shows through when you draw shapes or images. You set transparency by creating an AlphaComposite object and then passing it to the setComposite method of the Graphics2D object. You create an AlphaComposite by calling AlphaComposite.getInstance with a mixing rule designator and a transparency value. Transparency values range from 0.0F (completely transparent) to 1.0F (completely opaque). This is an example of using transparency:

import javax.swing.*;

import java.awt.*;

import java.awt.geom.*;

private Rectangle

blueSquare = new Rectangle(gap+offset, gap+offset, width, width),

redSquare = new Rectangle(gap, gap, width, width);

private AlphaComposite makeComposite(float alpha) {

int type = AlphaComposite.SRC_OVER;

return(AlphaComposite.getInstance(type, alpha));

}

private void drawSquares(Graphics2D g2d, float alpha) {

Composite originalComposite = g2d.getComposite();

g2d.setPaint(Color.blue);

g2d.fill(blueSquare);

g2d.setComposite(makeComposite(alpha));

g2d.setPaint(Color.red);

g2d.fill(redSquare);

g2d.setComposite(originalComposite);

}

In the AWT, the drawXxx methods of Graphics resulted in solid, 1-pixel wide lines. Also, drawing commands that consist of multiple line segments (e.g., drawRect and drawPolygon) had a predefined way of joining the line segments together and terminating segments that do not join to others. Java 2D gives you much more flexibility. In addition to setting the pen color or pattern (via setPaint, Java 2D permits you to set the pen thickness and dashing pattern and to specify the way line segments end and are joined together. You do this by creating a BasicStroke object and then telling the Graphics2D object to use it via the setStroke method.

Java 2D allows you to easily translate, rotate, scale, or shear the coordinate system. This is very convenient because it is often much easier to move the coordinate system than to calculate new coordinates for each of your points. For these transformations, you use Graphics2D methods translate() and rotate().

Conclusion

The Java 2D API's capabilities go far beyond this introductory article. Sophisticated developers can use Java 2D to do things such as high-quality printing, custom color mixing, fancy text operations (e.g., create new fonts by transforming old ones), low-level image processing, and color model manipulations. For more information about Java 2D, check out these resources from Sun:

Peter V. Mikhalenko is a Sun certified professional who works for Deutsche Bank as a business consultant.

---------------------------------------------------------------------------------------

Get Java tips in your inbox Delivered each Thursday, our free Java newsletter provides insight and hands-on tips you need to unlock the full potential of this programming language. Automatically subscribe today!
1 comments

Editor's Picks