Java2D: An Introduction and Tutorial
3 Paint Styles
3.1 Paint Styles: Overview
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 yourself.
Use setPaint and getPaint to change and retrieve the Paint settings.
Note that setPaint and getPaint supersede the setColor and getColor methods that were used in Graphics.
3.2 Paint Classes
Arguments to the Graphics2D setPaint method (and return values of getPaint) must implement the Paint interface.
Here are the major built-in Paint classes:
- Color
Has the same constants (Color.red, Color.yellow, etc.) as the AWT version, plus some extra constructors.
- GradientPaint
Constructors takes two points, two colors, and optionally a boolean flag that indicates that the color pattern should cycle.
The first color is used at the first point, the second color at the second point, and points in between are colored based on how close they are to each of the points.
- TexturePaint
Constructor takes a BufferedImage and a Rectangle2D, maps the image to the rectangle, then tiles the rectangle.
Creating a BufferedImage from a GIF or JPEG file is a pain.
First load an Image normally, get its size, create a BufferedImage that size with BufferedImage.
TYPE_INT_ARGB as the image type, get the BufferedImage's Graphics object via createGraphics, then draw the Image into the BufferedImage using drawImage.
An example of this process is shown later.
3.3 Transparency
Transparency is not set in the Paint object, rather separately via an AlphaComposite object that is applied via setComposite.
See Section 4 for details.
3.4 Gradient Fills: Example Code
Download the source:
GradientPaintExample.java
(plus ShapeExample.java,
WindowUtilities.java,
and ExitListener.java
if you don't have them from the previous examples).
import java.awt.*;
/** An example of gradient fills with Java2D in Java 1.2.
* 1998 Marty Hall, http://www.apl.jhu.edu/~hall/java/
*/
public class GradientPaintExample extends ShapeExample {
// Red at (0,0), yellow at (175,175), changes gradually between.
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());
}
public static void main(String[] args) {
WindowUtilities.openInJFrame(new GradientPaintExample(),
380, 400);
}
}
3.5 Gradient Fills: Example Output
3.6 Tiled Images as Fill Patterns -- Overview
To use tiled images, you create a TexturePaint object and specify its use via the setPaint method of Graphics2D, just as with solid colors and gradient fills.
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.
Creating a BufferedImage to hold custom drawing is relatively straightforward: call the BufferedImage constructor with a width, a height, and a type of BufferedImage.
TYPE_INT_RGB, then call createGraphics on that to get a Graphics2D with which to draw.
It is a bit harder to create one from an image file.
First load an Image from an image file, then use MediaTracker to be sure it is done loading, then create an empty BufferedImage using the Image width and height, then get the Graphics2D via createGraphics, then draw the Image onto the BufferedImage.
This process has been wrapped up in the getBufferedImage method of my ImageUtilitiesities class.
Note, however, that as of JDK1.2beta4, tiled images fail when used in conjunction with rotation transformations.
3.7 Tiled Images as Fill Patterns: Example Code
Download the source: TiledImages.java
and ImageUtilities.java
(plus WindowUtilities.java
and ExitListener.java
if you don't have them from the previous examples).
TiledImages.java
import com.sun.java.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
/** An example of using TexturePaint to fill objects with tiled
* images. Uses the getBufferedImage method of ImageUtilitiesities to
* load an Image from a file and turn that into a BufferedImage.
* 1998 Marty Hall, http://www.apl.jhu.edu/~hall/java/
*/
public class TiledImages extends JPanel {
private String dir = System.getProperty("user.dir");
private String imageFile1 = dir + "/images/marty.jpg";
private TexturePaint imagePaint1;
private Rectangle imageRect;
private String imageFile2 = dir + "/images/bluedrop.gif";
private TexturePaint imagePaint2;
private int[] xPoints = { 30, 700, 400 };
private int[] yPoints = { 30, 30, 600 };
private Polygon imageTriangle = new Polygon(xPoints, yPoints, 3);
public TiledImages() {
BufferedImage image =
ImageUtilitiesities.getBufferedImage(imageFile1, this);
imageRect =
new Rectangle(235, 70, image.getWidth(), image.getHeight());
imagePaint1 =
new TexturePaint(image, imageRect);
image = ImageUtilitiesities.getBufferedImage(imageFile2, this);
imagePaint2 =
new TexturePaint(image, new Rectangle(0, 0, 32, 32));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setPaint(imagePaint2);
g2d.fill(imageTriangle);
g2d.setPaint(Color.blue);
g2d.setStroke(new BasicStroke(5));
g2d.draw(imageTriangle);
g2d.setPaint(imagePaint1);
g2d.fill(imageRect);
g2d.setPaint(Color.black);
g2d.draw(imageRect);
}
public static void main(String[] args) {
WindowUtilities.openInJFrame(new TiledImages(), 750, 650);
}
}
ImageUtilities.java
import java.awt.*;
import java.awt.image.*;
/** A class that simplifies a few common image operations, in
* particular creating a BufferedImage from an image file, and
* using MediaTracker to wait until an image or several images are
* done loading. 1998 Marty Hall, http://www.apl.jhu.edu/~hall/java/
*/
public class ImageUtilities {
/** Create Image from a file, then turn that into a BufferedImage.
*/
public static BufferedImage getBufferedImage(String imageFile,
Component c) {
Image image = c.getToolkit().getImage(imageFile);
waitForImage(image, c);
BufferedImage bufferedImage =
new BufferedImage(image.getWidth(c), image.getHeight(c),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.drawImage(image, 0, 0, c);
return(bufferedImage);
}
/** Take an Image associated with a file, and wait until it is
* done loading. Just a simple application of MediaTracker.
* If you are loading multiple images, don't use this
* consecutive times; instead use the version that takes
* an array of images.
*/
public static boolean waitForImage(Image image, Component c) {
MediaTracker tracker = new MediaTracker(c);
tracker.addImage(image, 0);
try {
tracker.waitForAll();
} catch(InterruptedException ie) {}
return(!tracker.isErrorAny());
}
/** Take some Images associated with files, and wait until they
* are done loading. Just a simple application of MediaTracker.
*/
public static boolean waitForImages(Image[] images, Component c) {
MediaTracker tracker = new MediaTracker(c);
for(int i=0; i<images.length; i++)
tracker.addImage(images[i], 0);
try {
tracker.waitForAll();
} catch(InterruptedException ie) {}
return(!tracker.isErrorAny());
}
}
3.8 Tiled Images as Fill Patterns: Example Output
Next ->
This tutorial was prepared by Marty Hall for work in the Research and Technology Development Center of the Johns Hopkins University Applied Physics Lab, for courses in the Johns Hopkins Part-Time MS Program in Computer Science, and for various industry seminars and courses.
© 1998 Marty Hall.Java 1.2beta4 version.
This article first appeared in November, 1998 and is reprinted with permission of the author.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|