You are on page 1of 66

Tutorial Contents Tutorial Resources The Java Tutorials' Blog has news and updates about the Java

SE tutorials. The Java Tutorials Community Portal is the place to discuss the tutorials and to share your modifications and extensions to the tutorials. You can download the Java Tutorials from the Sun Download Center. The FAQ answers questions about the Tutorials. Online Resources lists programming aids besides the Tutorials. In Book Form The Java Tutorial, Fourth Edition. Amazon.com. Errata for The Java Tutorial, Fourth Edition. The JFC Swing Tutorial, Second Edition. Amazon.com. Other books on the Java platform are available from The Java Series Store. Other Resources Java SE Platform Guides API Documentation The Java EE 5 Tutorial The Java Web Services Tutorial The J2EE Tutorial for the Sun ONE Platform NetBeans Documentation Sun Training and Professional Certification Java and Web Services Training Sun Java Technology Certification Software The Java Development Kit (JDK) for Java SE 6. NetBeans IDE Java EE SDK The Java Tutorials are practical guides for programmers who want to use the Java programming language to create applications. They include hundreds of complete, working examples, and dozens of lessons. Groups of related lessons are organized into "trails".

For the most accurate and up-to-date tutorials, please access the latest version from Sun's official website for the Java SE Tutorials (Last Updated 5/27/2009), which can be found at: http://java.sun.com/docs/books/tutorial. The Java Tutorials primarily describe features in Java SE 6. For best results, download JDK 6. Please check out the new Java Tutorials Community Portal, the place to discuss the tutorials, and to share your modifications and additions to the tutorials. What's New The Java Tutorials are continuously updated to keep up with changes to the Java Platform and to incorporate feedback from our readers. Some recent updates include: An entirely reworked File I/O lesson, featuring NIO.2. This functionality is part of JDK7, which is available now through the Open JDK project on java.net. A new specialized trail covering Sockets Direct Protocol, also new in JDK7. A new facility for gathering feedback about the tutorial. At the bottom of each tutorial page, under the "Discuss" heading, you can leave a publicly viewable, blog-style comment. Let us know what you think about the inclusion of this JS-Kit mechanism.

Trails Covering the Basics These trails are available in book form as The Java Tutorial, Fourth Edition. To buy this book, refer to the box to the right. Getting Started An introduction to Java technology and lessons on installing Java development software and using it to create a simple program. Learning the Java Language Lessons describing the essential concepts and features of the Java Programming Language. Essential Java Classes Lessons on exceptions, basic input/output, concurrency, regular expressions, and the platform environment. Collections Lessons on using and extending the Java Collections Framework. Swing An introduction to the Swing GUI toolkit, with an overview of features and a visual catalog of components. See below for a more comprehensive tutorial on Swing. Deployment How to package applications and applets using JAR files, and deploy them using Java Web Start and Java Plug-in. Preparation for Java Programming Language Certification List of available training and tutorial resources.

Creating Graphical User Interfaces This trail is available in book form as The JFC Swing Tutorial. To buy this book, refer to the box to the right. The Swing examples are bundled to be open and run in NetBeans IDE. (Of course you can import the source files into any IDE that you wish.) For more information, see Running Tutorial Examples in NetBeans IDE. Each Swing lesson has a separate Examples Index for a sample, check out the Using Swing Components Examples Index. Creating a GUI with Swing A comprehensive introduction to GUI creation on the Java platform.

Specialized Trails and Lessons These trails and lessons are only available as web pages. Custom Networking An introduction to the Java platform's powerful networking features. The Extension Mechanism How to make custom APIs available to all applications running on the Java platform. Full-Screen Exclusive Mode API How to write applications that more fully utilize the user's graphics hardware. Generics An enhancement to the type system that supports operations on objects of various types while providing compile-time type safety. Note that this lesson is for advanced users. The Java Language trail contains a Generics lesson that is suitable for beginners. Internationalization An introduction to designing software so that it can be easily be adapted (localized) to various languages and regions. JavaBeans The Java platform's component technology. JDBC Database Access Introduces an API for connectivity between the Java applications and a wide range of databases and a data sources. JMX Java Management Extensions provides a standard way of managing resources such as applications, devices, and services. JNDI Java Naming and Directory Interface enables accessing the Naming and Directory Service such as DNS and LDAP. RMI The Remote Method Invocation API allows an object to invoke methods of an object running on another Java Virtual Machine. Reflection An API that represents ("reflects") the classes, interfaces, and objects in the current Java Virtual Machine. Security Java platform features that help protect applications from malicious software. Sound An API for playing sound data from applications.

2D Graphics How to display and print 2D graphics in applications. Sockets Direct Protocol How to enable the Sockets Direct Protocol to take advantage of InfiniBand.

Sun Training and Professional Certification The Java Tutorials are practical guides for programmers who want to use the Java programming language to create applications. They include hundreds of complete, working examples, and dozens of lessons. Groups of related lessons are organized into "trails". For the most accurate and up-to-date tutorials, please access the latest version from Sun's official website for the Java SE Tutorials (Last Updated 5/27/2009), which can be found at: http://java.sun.com/docs/books/tutorial. The Java Tutorials primarily describe features in Java SE 6. For best results, download JDK 6. Please check out the new Java Tutorials Community Portal, the place to discuss the tutorials, and to share your modifications and additions to the tutorials. What's New The Java Tutorials are continuously updated to keep up with changes to the Java Platform and to incorporate feedback from our readers. Some recent updates include: An entirely reworked File I/O lesson, featuring NIO.2. This functionality is part of JDK7, which is available now through the Open JDK project on java.net. A new specialized trail covering Sockets Direct Protocol, also new in JDK7. A new facility for gathering feedback about the tutorial. At the bottom of each tutorial page, under the "Discuss" heading, you can leave a publicly viewable, blog-style comment. Let us know what you think about the inclusion of this JS-Kit mechanism.

Trails Covering the Basics These trails are available in book form as The Java Tutorial, Fourth Edition. To buy this book, refer to the box to the right. Getting Started An introduction to Java technology and lessons on installing Java development software and using it to create a simple program. Learning the Java Language Lessons describing the essential concepts and features of the Java Programming Language. Essential Java Classes Lessons on exceptions, basic input/output, concurrency, regular expressions, and the platform environment.

Collections Lessons on using and extending the Java Collections Framework. Swing An introduction to the Swing GUI toolkit, with an overview of features and a visual catalog of components. See below for a more comprehensive tutorial on Swing. Deployment How to package applications and applets using JAR files, and deploy them using Java Web Start and Java Plug-in. Preparation for Java Programming Language Certification List of available training and tutorial resources.

Creating Graphical User Interfaces This trail is available in book form as The JFC Swing Tutorial. To buy this book, refer to the box to the right. The Swing examples are bundled to be open and run in NetBeans IDE. (Of course you can import the source files into any IDE that you wish.) For more information, see Running Tutorial Examples in NetBeans IDE. Each Swing lesson has a separate Examples Index for a sample, check out the Using Swing Components Examples Index. Creating a GUI with Swing A comprehensive introduction to GUI creation on the Java platform.

Specialized Trails and Lessons These trails and lessons are only available as web pages. Custom Networking An introduction to the Java platform's powerful networking features. The Extension Mechanism How to make custom APIs available to all applications running on the Java platform. Full-Screen Exclusive Mode API How to write applications that more fully utilize the user's graphics hardware. Generics An enhancement to the type system that supports operations on objects of various types while providing compile-time type safety. Note that this lesson is for advanced users. The Java Language trail contains a Generics lesson that is suitable for beginners. Internationalization An introduction to designing software so that it can be easily be adapted (localized) to various languages and regions. JavaBeans The Java platform's component technology. JDBC Database Access Introduces an API for connectivity between the Java applications and a wide range of databases and a data sources.

JMX Java Management Extensions provides a standard way of managing resources such as applications, devices, and services. JNDI Java Naming and Directory Interface enables accessing the Naming and Directory Service such as DNS and LDAP. RMI The Remote Method Invocation API allows an object to invoke methods of an object running on another Java Virtual Machine. Reflection An API that represents ("reflects") the classes, interfaces, and objects in the current Java Virtual Machine. Security Java platform features that help protect applications from malicious software. Sound An API for playing sound data from applications. 2D Graphics How to display and print 2D graphics in applications. Sockets Direct Protocol How to enable the Sockets Direct Protocol to take advantage of InfiniBand.

Trail: 2D Graphics This trail introduces you to the Java 2D API and shows you how to display and print 2D graphics in your Java programs. The trial is intended for developers who want to enrich their knowledge of the Java 2D API, as well as for beginners in computer graphics. Almost every section contains relevant examples to illustrate specific capabilities. The Java 2D API enables you to easily perform the following tasks: Draw lines, rectangles and any other geometric shape. Fill those shapes with solid colors or gradients and textures. Draw text with options for fine control over the font and rendering process. Draw images, optionally applying filtering operations. Apply operations such as compositing and transforming during any of the above rendering operations.

This chapter also explains less familiar concepts such as compositing. Using 2D Graphics API to display complex charts

Using image-filtering operations This chapter describes the concept of drawing on-screen and off-screen images, as well as surfaces and printer devices. This trail covers the most common uses of the Java 2D APIs and briefly describes some of the more advanced features. Overview of the Java 2D Graphics API introduces the key Java 2D concepts and describes the Java 2D rendering model. This lesson is more conceptual than other lessons of this trail, it enables you to get deep into basic notions and classes descriptions. Getting started with Graphics uses a developed example to show you how to obtain a Graphics object and use it for common graphics rendering tasks. Working with Geometry teaches you how to use APIs to draw graphic primitives and arbitrary shapes, and how to apply fancy strokes and fill styles. Working with Text APIs shows you how to effectively use text APIs, including how to create a Font object with desired attributes, measure text, and determine the names of the fonts available on your system. Working with Images explains how to create a BufferedImage object, perform image-filtering operations, and draw on an image. Printing teaches you how to render 2D graphics to a printer, print complex documents, and use Print Services. Advanced topics in Java 2D explains how to perform transformations, clip the drawing region, composite overlapping graphics, specify rendering preferences, and control rendering quality.

We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of replies your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use. Trail: 2D Graphics Lesson: Overview of the Java 2D API Concepts Overview of the Java 2D API Concepts Coordinates Java 2D Rendering

Geometric Primitives Text Images Printing Home Page > 2D Graphics > Overview of the Java 2D API Concepts Previous Trail Next Java 2D Rendering The Java 2D API provides a uniform rendering model across different types of devices. At the application level, the rendering process is the same whether the target rendering device is a screen or a printer. When a component needs to be displayed, its paint or update method is automatically invoked with the appropriate Graphics context. The Java 2D API includes the java.awt.Graphics2D class, which extends the Graphics class to provide access to the enhanced graphics and rendering features of the Java 2D API. These features include: Rendering the outline of any geometric primitive, using the stroke and paint attributes (draw method). Rendering any geometric primitive by filling

Geometric Primitives

The Java 2D API provides a useful set of standard shapes such as points, lines, rectangles, arcs, ellipses, and curves. The most important package to define common geometric primitives is the java.awt.geom package. Arbitrary shapes can be represented by combinations of straight geometric primitives.

The Shape interface represents a geometric shape, which has an outline and an interior. This interface provides a common set of methods for describing and inspecting twodimensional geometric objects and supports curved line segments and multiple sub-shapes. The Graphics class supports only straight line segments. The Shape interface can support curves segments. For more details about how to draw and fill shapes, see the Working with Geometry lesson. The Point2D class defines a point representing a location in (x, y) coordinate space. The term point in the Java 2D API is not the same as a

Points

pixel. A point has no area, does not contain a color, and cannot be rendered.

Points are used to create other shapes. ThePoint2D class also includes a method for calculating the distance between two points. The Line2D class is an abstract class that represents a line. A lines coordinates can be retrieved as double. The Line2D class includes several methods for setting a lines endpoints.

Lines

Also, you can create a straight line segment by using the GeneralPath class described below. Rectangular Shapes

The Rectangle2D, RoundRectangle2D, Arc2D, and Ellipse2D primitives are all derived from the RectangularShape class. This class defines methods for Shape objects that can be described by a rectangular bounding box. The geometry of a RectangularShape object can be extrapolated from a rectangle that completely encloses the outline of the Shape.

Quadratic and Cubic Curves The QuadCurve2D enables you to create quadratic parametric curve segments. A quadratic curve is defined by two endpoints and one control point.

The CubicCurve2D class enables you to create cubic parametric curve segments. A cubic curve is defined by two endpoints and two control points. The following are examples of quadratic and cubic curves. See Stroking and Filling for implementations of cubic and quadratic curves. This figure represents a quadratic curve.

This figure represents a cubic curve.

Arbitrary Shapes The GeneralPath class enables you to construct an arbitrary shape by specifying a series of positions along the shapes boundary. These positions can be connected by line segments, quadratic curves, or cubic (Bzier) curves. The following shape can be created with three line segments and a cubic curve. See Stroking and Filling for more information about the implementation of this shape.

Areas With the Area class, you can perform boolean operations, such as union, intersection, and subtraction, on any two Shape objects. This technique, often referred to as constructive area geometry, enables you to quickly create complex Shape objects without having to describe

each line segment or curve.

Coordinates Java 2D Rendering Geometric Primitives Text Images Printing Text The Java 2D API has various text rendering capabilities including methods for rendering strings and entire classes for setting font attributes and performing text layout. If you just want to draw a static text string, the most direct way to render it directly through the Graphics class by using the drawString method. To specify the font, you use the setFont method of the Graphics class. If you want to implement your own text-editing routines or need more control over the layout of the text than the text components provide, you can use the Java 2D text layout classes in the java.awt.font package. Fonts The shapes that a font uses to represent the characters in a string are called glyphs. A particular character or combination of characters might be represented as one or more glyphs. For example, might be represented by two glyphs, whereas the ligature fi might be represented by a single glyph. A font can be thought of as a collection of glyphs. A single font might have many faces, such as italic and regular. All of the faces in a font have similar typographic features and can be recognized as members of the same family. In other words, a collection of glyphs with a particular style form a

font face. A collection of font faces forms a font family. The collection of font families forms the set of fonts that are available on the system. When you are using the Java 2D API, you specify fonts by using an instance of Font. You can determine what fonts are available by calling the static method GraphicsEnvironment.getLocalGraphicsEnvironment and then querying the returned GraphicsEnvironment. The getAllFonts method returns an array that contains Font instances for all of the fonts available on the system. The getAvailableFontFamilyNames method returns a list of the available font families. Text Layout Before text can be displayed, it must be laid out so that the characters are represented by the appropriate glyphs in the proper positions. The following are two Java 2D mechanisms for managing text layout:

The TextLayout class manages text layout, highlighting, and hit detection. The facilities provided by TextLayout handle the most common cases, including strings with mixed fonts, mixed languages, and bidirectional text. . You can create the own GlyphVector objects by using the Font class and then rendering each GlyphVector object through the Graphics2D class. Thus, you can completely control how text is shaped and positioned. .

Rendering Hints for Text The Java 2D API enables you to control the quality of shapes and text rendering by using rendering hints. Rendering hints are encapsulated by the java.awt.RenderingHints class. As applied to text, this capability is used for antialiasing (which is also known as an smooth edges). For example, the KEY_TEXT_ANTIALIASING hint enables you to control the antialiasing of text separately from the antialiasing of other shapes. To learn more about rendering hints see the Controlling Rendering Quality lesson. Trail: 2D Lesson: Overview of the Java 2D API Concepts Overview of the Java 2D API Concepts Coordinates Java 2D Rendering Geometric Primitives Text Images Printing Graphics

Printing All of the Swing and Java 2D graphics, including composited graphics and images, can be rendered to a printer by using the Java 2D Printing API. This API also provides document composition features that enable you to perform such operations as changing the order in which pages are printed. Rendering to a printer is like rendering to a screen. The printing system controls when pages are rendered, just like the drawing system controls when a component is painted on the screen. The Java 2D Printing API is based on a callback model in which the printing system, not the application, controls when pages are printed. The application provides the printing system with information about the document to be printed, and the printing system determines when each page needs to be imaged. The following two features are important to support printing: Job control Initiating and managing the print job including displaying the standard print and setup dialog boxes Pagination Rendering each page when the printing system requests it

When pages need to be imaged, the printing system calls the applications print method with an appropriate Graphics context. To use Java 2D API features when you print, you cast the Graphics object to a Graphics2D class, just like you do when you are rendering to the screen.

Images Printing

Home Page > 2D Graphics > Overview of the Java 2D API Concepts Previous Trail Next Images In the Java 2D API an image is typically a rectangular two-dimensional array of pixels, where each pixel represents the color at that position of the image and where the dimensions represent the horizontal extent (width) and vertical extent (height) of the image as it is displayed. The most important image class for representing such images is the java.awt.image.BufferedImage class. The Java 2D API stores the contents of such images in memory so that they can be directly accessed. Applications can directly create a BufferedImage object or obtain an image from an external image format such as PNG or GIF. In either case, the application can then draw on to image by using Java 2D API graphics calls. So, images are not limited to displaying photographic type images. Different objects such as line art, text, and other graphics and even other images can be drawn onto an image (as shown on the following images).

The Java 2D API enables you to apply image filtering operations to BufferedImage and includes several built-in filters. For example, the ConvolveOp filter can be used to blur or sharpen images. The resulting image can then be drawn to a screen, sent to a printer, or saved in a graphics format such as PNG, GIF etc. To learn more about images see the Working with Images lesson lesson.

Lesson: Getting Started with Graphics

The Java 2D API is powerful and complex. However, the vast majority of uses for the Java 2D API utilize a small subset of its capabilities encapsulated in the java.awt.Graphics class. This lesson covers the most common needs of applications developers. Less common needs are described later in the Advanced topics in the Java 2D API lesson. Most methods of the Graphics class can be divided into two basic groups: Draw and fill methods, enabling you to render basic shapes, text, and images Attributes setting methods, which affect how that drawing and filling appears

Methods such as setFont and setColor define how draw and fill methods render. This figure illustrates how these methods relate to graphic objects:

Drawing methods include:


drawString For drawing text g.drawString("Hello", 10, 10); drawImage For drawing images g.drawImage(img, 0, 0, width, height, 0, 0, imageWidth, imageHeight, null);

drawLine, drawArc, drawRect, drawOval, drawPolygon For drawing geometric shapes

g2.draw(new Line2D.Double(0, 0, 30, 40));

Depending on your current need, you can choose one of several methods in the Graphics class based on the following criteria: Whether you want to render the image at the specified location in its original size or scale it to fit inside the given rectangle Whether you prefer to fill the transparent areas of the image with color or keep them transparent

Fill methods apply to geometric shapes and include fillArc, fillRect, fillOval, fillPolygon. Whether you draw a line of text or an image, remember that in 2D graphics every point is determined by its x and y coordinates. All of the draw and fill methods need this information which determines where the text or image should be rendered. For example, to draw a line, an application calls the following: java.awt.Graphics.drawLine(int x1, int y1, int x2, int y2) In this code (x1, y1) is the start point of the line, and (x2, y2) is the end point of the line. So the code to draw a horizontal line is as follows: Graphics.drawLine(20, 100, 120, 100); The demo below accumulates all mentioned techniques. Move the slider to display various weather types.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The WeatherWizard demo uses the JSlider component as well as various graphics capabilities to generate and display a specified weather type. For more information about the JSlider class see the How to Use Sliders section of the Swing Tutorial. The paint method of the WeatherPainter class implements graphics features. The following code draws an image determined by using the setupWeatherReport() method. ... origComposite = g2.getComposite();

if (alpha0 != null) g2.setComposite(alpha0); g2.drawImage(img0, 0, 0, size.width, size.height, 0, 0, img0.getWidth(null), img0.getHeight(null), null); if (img1 != null) { if (alpha1 != null) g2.setComposite(alpha1); g2.drawImage(img1, 0, 0, size.width, size.height, 0, 0, img1.getWidth(null), img1.getHeight(null), null); } ... The setFont and drawString methods render the temperature and the weather condition. ... // Freezing, Cold, Cool, Warm, Hot, // Blue, Green, Yellow, Orange, Red Font font = new Font("Serif", Font.PLAIN, 36); g.setFont(font); String tempString = feels + " " + temperature+"F"; FontRenderContext frc = ((Graphics2D)g).getFontRenderContext(); ... g.setColor(textColor); int xTextTemp = rX-(int)boundsTemp.getX(); int yTextTemp = rY-(int)boundsTemp.getY(); g.drawString(tempString, xTextTemp, yTextTemp); int xTextCond = rX-(int)boundsCond.getX(); int yTextCond = rY-(int)boundsCond.getY() + (int)boundsTemp.getHeight(); g.drawString(condStr, xTextCond, yTextCond);

The fillRect method allows you to draw a rectangle filled with the specified color. ... Rectangle2D boundsTemp = font.getStringBounds(tempString, frc); Rectangle2D boundsCond = font.getStringBounds(condStr, frc); int wText = Math.max((int)boundsTemp.getWidth(), (int)boundsCond.getWidth());

int hText = (int)boundsTemp.getHeight() + (int)boundsCond.getHeight(); int rX = (size.width-wText)/2; int rY = (size.height-hText)/2; g.setColor(Color.LIGHT_GRAY); g2.fillRect(rX, rY, wText, hText); ... Try to modify the WeatherWizard demo to alter the graphical content. For example, use the fillRoundRect method instead of fillRect or apply another font size in the setFont method. Find the complete code for this applet in the WeatherWizard.java file. The demo also requires the following images: weather-cloud.png, weather-rain.png, weather-snow.png, and weather-sun.png located in the images directory. . Working with Geometry Drawing Geometric Primitives Drawing Arbitrary Shapes Stroking and Filling Graphics Primitives Trail: 2D Graphics Home Page > 2D Graphics Previous Trail Next Lesson: Working with Geometry In prior lessons, you have learned the graphics concept, including basic information about the coordinate system and graphic object creation. Now, you will progress to more detailed lessons about the 2D graphics classes. This lesson shows you how to use the Graphics2D class to draw graphic primitives as well as arbitrary shapes, and how to display graphics with fancy outline and fill styles. These topics are discussed in the following sections. Drawing Geometric Primitives This section explains how to create standard shapes such as points, lines, curves, arcs, rectangles, and ellipses. Drawing Arbitrary Shapes This section explains how to draw shapes represented by combinations of straight geometric primitives by using the GeneralPath class.

Filling and Stroking This section explains how to set the stroke and paint attributes to control the outline and fill styles applied to Shape objects and text. We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of replies your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.

Working with Geometry Drawing Geometric Primitives The Java 2D API provides several classes that define common geometric objects such as points, lines, curves, and rectangles. These geometry classes are part of the java.awt.geom package. The PathIterator interface defines methods for retrieving elements from a path. The Shape interface provides a set of methods for describing and inspecting geometric path objects. This interface is implemented by the GeneralPath class and other geometry classes. All examples represented in this section create geometries by using java.awt.geom and then render them by using the Graphics2D class. To begin you obtain a Graphics2D object, for example by casting the Graphics parameter of the paint() method. public void paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... } Point The Point class creates a point representing a location in (x,y) coordinate space. The subclasses Point2D.Float and Point2D.Double provide correspondingly float and double precision for storing the coordinates of the point. //Create Point2D.Double Point2D.Double point = new Point2D.Double(x, y); To create a point with the coordinates 0,0 you use the default constructor, Point2D.Double(). You can use the setLocation method to set the position of the point as follows:

setLocation(double x, double y) To set the location of the point- defining coordinates as double values setLocation(Point2D p) To set the location of the point using the coordinates of another point.

Also, the Point2D class has methods to calculate the distance between the current point and a point with given coordinates, or the distance between two points. Line The Line2D class represents a line segment in (x, y) coordinate space. The Line2D.Float and Line2D.Double subclasses specify lines in float and double precision. For example: // draw Line2D.Double g2.draw(new Line2D.Double(x1, y1, x2, y2)); This class includes several setLine() methods to define the endpoints of the line. Aternatively, the endpoints of the line could be specified by using the constructor for the Line2D.Float class as follows:

Line2D.Float(float X1, float Y1, float X2, float Y2) Line2D.Float(Point2D p1, Point2D p2)

Use the Stroke object in the Graphics2D class to define the stroke for the line path. Curves The java.awt.geom package enables you to create a quadratic or cubic curve segment. Quadratic Curve Segments The QuadCurve2D class implements the Shape interface. This class represents a quadratic parametric curve segment in (x, y) coordinate space. The QuadCurve2D.Float and QuadCurve2D.Double subclasses specify a quadratic curve in float and double precision. Several setCurve methods are used to specify two endpoints and a control point of the curve, whose coordinates can be defined directly, by the coordinates of other points and by using a given array. A very useful method, setCurve(QuadCurve2D c), sets the quadratic curve with the same endpoints and the control point as a supplied curve. For example: // create new QuadCurve2D.Float QuadCurve2D q = new QuadCurve2D.Float(); // draw QuadCurve2D.Float with set coordinates q.setCurve(x1, y1, ctrlx, ctrly, x2, y2); g2.draw(q);

Cubic Curve Segment The CubicCurve2D class also implements the Shape interface. This class represents a cubic parametric curve segment in (x, y) coordinate space. CubicCurve2D.Float and CubicCurve2D.Double subclasses specify a cubic curve in float and double precision. The CubicCurve2D class has similar methods for setting the curve as the QuadraticCurve2Dclass, except with a second control point. For example: // create new CubicCurve2D.Double CubicCurve2D c = new CubicCurve2D.Double(); // draw CubicCurve2D.Double with set coordinates c.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); g2.draw(c); Rectangle Classes that specify primitives represented in the following example extend the RectangularShape class, which implements the Shape interface and adds a few methods of its own. These methods enables you to get information about a shapes location and size, to examine the center point of a rectangle, and to set the bounds of the shape. The Rectangle2D class represents a rectangle defined by a location (x, y) and dimension (w x h). The Rectangle2D.Float and Rectangle2D.Double subclasses specify a rectangle in float and double precision. For example: // draw Rectangle2D.Double g2.draw(new Rectangle2D.Double(x, y, rectwidth, rectheight)); The RoundRectangle2D class represents a rectangle with rounded corners defined by a location (x, y), a dimension (w x h), and the width and height of the corner arc. The RoundRectangle2D.Float and RoundRectangle2D.Double subclasses specify a round rectangle in float and double precision. The rounded rectangle is specified with following parameters:

Location Width Height Width of the corner arc

Height of the corner acr

To set the location, size, and arcs of a RoundRectangle2D object, use the method setRoundRect(double a, double y, double w, double h, double arcWidth, double arcHeight). For example: // draw RoundRectangle2D.Double g2.draw(new RoundRectangle2D.Double(x, y, rectwidth, rectheight, 10, 10)); Ellipse The Ellipse2D class represents an ellipse defined by a bounding rectangle. The Ellipse2D.Float and Ellipse2D.Double subclasses specify an ellipse in float and double precision. Ellipse is fully defined by a location, a width and a height. For example: // draw Ellipse2D.Double g2.draw(new Ellipse2D.Double(x, y, rectwidth, rectheight)); Arc To draw a piece of an ellipse, you use the Arc2D class. This class represents an arc defined by a bounding rectangle, a start angle, an angular extent, and a closure type. The Arc2D.Float and Arc2D.Double subclasses specify an ellipse in float and double precision. The Arc2D class defines the following three types of arcs, represented by corresponding constants in this class: OPEN, PIE and CHORD.

Several methods set the size and parameters of the arc:


Directly, by coordinates By supplied Point2D and Dimension2D By copying an existing Arc2D

Also, you can use the setArcByCenter method to specify an arc from a center point, given by its coordinates and a radius.

// draw Arc2D.Double g2.draw(new Arc2D.Double(x, y, rectwidth, rectheight, 90, 135, Arc2D.OPEN)); The ShapesDemo2D.java code example contains implementations off all described geometric primitives. For more information about classes and methods represented in this section see the java.awt.geom specification.

Drawing Arbitrary Shapes You have already learned how to draw most of shapes represented in the java.awt.geom package. To create more complicated geometry, such as polygons, polylines, or stars you use another class from this package, GeneralPath. This class implements the Shape interface and represents a geometric path constructed from lines, and quadratic and cubic curves. The three constructors in this class can create the GeneralPath object with the default winding rule (WIND_NON_ZERO), the given winding rule (WIND_NON_ZERO or WIND_EVEN_ODD), or the specified initial coordinate capacity. The winding rule specifies how the interior of a path is determined. public void Paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... } To create an empty GeneralPath instance call new GeneralPath() and then add segments to the shape by using the following methods: moveTo(float x, float y) Moves the current point of the path to the given point lineTo(float x, float y) Adds a line segment to the current path quadTo(float ctrlx, float ctrly, float x2, floaty2) Adds a quadratic curve segment to the current path curveTo(float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x3, floaty3)

Adds a cubic curve segment to the current path closePath() Closes the current path The following example illustrates how to draw a polyline by using GeneralPath: // draw GeneralPath (polyline) int x2Points[] = {0, 100, 0, 100}; int y2Points[] = {0, 50, 50, 0}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]); for (int index = 1; index < x2Points.length; index++) { polyline.lineTo(x2Points[index], y2Points[index]); }; g2.draw(polyline); This example illustrates how to draw a polygon by using GeneralPath: // draw GeneralPath (polygon) int x1Points[] = {0, 100, 0, 100}; int y1Points[] = {0, 50, 50, 0}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for (int index = 1; index < x1Points.length; index++) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); Note that the only difference between two last code examples is the closePath() method. This method makes a polygon from a polyline by drawing a straight line back to the coordinates of the last moveTo.

To add a specific path to the end of your GeneralPath object you use one of the append() methods. The ShapesDemo2D.java code example contains additional implementations of arbitrary shapes. Drawing Arbitrary Shapes You have already learned how to draw most of shapes represented in the java.awt.geom package. To create more complicated geometry, such as polygons, polylines, or stars you use another class from this package, GeneralPath. This class implements the Shape interface and represents a geometric path constructed from lines, and quadratic and cubic curves. The three constructors in this class can create the GeneralPath object with the default winding rule (WIND_NON_ZERO), the given winding rule (WIND_NON_ZERO or WIND_EVEN_ODD), or the specified initial coordinate capacity. The winding rule specifies how the interior of a path is determined. public void Paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... } To create an empty GeneralPath instance call new GeneralPath() and then add segments to the shape by using the following methods: moveTo(float x, float y) Moves the current point of the path to the given point lineTo(float x, float y) Adds a line segment to the current path quadTo(float ctrlx, float ctrly, float x2, floaty2) Adds a quadratic curve segment to the current path curveTo(float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x3, floaty3) Adds a cubic curve segment to the current path closePath() Closes the current path

The following example illustrates how to draw a polyline by using GeneralPath: // draw GeneralPath (polyline) int x2Points[] = {0, 100, 0, 100}; int y2Points[] = {0, 50, 50, 0}; GeneralPath polyline =

new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]); for (int index = 1; index < x2Points.length; index++) { polyline.lineTo(x2Points[index], y2Points[index]); }; g2.draw(polyline); This example illustrates how to draw a polygon by using GeneralPath: // draw GeneralPath (polygon) int x1Points[] = {0, 100, 0, 100}; int y1Points[] = {0, 50, 50, 0}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for (int index = 1; index < x1Points.length; index++) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); Note that the only difference between two last code examples is the closePath() method. This method makes a polygon from a polyline by drawing a straight line back to the coordinates of the last moveTo. To add a specific path to the end of your GeneralPath object you use one of the append() methods. The ShapesDemo2D.java code example contains additional implementations of arbitrary shapes. Stroking and Filling Graphics Primitives You already know how to create different geometric primitives and more complicated shapes. This lesson teaches how to add some color and fancy outlines to your graphics and represents filling and stroking:

Filling is a process of painting the shapes interior with solid color or a color gradient, or a texture pattern

Stroking is a process of drawing a shapes outline applying stroke width, line style, and color attribute

To apply fancy line styles and fill patterns to geometric primitives change the stroke and paint attributes in the Graphics2D context before rendering. For example, draw a dashed line by creating an appropriate Stroke object. To add this stroke to the Graphics2D context before you render the line call the setStroke method . Similarly, you apply a gradient fill to a Shape object by creating a GradientPaint object and adding it to the Graphics2D context. The following code lines enrich geometric primitives with filling and stroking context: // draw RoundRectangle2D.Double final static float dash1[] = {10.0f}; final static BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); // fill Ellipse2D.Double redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE); g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(0, 0, 100, 50)); The ShapesDemo2D.java code example represents additional implementations of stoking and filling. Defining Fancy Line Styles and Fill Patterns Using the Java 2D Stroke and Paint classes, you can define fancy line styles and fill patterns. Line Styles Line styles are defined by the stroke attribute in the Graphics2D rendering context. To set the stroke attribute, you create a BasicStroke object and pass it into the Graphics2D setStroke method. A BasicStroke object holds information about the line width, join style, end-cap style, and dash style. This information is used when a Shape is rendered with the draw method.

The line width is the thickness of the line measured perpendicular to its trajectory. The line width is specified as a float value in user coordinate units, which are roughly equivalent to 1/72 of an inch when the default transform is used. The join style is the decoration that is applied where two line segments meet. BasicStroke supports the following three join styles: JOIN_BEVEL

JOIN_MITER JOIN_ROUND The end-cap style is the decoration that is applied where a line segment ends. BasicStroke supports the following three end-cap styles: CAP_BUTT CAP_ROUND CAP_SQUARE The dash style defines the pattern of opaque and transparent sections applied along the length of the line. The dash style is defined by a dash array and a dash phase. The dash array defines the dash pattern. Alternating elements in the array represent the dash length and the length of the space between dashes in user coordinate units. Element 0 represents the first dash, element 1 the first space, and so on. The dash phase is an offset into the dash pattern, also specified in user coordinate units. The dash phase indicates what part of the dash pattern is applied to the beginning of the line. Fill Patterns Fill patterns are defined by the paint attribute in the Graphics2D rendering context. To set the paint attribute, you create an instance of an object that implements the Paint interface and pass it into the Graphics2D setPaint method. The following three classes implement the Paint interface: Color, GradientPaint, and TexturePaint. To create a GradientPaint, you specify a beginning position and color and an ending position and color. The gradient changes proportionally from one color to the other color along the line connecting the two positions. For example:

The pattern for a TexturePaint class is defined by a BufferedImage class. To create a TexturePaint object, you specify the image that contains the pattern and a rectangle that is used to replicate and anchor the pattern. The following image represents this feature:

Lesson: Working with Text APIs This lesson introduces you to the concept of working with text APIs to apply text rendering capabilities. Already in this trail, you have used basic Java 2D text APIs and know how to set a font and position, and how to draw text. This lesson expands on that material to help you develop an understanding of how to use those APIs and moves further into the capabilities of Java 2D text display. These topics are discussed in the following sections. Selecting a font This section explains how to use the methods of the Font class to determine which fonts are available on your system, to create a Font object, and obtain information about a font family. Measuring Text This section explains how to properly measure text by using an instance of the FontMetrics class. Advanced Text Display This section explains how to position and render a paragraph of styled text, how to display antialiased text, and how to use text attributes to style text.

Selecting a Font Java 2D defines the following five logical font families:

Dialog DialogInput Monospaced Serif SansSerif

These fonts are available on any Java platform and can be thought of as aliases for some underlying font that has the properties implied by its name. A Serif font is a font similar to Times New Roman, which is commonly used in print. A Sans Serif font is more typical for onscreen use. These fonts can be customized for the locale of the user. In addition these fonts support the widest range of code points (unicode characters). Apart from the family, fonts have other attributes, the most important of which are style and size. Styles are Bold and Italic. The default Java 2D font is 12 pt Dialog. This font is a typical point size for reading text on a normal 72120 DPI display device. An application can create an instance of this font directly by specifying the following: Font font = new Font("Dialog", Font.PLAIN, 12); In addition to the logical fonts, Java software provides access to other fonts that are installed on your system. The names of all available font families can be found by calling the following: GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String []fontFamilies = ge.getAvailableFontFamilyNames(); The FontSelector sample program (available in FontSelector.java) illustrates how to locate and select these fonts. You can use this example to view how Sans Serif appears on your system. These other fonts are called physical fonts. Note: Applications should not assume that any particular physical font is present. However, the logical fonts are a safe choice because they are always present.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. Sometimes, an application cannot depend on a font being installed on the system, usually because the font is a custom font that is not otherwise available. In this case, the application must include the font. This lesson shows how to obtain a TrueType font, the most commonly used font type on modern operating systems, to a java.awt.Font object. You can use either of these methods: Font java.awt.Font.createFont(int fontFormat, InputStream in); Font java.awt.Font.createFont(int fontFormat, File fontFile); To identify a TrueType font, fontFormat must be the constant Font.TRUETYPE_FONT. Font font = Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf")); Accessing the font directly from a file must be more convenient for some cases. However, an InputStream might be needed if your code is unable to access file system resources, or if the font is packaged in a Java Archive (JAR) file along with the rest of the application or applet. The returned Font instance can then be used with the Font.deriveFont(..) methods to derive a version that is the required size. For example: try { /* Returned font is of pt size 1 */ Font font = Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf")); /* derive and return a 12 pt version : need to use float otherwise * it would be interpreted as style */ return font.deriveFont(12f); } catch (IOException ioe); } catch (FontFormatException ffe); } It is important to use deriveFont() because fonts which are created by application are not part of the set of fonts known to the underlying font system. Because deriveFont works from the original created font it does not have this limitation.

The solution for this problem is to register the created font with the graphics environment. For example: try { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf")); } catch (IOException ioe); } catch (FontFormatException ffe); } After this step is done, the font is available in calls to getAvailableFontFamilyNames() and can be used in font constructors.

Measuring Text To properly measure text, you need to learn a few methods and some mistakes to avoid. Font metrics are measurements of text rendered by a Font object such as the height of a line of text in the font. The most common way to measure text is to use a FontMetrics instance which encapsulates this metrics information. For example: // get metrics from the graphics FontMetrics metrics = graphics.getFontMetrics(font); // get the height of a line of text in this font and render context int hgt = metrics.getHeight(); // get the advance of my text in this font and render context int adv = metrics.stringWidth(text); // calculate the size of a box to hold the text with some padding. Dimension size = new Dimension(adv+2, hgt+2); This way is sufficient for many applications to evenly space lines of text or to size Swing components. Note the following: The metrics are obtained from the Graphics class, because this class encapsulates the FontRenderContext, which is needed to accurately measure text. At screen resolutions, fonts are adjusted for ease of reading. As text size increases, this adjustment does not scale linearly. So, at 20 pt, a font will not display text exactly twice

the length as it would at 10 pt. Besides the text itself and the font, the other important piece of information needed to measure text is the FontRenderContext. This method includes the transform from user space to device pixels that is used in measuring text. The height is reported without reference to any particular string of text. It is useful, for example in, a text editor where you want the same line spacing between each line of text. stringWidth() returns the advance width of the text. Advance width is the distance from the origin of the text to the position of a subsequently rendered string. When using these methods to measure text, note that the text can extend in any direction outside of a rectangle, defined by the font height and the advance of the string.

Typically, the simplest solution is to ensure that the text is not clipped, for example, by components that surround the text. Add padding in cases where the text might otherwise be clipped. If this solution is insufficient, other text measurement APIs in the Java 2D software can return rectangular bounding boxes. These boxes account for the height of the specific

text to be measured and for pixelization effects.

Advanced Text Display Displaying Antialiased Text by Using Rendering Hints Using Text Attributes to Style Text Drawing Multiple Lines of Text Home Page > 2D Graphics > Working with Text APIs Previous Trail Next Advanced Text Display The Java 2D API provides mechanisms to support sophisticated text layout. This section describes following features of advanced text display. Displaying Antialiased Text by Using Rendering Hints This section explains how to control the rendering quality through the use of rendering hints. Using Text Attributes to Style Text This section explains how to use the TextAttribute class to underline or strikethough text. Drawing Multiple Lines of Text This section explains how to position and render a paragraph of styled text by using the TextLayout and LineBreakMeasurer classes.

Displaying Antialiased Text by Using Rendering Hints Java 2D text rendering can be affected by rendering hints. Recall that the most important text drawing method is the following:

Graphics.drawString(String s, int x, int y);

Usually, this method draws each glyph in a string of text with a solid color and each pixel that is on in that glyph is set to that colour. This type of drawing produces the highest contrast text, but sometimes with jagged (aliased) edges. Text antialiasing is a technique used to smooth the edges of text on a screen. The Java 2D API enables applications to specify whether this technique should be used and what algorithm to use by applying a text rendering hint to the Graphics. The most common rendering hint blends the foreground (text) color with the onscreen background pixels at the edges of the text. To request this hint an application must invoke the following: graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, (RenderingHints.VALUE_TEXT_ANTIALIAS_ON); The following figure illustrates the antialiasing capability.

If used inappropriately this method can make the text appear overly fuzzy. In such cases, a better hint to use is the following: graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, (RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); This method automatically uses information in the font itself to decide whether to use antialiasing or to use solid colors. LCD displays have a property that the Java 2D API can use to produce text that isn't as fuzzy as typical antialiasing but is more legible

Using Text Attributes to Style Text Applications typically need the capability to apply the following text attributes: Underline A line that is drawn underneath text Strikethrough A horizontal line that is drawn through the text

Superscript or Subscript A text or a letter that appears slightly above a line or correspondingly below a line Kerning The adjustment of the space between characters

These and other text attributes can be applied by using the Java 2D TextAttribute class. To apply these text attributes by add them to a Font object. For example: Map<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>(); map.put(TextAttribute.KERNING, TextAttribute.KERNING_ON); font = font.deriveFont( map ); graphics.setFont( font ); The code example represented below shows the application of text attributes in the following order: 1. Sample string (no text attributes applied) 2. Kerning 3. Kerning and Underlining 4. Kerning,Underlining and Strikethrough 5. Kerning,Underlining, Strikethrough and Color

Drawing Multiple Lines of Text If you have a paragraph of styled text that you would like to fit within a specific width, you can use the LineBreakMeasurer class. This class enables styled text to be broken into lines so that they fit within a particular visual advance. Each line is returned as a TextLayout object, which represents unchangeable, styled character data. However, this class also enables access to layout information. The getAscent and getDescent methods of TextLayout return information about the font that is used to position the lines in the component. The text is stored as an AttributedCharacterIterator object so that the font and point size attributes can be stored with the text. The following applet positions a paragraph of styled text within a component, using LineBreakMeasurer, TextLayout and AttributedCharacterIterator.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in LineBreakSample.java. The following code creates an iterator with the string vanGogh. The start and end of the iterator is retrieved and a new LineBreakMeasurer is created from the iterator. AttributedCharacterIterator paragraph = vanGogh.getIterator(); paragraphStart = paragraph.getBeginIndex(); paragraphEnd = paragraph.getEndIndex(); FontRenderContext frc = g2d.getFontRenderContext(); lineMeasurer = new LineBreakMeasurer(paragraph, frc); The size of the window is used to determine where the line should break. Also a TextLayout object is created for each line in the paragraph. // Set break width to width of Component. float breakWidth = (float)getSize().width; float drawPosY = 0; // Set position to the index of the first character in the paragraph. lineMeasurer.setPosition(paragraphStart); // Get lines from until the entire paragraph has been displayed. while (lineMeasurer.getPosition() < paragraphEnd) { TextLayout layout = lineMeasurer.nextLayout(breakWidth); // Compute pen x position. If the paragraph is right-to-left we // will align the TextLayouts to the right edge of the panel. float drawPosX = layout.isLeftToRight() ? 0 : breakWidth - layout.getAdvance(); // Move y-coordinate by the ascent of the layout. drawPosY += layout.getAscent(); // Draw the TextLayout at (drawPosX, drawPosY). layout.draw(g2d, drawPosX, drawPosY); // Move y-coordinate in preparation for next layout. drawPosY += layout.getDescent() + layout.getLeading();

}Download Search

the the

JDK Tutorials

The TextLayout class is not frequently created directly by applications. However, this class is useful when applications need to work directly with text that has had styles (text attributes) applied at specific positions in text. For example, to draw a single word italicized in a paragraph, an application would need to perform measurements and set the font for each substring. If the text is bidirectional, this task is not so easy to do correctly. Creating a TextLayout object from an AttributedString object handles this problem for you. Consult the Java SE specification for more information about TextLayout. Lesson: Working with Images As you have already learned from the Overview lesson, Images are described by a width and a height, measured in pixels, and have a coordinate system that is independent of the drawing surface. There are a number of common tasks when working with images.

Loading an external GIF, PNG JPEG image format file into Java 2D's internal image representation. Directly creating a Java 2D image and rendering to it. Drawing the contents of a Java 2D image on to a drawing surface. Saving the contents of a Java 2D image to an external GIF, PNG, or JPEG image file.

This lesson teaches you the basics of loading, displaying, and saving images. The are two main classes that you must learn about to work with images:

The java.awt.Image class is the superclass that represents graphical images as rectangular arrays of pixels. The java.awt.image.BufferedImage class, which extends the Image class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.

The BufferedImage class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage is a subclass of Image it can be rendered by the Graphics and Graphics2D methods that accept an Image parameter.

A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage. A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image's pixel data. The Raster performs the following functions:

Represents the rectangular coordinates of the image Maintains image data in memory Provides a mechanism for creating multiple subimages from a single image data buffer Provides methods for accessing specific pixels within the image

The basic operations with images are represented in the following sections: Reading/Loading an image This section explains how to load an image from an external image format into a Java application using the Image I/O API Drawing an image This section teaches how to display images using the drawImage method of the Graphics and Graphics2D classes. Creating and drawing To an image This section describes how to create an image and how to use the image itself as a drawing surface. Writing/saving an image
This section explains how to save created images in an appropriate format.

Reading/Loading an Image When you think of digital images, you probably think of sampled image formats such as the JPEG image format used in digital photography, or GIF images commonly used on web pages. All

programs that can use these images must first convert them from that external format into an internal format. Java 2D supports loading these external image formats into its BufferedImage format using its Image I/O API which is in the javax.imageio package. Image I/O has built-in support for GIF, PNG, JPEG, BMP, and WBMP. Image I/O is also extensible so that developers or administrators can "plug-in" support for additional formats. For example, plug-ins for TIFF and JPEG 2000 are separately available. To load an image from a specific file use the following code: BufferedImage img = null; try { img = ImageIO.read(new File("strawberry.jpg")); } catch (IOException e) { } Image I/O recognises the contents of the file as a JPEG format image, and decodes it into a BufferedImage which can be directly used by Java 2D. LoadImageApp.java shows how to display this image. If the code is running in an applet, then its just as easy to obtain the image from the applet codebase : try { URL url = new URL(getCodeBase(), "strawberry.jpg"); img = ImageIO.read(url); } catch (IOException e) { } The getCodeBase method used in this example returns the URL of the directory containing this applet. The following example shows how to use the getCodeBase method to load the strawberry.jpg file.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

LoadImageApp.java contains the complete code for this example and this applet requires the strawberry.jpg image file. In addition to reading from files or URLS, Image I/O can read from other sources, such as an InputStream. ImageIO.read() is the most straightforward convenience API for most applications, but the javax.imageio.ImageIO provides many more static methods for more advanced usages of the Image I/O API. The collection of methods on this class represent just a subset of the rich set of APIs for discovering information about the images and for controlling the image decoding (reading) process. We will explore some of the other capabilities of Image I/O later in the Writing/saving an image section. More information can be found in the Image I/O guide. Drawing an Image As you have already learned, the Graphics.drawImage method draws an image at a specific location: boolean Graphics.drawImage(Image img, int x, int y, ImageObserver observer); The x,y location specifies the position for the top-left of the image. The observer parameter notifies the application of updates to an image that is loaded asynchronously. The observer parameter is not frequently used directly and is not needed for the BufferedImage class, so it usually is null. The described method addresses only the case where the entire image is to be drawn, mapping image pixels to user space coordinates 1:1. Sometimes applications require to draw a part of the image (a sub-image), or scale the image to cover a particular area of the drawing surface, or transform or filter the image before drawing. The overloads of the drawImage() method perform these operations. For example, the following overload of the drawImage() method enables you to draw as much of a specified area of the specified image as is currently available, scaling it to fit inside the specified area of the destination drawable surface: boolean Graphics.drawImage(Image img, int dstx1, int dsty1, int dstx2, int dsty2, int srcx1, int srcy1, int srcx2, int srcy2, ImageObserver observer);

The src parameters represent the area of the image to copy and draw. The dst parameters display the area of the destination to cover by the the source area. The dstx1, dsty1 coordinates define the location to draw the image. The width and height dimensions on the destination area are calculated by the following expressions: (dstx2-dstx1), (dsty2-dsty1). If the dimensions of the source and destinations areas are different, the Java 2D API will scale up or scale down, as needed. The following code example divides an image into four quadrants and randomly draws each quadrant of the source image into a different quadrant of the destination.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in JumbledImageApplet.java. This example uses the following code to paint the jumbled duke_skateboard.jpg image. It iterates over the four sub-images of the source, drawing each in turn into a randomly selected destination quadrant. /* divide the image 'bi' into four rectangular areas and draw each * of these areas in to a different part of the image, so as to * jumble up the image. * 'cells' is an array which has been populated with values * which redirect drawing of one subarea to another subarea. */ int cellWidth = bi.getWidth(null)/2; int cellHeight = bi.getHeight(null)/2; for (int x=0; x<2; x++) { int sx = x*cellWidth; for (int y=0; y<2; y++) { int sy = y*cellHeight; int cell = cells[x*2+y]; int dx = (cell / 2) * cellWidth; int dy = (cell % 2) * cellHeight; g.drawImage(bi, dx, dy, dx+cellWidth, dy+cellHeight, sx, sy, sx+cellWidth, sy+cellHeight, null); } }

Filtering Images

In addition to copying and scaling images, the Java 2D API also filter an image. Filtering is drawing or producing a new image by applying an algorithm to the pixels of the source image. Image filters can be applied by using the following method: void Graphics2D.drawImage(BufferedImage img, BufferedImageOp op, int x, int y) The BufferedImageOp parameter implements the filter. The following applet represents an image drawn on top of text. Drag the slider to show more or less of the text through the image and make the image more or less transparent.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The following code shows how the filter action is done by operating on a BufferedImage object with an alpha channel and rescales that alpha channel by using the RescaleOp object. The alpha channel determines the translucency of each pixel. It also specifies the degree to which this image overwrites. /* Create an ARGB BufferedImage */ BufferedImage img = ImageIO.read(imageSrc); int w = img.getWidth(null); int h = img.getHeight(null); BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.getGraphics(); g.drawImage(img, 0, 0, null); /* Create a rescale filter op that makes the image 50% opaque */ float[] scales = { 1f, 1f, 1f, 0.5f }; float[] offsets = new float[4]; RescaleOp rop = new RescaleOp(scales, offsets, null); /* Draw the image, applying the filter */ g2d.drawImage(bi, rop, 0, 0);

The complete example represented in SeeThroughImageApplet.java includes the code that uses the slider to adjust the transparency from the initial 50%. This example also requires the duke_skateboard.jpg image.

The RescaleOp object is just one of many filters that can be created. The Java 2D API has several built in filters including the following:

ConvolveOp. Each output pixel is computed from surrounding pixels in the source image. It may be used to blur or sharpen images. AffineTransformOp. This filter maps pixels in the source to a different position in the destination by applying a transformation on the pixel location. LookupOp. This filter uses an application supplied lookup table to remap pixel colors. RescaleOp. This filter multiplies the colors by some factor. Can be used to lighten or darken the image, to increase or reduce its opacity, etc.

The following example uses each of the described filters as well as scaling:

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in ImageDrawingApplet.java and this applet requires the bld.jpg image. Use the drop-down menu to select an image scaling or filtering operation. Creating and Drawing to an Image We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer. In this case, you can create a BufferedImage object manually, using three constructors of this class: new BufferedImage(width, height, type) - constructs a BufferedImage of one of the predefined image types. new BufferedImage(width, height, type, colorModel) constructs a BufferedImage of one of the predefined image types: TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. new BufferedImage(colorModel, raster, premultiplied, properties) - constructs a new BufferedImage with a specified ColorModel and Raster.

On the other hand, we can use methods of the Component class. These methods can analyze the display resolution for the given Component or GraphicsConfiguration and create an image of an appropriate type.

Component.createImage(width,

height) GraphicsConfiguration.createCompati bleImage(width, height) GraphicsConfiguration.createCompati bleImage(width, height, transparency)

GraphicsConfiguration returns an object of BufferedImage type, but the Component returns an object of Image type, if you need a BufferedImage object instead then you can perform an instanceof and cast to a BufferedImage in your code. As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a createGraphics() method of the BufferedImage class for this purpose: ... BufferedImage off_Image = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = off_Image.createGraphics(); Another interesting use of offscreen images is an automatic double buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen. Java 2D also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the Image class: The getCapabilities method allows you to determine whether the image is currently accelerated. The setAccelerationPriority method lets you set a hint about how important acceleration is for the image.

The getAccelerationPriority method gets a hint about the acceleration importance.

Creating and Drawing to an Image We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer. In this case, you can create a BufferedImage object manually, using three constructors of this class: new BufferedImage(width, height, type) - constructs a BufferedImage of one of the predefined image types. new BufferedImage(width, height, type, colorModel) constructs a BufferedImage of one of the predefined image types: TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. new BufferedImage(colorModel, raster, premultiplied, properties) - constructs a new BufferedImage with a specified ColorModel and Raster.

On the other hand, we can use methods of the Component class. These methods can analyze the display resolution for the given Component or GraphicsConfiguration and create an image of an appropriate type.

Component.createImage(width,

height) GraphicsConfiguration.createCompati bleImage(width, height) GraphicsConfiguration.createCompati bleImage(width, height, transparency)

GraphicsConfiguration returns an object of BufferedImage type, but the Component returns an object of Image type, if you need a BufferedImage object instead then you can perform an instanceof and cast to a BufferedImage in your code.

As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a createGraphics() method of the BufferedImage class for this purpose: ... BufferedImage off_Image = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = off_Image.createGraphics(); Another interesting use of offscreen images is an automatic double buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen. Java 2D also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the Image class: The getCapabilities method allows you to determine whether the image is currently accelerated. The setAccelerationPriority method lets you set a hint about how important acceleration is for the image. The getAccelerationPriority method gets a hint about the acceleration importance.

Creating and Drawing to an Image We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer. In this case, you can create a BufferedImage object manually, using three constructors of this class: new BufferedImage(width, height, type) - constructs a BufferedImage of one of the predefined image types.

new BufferedImage(width, height, type, colorModel) constructs a BufferedImage of one of the predefined image types: TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. new BufferedImage(colorModel, raster, premultiplied, properties) - constructs a new BufferedImage with a specified ColorModel and Raster.

On the other hand, we can use methods of the Component class. These methods can analyze the display resolution for the given Component or GraphicsConfiguration and create an image of an appropriate type.

Component.createImage(width,

height) GraphicsConfiguration.createCompati bleImage(width, height) GraphicsConfiguration.createCompati bleImage(width, height, transparency)

GraphicsConfiguration returns an object of BufferedImage type, but the Component returns an object of Image type, if you need a BufferedImage object instead then you can perform an instanceof and cast to a BufferedImage in your code. As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a createGraphics() method of the BufferedImage class for this purpose: ... BufferedImage off_Image = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = off_Image.createGraphics(); Another interesting use of offscreen images is an automatic double buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen.

Java 2D also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the Image class: The getCapabilities method allows you to determine whether the image is currently accelerated. The setAccelerationPriority method lets you set a hint about how important acceleration is for the image. The getAccelerationPriority method gets a hint about the acceleration importance.

A Basic Printing Program This section explains how to create a basic printing program that displays a print dialog and prints the text "Hello World" to the selected printer. Printing task usually consists of two parts: Job control Creating a print job, associating it with a printer, specifying the number of copies, and user print dialog interaction. Page Imaging Drawing content to a page, and managing content that spans pages (pagination).

First create the printer job. The class representing a printer job and most other related classes is located in the java.awt.print package. import java.awt.print.*; PrinterJob job = PrinterJob.getPrinterJob(); Next provide code that renders the content to the page by implementing the Printable interface. class HelloWorldPrinter implements Printable { ... } .. job.setPrintable(new HelloWorldPrinter());

An application typically displays a print dialog so that the user can adjust various options such as number of copies, page orientation, or the destination printer. boolean doPrint = job.printDialog(); This dialog appears until the user either approves or cancels printing. The doPrint variable will be true if the user gave a command to go ahead and print. If the doPrint variable is false, the user cancelled the print job. Since displaying the dialog at all is optional, the returned value is purely informational. If the doPrint variable is true, then the application will request that the job be printed by calling the PrinterJob.print method. if (doPrint) { try { job.print(); } catch (PrinterException e) { /* The job did not successfully complete */ } } The PrinterException will be thrown if there is problem sending the job to the printer. However, since the PrinterJob.print method returns as soon as the job is sent to the printer, the user application cannot detect paper jams or paper out problems. This job control boilerplate is sufficient for basic printing uses. The Printable interface has only one method: public int print(Graphics graphics, PageFormat pf, int page) throws PrinterException; The PageFormat class describes the page orientation (portrait or landscape) and its size and imageable area in units of 1/72nd of an inch. Imageable area accounts for the margin limits of most printers (hardware margin). The imageable area is the space inside these margins, and in practice if is often further limited to leave space for headers or footers. A page parameter is the zero-based page number that will be rendered. The following code represents the full Printable implementation: import java.awt.print.*; import java.awt.*;

public class HelloWorldPrinter implements Printable { public int print(Graphics g, PageFormat pf, int page) throws PrinterException { if (page > 0) { /* We have only one page, and 'page' is zero-based */ return NO_SUCH_PAGE; } /* User (0,0) is typically outside the imageable area, so we must * translate by the X and Y values in the PageFormat to avoid clipping */ Graphics2D g2d = (Graphics2D)g; g2d.translate(pf.getImageableX(), pf.getImageableY()); /* Now we perform our rendering */ g.drawString("Hello world!", 100, 100); /* tell the caller that this page is part of the printed document */ return PAGE_EXISTS; } } The complete code for this example is in HelloWorldPrinter.java. Sending a Graphics instance to the printer is essentially the same as rendering it to the screen. In both cases you need to perform the following steps: To draw a test string is as easy as the other operations that were described for drawing to a Graphics2D. Printer graphics have a higher resolution, which should be transparent to most code. The Printable.print() method is called by the printing system, just as the Component.paint() method is called to paint a Component on the display. The printing system will call the Printable.print() method for page 0, 1,.. etc until the print() method returns NO_SUCH_PAGE.

The print() method may be called with the same page index multiple times until the document is completed. This feature is applied when the user specifies attributes such as multiple copies with collate option. The PageFormat's imageable area determines the clip area. Imageable area is also important in calculating pagination, or how to span content across printed pages, since page breaks are determined by how much can fit on each page.

Note: A call to the print() method may be skipped for certain page indices if the user has specified a different page range that does not involve a particular page index.

Using Print Setup Dialogs Traditionally, the user wants to see the page setup and print dialog boxes. From the print dialog you can select a printer, specify pages to print, and set the number of copies.

An application displays a print dialog when the user presses a button related to the print command, or chooses an item from the print menu. To display this dialog, call the printDialog method of the PrinterJob class: PrinterJob pj = PrinterJob.getPrinterJob(); ... if (pj.printDialog()) { try {pj.print();} catch (PrinterException exc) { System.out.println(exc); } } ... This method returns true if the user clicked OK to leave the dialog, and false otherwise. The user's choices in the dialog are constrained based on the number and format of the pages that have been set to the PrinterJob. The printDialog method in the above code snippet opens a native print dialog. The PrintDialogExample.java code example shows how to display a cross-platform print dialog. You can change the page setup information contained in the PageFormat object by using the page setup dialog.

To display the page setup dialog, call the pageDialog method of the PrinterJob class. PrinterJob pj = PrinterJob.getPrinterJob(); PageFormat pf = pj.pageDialog(pj.defaultPage()); The page setup dialog is initialized using the parameter passed to pageDialog. If the user clicks the OK button in the dialog, the PageFormat instance will be created in accordance with the users selections, and then returned. If the user cancels the dialog, pageDialog returns the original unchanged PageFormat. Usually the Java 2D Printing API requires an application to display a print dialog, but in sometimes it's possible to print without showing any dialog at all. This type of printing is called silent printing. It may be useful in specific cases, such as, when you need to print a particular database weekly report. In the other cases it is always recommended to inform the user when a print process is starting. Using Print Setup Dialogs Traditionally, the user wants to see the page setup and print dialog boxes. From the print dialog you can select a printer, specify pages to print, and set the number of copies.

An application displays a print dialog when the user presses a button related to the print command, or chooses an item from the print menu. To display this dialog, call the printDialog method of the PrinterJob class: PrinterJob pj = PrinterJob.getPrinterJob(); ...

if (pj.printDialog()) { try {pj.print();} catch (PrinterException exc) { System.out.println(exc); } } ... This method returns true if the user clicked OK to leave the dialog, and false otherwise. The user's choices in the dialog are constrained based on the number and format of the pages that have been set to the PrinterJob. The printDialog method in the above code snippet opens a native print dialog. The PrintDialogExample.java code example shows how to display a cross-platform print dialog. You can change the page setup information contained in the PageFormat object by using the page setup dialog.

To display the page setup dialog, call the pageDialog method of the PrinterJob class. PrinterJob pj = PrinterJob.getPrinterJob(); PageFormat pf = pj.pageDialog(pj.defaultPage()); The page setup dialog is initialized using the parameter passed to pageDialog. If the user clicks the OK button in the dialog, the PageFormat instance will be created in accordance with the users

selections, and then returned. If the user cancels the dialog, pageDialog returns the original unchanged PageFormat. Usually the Java 2D Printing API requires an application to display a print dialog, but in sometimes it's possible to print without showing any dialog at all. This type of printing is called silent printing. It may be useful in specific cases, such as, when you need to print a particular database weekly report. In the other cases it is always recommended to inform the user when a print process is starting.

Working with Print Services and Attributes From the previous lessons you have learned that the Java 2D printing API supports page imaging, displays print and page setup dialogs, and specifies printing attributes. Printing services is another key component of any printing subsystem. The Java Print Service (JPS) API extends the current Java 2D printing features to offer the following functionality:

Application discovers printers that cater to its needs by dynamically querying the printer capabilities. Application extends the attributes included with the JPS API. Third parties can plug in their own print services with the Service Provider Interface, which print different formats, including Postscript, PDF, and SVG.

The Java Print Service API consists of four packages:

The javax.print package provides the principal classes and interfaces for the Java Print Service API. It enables client and server applications to:

Discover and select print services based on their capabilities.

Specify the format of print data. Submit print jobs to services that support the document type to be printed.

Document Type Specification The DocFlavor class represents format of the print data, such as JPEG or PostScript. The DocFlavor format consists of two parts: a MIME type and a representation class name. A MIME type describes the format, and a document representation class name indicates how the document is delivered to the printer or output stream. An application uses the DocFlavor and an attribute set to find printers with the capabilities specified by the attribute set. This code sample demonstrates obtaining an array of StreamPrintServiceFactory objects that can return StreamPrintService objects able to convert a GIF image into PostScript: DocFlavor flavor = DocFlavor.INPUT_STREAM.GIF; String psMimeType = DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType(); StreamPrintServiceFactory[] psfactories = StreamPrintServiceFactory.lookupStreamPrintServiceFactories( flavor, psMimeType); Attribute Definitions The javax.print.attribute and javax.print.attribute.standard packages define print attributes which describe the capabilities of a print service, specify the requirements of a print job, and track the progress of the print job. For example, if you would like to use A4 paper format and print three copies of your document you will have to create a set of the following attributes implementing the PrintRequestAttributeSet interface: PrintRequestAttributeSet attr_set = new HashPrintRequestAttributeSet(); attr_set.add(MediaSize.ISO_A4); attr_set.add(new Copies(3)); Then you must pass the attribute set to the print job's print method, along with the DocFlavor. Print Service Discovery An application invokes the static methods of the abstract class PrintServiceLookup to locate print services that have the capabilities to satisfy the application's print request. For example, in order to print two copies of a double-sided document, the application first needs to find printers that have double-sided printing capability:

DocFlavor doc_flavor = DocFlavor.INPUT_STREAM.PDF; PrintRequestAttributeSet attr_set = new HashPrintRequestAttributeSet(); attr_set.add(new Copies(2)); attr_set.add(Sides.DUPLEX); PrintService[] service = PrintServiceLookup.lookupPrintServices(doc_flavor, attr_set); Common Use of the API In conclusion, the Java Print Service API performs the following steps to process a print request:
1. Chooses a DocFlavor.

2. Creates a set of attributes. 3. Locates a print service that can handle the print request as specified by the DocFlavor and the attribute set. 4. Creates a Doc object encapsulating the DocFlavor and the actual print data. 5. Gets a print job, represented by DocPrintJob, from the print service. 6. Calls the print method of the print job. For more information about Java Print Service, see Java 2D Print Service API User Guide.

Printing the Contents of a User Interface Another common printing task is to print the contents of a window or a frame, either in whole, or in part. The window may contain the following components: toolbars, buttons sliders, text labels, scrollable text areas, images, and other graphical content. All of these components are printed using the following methods of the Java 2D printing API: java.awt.Component.print(Graphics g); java.awt.Component.printAll(Graphics g); The following figure represents a simple user interface.

The code to create this UI is located in the sample program PrintUIWindow.java. To print this window, modify the code in the earlier examples which printed text or images. The resulting code should appear as follows: public int print(Graphics g, PageFormat pf, int page) throws PrinterException { if (page > 0) { return NO_SUCH_PAGE; } Graphics2D g2d = (Graphics2D)g; g2d.translate(pf.getImageableX(), pf.getImageableY()); /* Print the entire visible contents of a java.awt.Frame */ frame.printAll(g); return PAGE_EXISTS; } Note: The call to the printAll method is the only difference between this example and examples to print text or image. The print(Graphics g) method mirrors the java.awt.Component.paint(Graphics g) method used for on-screen rendering. Use the print() method rather than the paint() method as the Components class may have overridden the print() method to handle the printing case differently.

The printAll(Graphics g)method prints the component and all its subcomponents. This method is usually used to print object such as a complete window, rather than a single component.

Printing Support in Swing Components The PrintUIWindow.java example represented in the previous section demonstrates that the printout is exactly the same you saw on the screen. This appearance seems reasonable. However, if a window is scrollable, then the contents that are currently scrolled out of view are not included in the printout. This creates a dump effect on the printer. This becomes a particular problem when printing large components such as a Swing table or text components. Components may contain many lines of text which cannot all be entirely visible on the screen. In this case, print the contents displayed by the component in a manner consistent with the screen display. To solve this problem, the Swing table and all text components are printing aware. The following methods directly provide the use of the Java 2D printing:

javax.swing.JTable.print(); javax.swing.text.JTextComponent.pri

nt(); These methods provide a full implementation of printing for their contents. An application doesn't need directly create a PrinterJob object and implement the Printable interface. The call of these methods displays a print dialog and prints the component's data in accordance with the user's selections. There are also additional methods which provide more options. For more information see related articles at java.sun.com. Lesson: Advanced Topics in Java2D This lesson shows you how to use Graphics2D to display graphics with fancy outline and fill styles, transform graphics when they are rendered, constrain rendering to a particular area, and

generally control the way graphics look when they are rendered. You'll also learn how to create complex Shape objects by combining simple ones and how to detect when the user clicks on a displayed graphics primitive. These topics are discussed in the following sections: Transforming Shapes, Text, and Images This section shows you how to modify the default transformation so that objects are translated, rotated, scaled, or sheared when they are rendered. Clipping the Drawing Region You can use any shape as a clipping path--the area within which rendering takes place. Compositing Graphics This section illustrates the various compositing styles supported by AlphaComposite and shows you how to set the compositing style in the Graphics2D rendering context. Controlling Rendering Quality This section describes the rendering hints that Graphics2D supports and shows you how to specify your preference in the trade-off between rendering quality and speed. Constructing Complex Shapes from Geometry Primitives This section shows you how to perform boolean operations on Shape objects using the Area class. Supporting User Interaction This section shows you how to perform hit detection on graphics primitives. Transforming Shapes, Text, and Images You can modify the transform attribute in the Graphics2D context to move, rotate, scale, and shear graphics primitives when they are rendered. The transform attribute is defined by an instance of the AffineTransform class. An affine transform is a transformation such as translate, rotate, scale, or shear in which parallel lines remain parallel even after being transformed. The Graphics2D class provides several methods for changing the transform attribute. You can construct a new AffineTransform and change the Graphics2D transform attribute by calling transform. AffineTransform defines the following factory methods to make it easier to construct new transforms:

getRotateInstance getScaleInstance

getShearInstance getTranslateInstance

Alternatively you can use one of the Graphics2D transformation methods to modify the current transform. When you call one of these convenience methods, the resulting transform is concatenated with the current transform and is applied during rendering:

rotate--to specify an angle of rotation in radians scale--to specify a scaling factor in the x and y directions shear--to specify a shearing factor in the x and y directions translate--to specify a translation offset in the x and y directions

You can also construct an AffineTransform object directly and concatenate it with the current transform by calling the transform method. The drawImage method is also overloaded to allow you to specify an AffineTransform that is applied to the image as it is rendered. Specifying a transform when you call drawImage does not affect the Graphics2D transform attribute. Example: Transform The following program is the same as StrokeandFill, but also allows the user to choose a transformation to apply to the selected object when it is rendered.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. Transform.java contains the complete code for this applet. When a transform is chosen from the Transform menu, the transform is concatenated onto the AffineTransform at: public void setTrans(int transIndex) { // Sets the AffineTransform. switch ( transIndex ) { case 0 : at.setToIdentity(); at.translate(w/2, h/2); break; case 1 : at.rotate(Math.toRadians(45)); break; case 2 : at.scale(0.5, 0.5); break; case 3 : at.shear(0.5, 0.0); break; }

} Before displaying the shape corresponding to the menu choices, the application first retrieves the current transform from the Graphics2D object: AffineTransform saveXform = g2.getTransform(); This transform will be restored to the Graphics2D after rendering. After retrieving the current transform, another AffineTransform, toCenterAt, is created that causes shapes to be rendered in the center of the panel. The at AffineTransform is concatenated onto toCenterAt: AffineTransform toCenterAt = new AffineTransform(); toCenterAt.concatenate(at); toCenterAt.translate(-(r.width/2), -(r.height/2)); The toCenterAt transform is concatenated onto the Graphics2D transform with the transform method: g2.transform(toCenterAt); After rendering is completed, the original transform is restored using the setTransform method: g2.setTransform(saveXform); Note: Never use the setTransform method to concatenate a coordinate transform onto an existing transform. The setTransform method overwrites the Graphics2D object's current transform, which might be needed for other reasons, such as positioning Swing and lightweight components in a window. Use these steps to perform transformations:
1. Use the getTransform method to get the current transform. 2. Use transform, translate, scale, shear, or rotate to concatenate a transform.

3. Perform the rendering. 4. Restore the original transform using the setTransform method. Clipping the Drawing Region Compositing Graphics Controlling Rendering Quality Constructing Complex Shapes from Geometry Primitives Supporting User Interaction Home Page > 2D Graphics > Advanced Topics in Java2D

Previous Trail Next Clipping the Drawing Region Any Shape object can be used as a clipping path that restricts the portion of the drawing area that will be rendered. The clipping path is part of the Graphics2D context; to set the clip attribute, you call Graphics2D.setClip and pass in the Shape that defines the clipping path you want to use. You can shrink the clipping path by calling the clip method and passing in another Shape; the clip is set to the intersection of the current clip and the specified Shape. Example: ClipImage This example animates a clipping path to reveal different portions of an image.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. ClipImage.java contains the complete code for this applet. The applet requires the clouds.jpg image file. The clipping path is defined by the intersection of an ellipse and a rectangle whose dimensions are set randomly. The ellipse is passed to the setClip method, and then clip is called to set the clipping path to the intersection of the ellipse and the rectangle. private Ellipse2D ellipse = new Ellipse2D.Float(); private Rectangle2D rect = new Rectangle2D.Float(); ... ellipse.setFrame(x, y, ew, eh); g2.setClip(ellipse); rect.setRect(x+5, y+5, ew-10, eh-10); g2.clip(rect); Example: Starry A clipping area can also be created from a text string. The following example creates a TextLayout with the string The Starry Night. Then, it gets the outline of the TextLayout. The TextLayout.getOutline method returns a Shape object and a Rectangle is created from the bounds of this Shape object. The bounds contain all the pixels the layout can draw. The color in the graphics context is set to blue and the outline shape is drawn, as illustrated by the following image and code snippet.

FontRenderContext frc = g2.getFontRenderContext(); Font f = new Font("Helvetica", 1, w/10); String s = new String("The Starry Night"); TextLayout textTl = new TextLayout(s, f, frc); AffineTransform transform = new AffineTransform(); Shape outline = textTl.getOutline(null); Rectangle r = outline.getBounds(); transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); g2.setColor(Color.blue); g2.draw(outline); Next, a clipping area is set on the graphics context using the Shape object created from getOutline. The starry.gif image, which is Van Gogh's famous painting, The Starry Night, is drawn into this clipping area starting at the lower left corner of the Rectangle object. g2.setClip(outline); g2.drawImage(img, r.x, r.y, r.width, r.height, this);

Note: If you don't see the applet running above, you need to install release 6 of the JDK. Starry.java contains the complete code for this program. This applet requires the Starry.gif image file.

You might also like