Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures


Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips


Submit News
Search the site here...

Swing Chapter 22. (Special topics) Printing. Easy for reading, Click here!

Custom Search
Swing Chapter 22. (Special topics) Printing. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 1/5 

Next Page (2/5) Next Page

Part IV - Special Topics

Subpages: 1. Java 2 Printing API overview
2. Printing images
3. Print preview
4. Printing styled text
5. Printing tables

In the following six chapters we cover several different topics which relate directly to the use of Swing. Chapter 22 discusses the powerful new Java 2 printing API. We construct examples showing how to print an image on multiple pages, construct a print preview component, print styled text, and print JTable data (in both portrait and landscape modes). Chapter 23 introduces a few Java2D features. Examples include a generic 2D chart class, a 2D label class, and the beginnings of a Pac-man game. Chapter 24 introduces Accessibility and shows how easy it is to integrate this functionality into existing apps. Chapter 25 covers the basics of the JavaHelp API, and includes examples showing how we can customize the Swing-based help viewer to our liking. Chapter 26 introduces CORBA and contains an example of a client-server, Swing-based app based on our StocksTable example from chapter 18. Chapter 27 consists of two examples contributed by experienced Swing developers: constructing custom multi-line labels and tooltips and an internet browser application. Unfortunately, due to space limitations, chapters 24-27 were not included in this edition. However, they remain freely available to all readers on the book's web site.

Chapter 22. Printing

In this chapter:

  •          Java 2 Printing API overview
  •          Printing images
  •          Print preview
  •          Printing styled text
  •          Printing tables

22.1  Java 2 Printing API overview

With Java 2 comes a considerably advanced printing API. Java veterans may recall that JDK 1.0 didn't provide printing capabilities at all. JDK 1.1 provided access to native print jobs, but multi-page printing was a real problem for that API.

Now Java developers are able to perform multi-page printing using page count selection and other typical specifications in the native Print dialog, as well as page format selection in the native platform-specific Page Setup dialog. The printing-related API is concentrated in the java.awt.print package, and we'll start this chapter with an overview of these classes and interfaces.

Note: At this point the underlying communication with the native printing system is not yet matured. You will notice that some of the examples in this chapter run extremely slow, especially when dealing with Images. We expect these deficiencies to decrease, and the material presented here should be equally applicable in future releases of Java.

22.1.1  PrinterJob

class java.awt.print.PrinterJob

This is the main class which controls printing in Java 2. It is used to store print job properties, to initiate printing when necessary, and to control the display of Print dialogs. A typical printing process is shown in the following code:

    PrinterJob prnJob = PrinterJob.getPrinterJob();


    if (!prnJob.printDialog())



This code retrieves an instance of PrinterJob with the static getPrinterJob() method, passes a Printable instance to it (used to render a specific page on demand--see below), invokes a platform-dependent Print dialog by calling PrinterJob's printDialog() method, and, if this method returns true (indicating the "ok" to print), starts the actual printing process by calling the print() method on that PrinterJob.

The Print dialog will look familiar, as it is the typical dialog used by most other applications on the user's system. For example, figure 22.1 shows a Windows NT Print dialog:

Figure 22.1 Windows NT Print dialog: about to print a pageable job .

<<file figure22-1.gif>>

Though the PrinterJob is the most important constituent of the printing process, it can do nothing without a Printable instance that specifies how to actually perform the necessary rendering for each page.

22.1.2  The Printable interface

abstract interface java.awt.print.Printable

This interface defines only one method: print(), which takes three parameters:

Graphics graphics: the graphical context into which the page will be drawn.

PageFormat pageFormat: an object containing information about the size and orientation of the page being drawn (see below).

int pageIndex: the zero based index of the page to be drawn.

The print() method will be called to print a portion of the PrinterJob corresponding to a given pageIndex. An implementation of this method should perform rendering of a specified page, using a given graphical context and a given PageFormat. The return value from this method should be PAGE_EXISTS if the page is rendered successfully, or NO_SUCH_PAGE if the given page index is too large and does not exist. (These are static ints defined in Printable.)

Note: we never call a Printable's print() method ourselves. This is handled deep inside the actual platform-specific PrinterJob implementation which we aren't concerned with here.

A class that implements Printable is said to be a page painter. When a PrinterJob uses only one page painter to print each page it is referred to as a printable job. The notion of a document as being separated into a certain number of pages is not predefined in a printable job. In order to print a specific page, a printable job will actually render all pages leading up to that page first, and then it will print the specified page. This is because it does not maintain information about how much space each page will occupy when rendered with the given page painter. For example, if we specify, in our Print dialog, that we want to print pages 3 and 5 only, then pages 0 through 4 (because pages are 0-indexed) will be rendered with the print() method, but only 2 and 4 will actually be printed.

Warning: Since the system only knows how many pages a printable job will span after the rendering of the complete document takes place (i.e. after paint() has been called), Print dialogs will not display the correct number of pages to be printed. This is because there is no pre-print communication between a PrinterJob and the system that determines how much space the printable job requires. For this reason you will often see a range such as 1 to 9999 in Print dialogs when printing printable jobs. (This is not the case for pageable jobs--see below.)

In reality, it is often the case that print() will be called for each page more than once. From a draft of an overview of the Java Printing API: "This *callback* printing model is necessary to support printing on a wide range of printers and systems...This model also enables printing to a bitmap printer from a computer that doesn't have enough memory or disk space to buffer a full-page bitmap. In this situation, a page is printed as a series of small bitmaps or *bands*. For example, if only enough memory to buffer one tenth of a page is available, the page is divided into ten bands. The printing system asks the application to render each page ten times, once to fill each band. The application does not need to be aware of the number or size of the bands; it simply must be able to render each page when requested." --  http://java.sun.com/printing/jdk1.2/index.html

Though this explains some of the performance problems that we will see in the coming examples, it seems that the model described above is not exactly what we are dealing with in Java 2 FCS. In fact, after some investigation, it turns out that the division into bands is not based on available memory. Rather, a hard-coded 512k buffer is used. By increasing the size of this buffer, it is feasible to increase performance significantly. However, this would involve modification of peer-level classes; something that we are certainly not encouraged to do. We hope to see this limitation accounted for in future releases.

22.1.3  The Pageable interface

abstract interface java.awt.print.Pageable

It is possible to support multiple page painters in a single PrinterJob. As we know, each page printer can correspond to a different scheme of printing because each Printable implements its own print() method. Implemenatations of the Pageable interface are designed to manage groups of page painters, and a  print job that uses multiple page painters is referred to as a pageable job. Each page in a pageable job can use a different page printer and PageFormat (see below) to perform its rendering.

Unlike printable jobs, pageable jobs do maintain the predefined notion of a document as a set of separate pages. For this reason pages of a pageable job can be printed in any order without the necessity of rendering all pages leading up to a specific page (as is the case with printable jobs). Also, because a Pageable instance carries with it an explicit page count, this can be communicated to the native printing system when a PrinterJob is established. So when printing a pageable job the native Print dialog will know the correct range of pages to display, unlike a printable job. (Note that this does not mean pageable jobs are not subject to the inherent limitations described above; we will see the same repetitive calling of print() that we do in printable jobs.)

When constructing a pageable PrinterJob, instead of calling PrinterJob's setPrintable() method (see section 22.1.1 above), we call its setPageable() method. Figure 22.1 shows a Windows NT Print dialog about to print a pageable job. Notice that the range of pages is not 1 to 9999.

We won't be working with pageable jobs in this chapter because all the documents we will be printing only require one Printable implementation, even if documents can span multiple pages. In most real-world applications, each page of a document is printed with identical orientation, margins, and other sizing characterstics. However, if greater flexibility is desired, Pageable implementations such as Book (see below) can be useful.

22.1.4  The PrinterGraphics interface

abstract interface java.awt.print.PrinterGraphics

This interface defines only one method: getPrinterJob(), which retrieves the PrinterJob instance controlling the current printing process. It is implemented by Graphics objects that are passed to Printable objects to render a page. (We will not need to use this interface at all, as it is used deep inside PrinterJob instances to define Graphics objects passed to each Printable's paint() method during printing.)

22.1.5  PageFormat

class java.awt.print.PageFormat

This class encapsulates a Paper object and adds to it an orientation property (landscape or portrait). We can force a Printable to use a specific PageFormat by passing one to PrinterJob's overloaded setPrintable() method. For instance, the following would force a printable job to use a specific PageFormat with a landscape orientation:

    PrinterJob prnJob = PrinterJob.getPrinterJob();

    PageFormat pf = job.defaultPage();


    prnJob.setPrintable(myPrintable, pf);

    if (!prnJob.printDialog())



PageFormat defines three orientations:

LANDSCAPE: The origin is at the bottom left-hand corner of the paper with x axis pointing up and y axis pointing to the right.

PORTRAIT (most common): The origin is at the top left-hand corner of the paper with x axis pointing to the right and y axis pointing down.

REVERSE_LANDSCAPE: The origin is at the top right-hand corner of the paper with x axis pointing down and y axis pointing to the left.

We can optionally display a page setup dialog in which the user can specify page characteristics such as orientation, paper size, margin size, etc. This dialog will return a new PageFormat to use in printing. The page setup dialog is meant to be presented before the Print dialog and can be displayed using PrinterJob's pageDialog() method. The following code brings up a page setup dialog, and uses the resulting PageFormat for printing a printable job:

    PrinterJob prnJob = PrinterJob.getPrinterJob();

    PageFormat pf = job.pageDialog(job.defaultPage());

    prnJob.setPrintable(myPrintable, pf);

    if (!prnJob.printDialog())



Note that we need to pass the pageDialog() method a PageFormat instance, as it uses it to clone and modify as the user specifies. If the changes are accepted the cloned and modifed version is returned. If they are not, the original version passed in is returned. Figure 22.2 shows a Windows NT page setup dialog:

Figure 22.2 Windows NT page setup dialog .

<<file figure22-2.gif>>

22.1.6  Paper

class java.awt.print.Paper

This class holds the size and margins of the paper used for printing. Methods getImageableX() and getImageableY() retrieve the coordinates of the top-left corner of the printable area in 1/72nds of an inch (which is approximately equal to one screen pixel--referred to as a "point" in typography). Methods getImageableWidth() and getImageableHeight() retrieve the width and height of the printable area (also in 1/72nds of an inch). We can also change the size of the useable region of the paper using its setImageableArea() method.

We can access the Paper object associated with a PageFormat using PageFormat's getPaper() and setPaper() methods.

22.1.7  Book

class java.awt.print.Book

This class represents a collection of Printable instances with corresponding PageFormats to represent a complex document whose pages may have different formats. The Book class implements the Pageable interface, and Printables are added to a Book using one of its append() methods. This class also defines several methods allowing for the manipulation and replacement of specific pages. (A page in terms of a Book is a Printable-PageFormat pair. Each page does correspond to an actual printed page.) See the API docs and the Java Tutorial for more information about this class.

22.1.8  PrinterException

class java.awt.print.PrinterException

This exception may be thrown to indicate an error during a printing procedure. It has two concrete sub-classes: PrinterAbortException and PrinterIOException. The former indicates that a print job was terminated by the application or user while printing, and the latter indicates that there was a problem outputting to the printer.

Reference: For more information about the printing API and features that are expected to be implemented in future versions, refer to the Java tutorial.

[ Return to Swing (Book) ]

Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color

[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3

[ More in News Section ]

Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy