Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Online Training

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
 
Training Index

Writing Advanced Applications
Chapter 6 Continued: Printing API

[<<BACK] [CONTENTS] [NEXT>>]

The JavaTM 2 platform java.awt.print package lets you print anything that can be rendered to a Graphics or Graphics2D context — including AWT components, Java Foundation Classes (JFC) Project Swing (Project Swing) components, and 2D graphics. The Printing API is easy to use. Your application tells the printing system what to print, and the printing system determines when each page is rendered. This callback printing model enables printing support on a wide range of printers and systems. The callback model also lets users print to a bitmap printer from a computer that does not have enough memory or disk space to hold the bitmap for an entire page.

A graphics context lets a program paint to a rendering device such as a screen, printer, or offscreen image. Because Swing components are rendered through a Graphics object using AWT graphics support, it is easy to print Swing components with the new printing API. However, AWT components are not rendered to a graphics device, so you must extend the AWT component class and implement the AWT component paint method.


What is in the Package?

The java.awt.print consists of the following interfaces, classes, and exceptions. Here is where you can view the API specification.
  • Interfaces
    • Pageable
    • Printable
    • PrinterGraphics
  • Classes
    • Book
    • PageFormat
    • Paper
    • PrinterJob
  • Exceptions
    • PrinterAbortException
    • PrinterException
    • PrinterIOException

Printing an AWT Component

The printbutton.java application displays a panel with MyButton on it. When you click the button, the application prints the MyButton component.

In the code, the Button class is extended to implement Printable and includes the paint and print method implementations. The print method is required because the class implements Printable, and the paint method is needed to describe how the button shape and label text looks when printed.

To see the button, the printer graphics context is translated into the imageable area of the printer, and to see the label text, a font is set on the printer graphics context.

In this example, the button is printed at a 164/72 inches inset from the left imageable margin (there are 72 pixels per inch) and 5/72 inches from the top imageable margin. This is where the button is positioned in the frame by the layout manager and those same numbers are returned by the following calls:

int X = (int)this.getLocation().getX();
int Y = (int)this.getLocation().getY();
And here is the MyButton class code:
class MyButton extends Button 
		implements Printable {

  public MyButton() {
    super("MyButton");
  }

  public void paint(Graphics g) {
  //To see the label text, you must specify a font for
  //the printer graphics context
    Font  f = new Font("Monospaced", Font.PLAIN,12);
    g2.setFont (f);

  //Using "g" render anything you want.
  //Get the button's location, width, and height
    int X = (int)this.getLocation().getX();
    int Y = (int)this.getLocation().getY();
    int W = (int)this.getSize().getWidth();
    int H = (int)this.getSize().getHeight();

  //Draw the button shape
    g.drawRect(X, Y, W, H);

  //Draw the button label
  //For simplicity code to center the label inside the
  //button shape is replaced by integer offset values  
    g.drawString(this.getLabel(), X+10, Y+15);

  }

  public int print(Graphics g, 
                     PageFormat pf, int pi) 
		       throws PrinterException {
    if (pi >= 1) {
      return Printable.NO_SUCH_PAGE;
    }

    Graphics2D g2 = (Graphics2D) g;

  //To see the button on the printed page, you
  //must translate the printer graphics context
  //into the imageable area
    g2.translate(pf.getImageableX(), pf.getImageableY());
    g2.setColor(Color.black);
    paint(g2);
    return Printable.PAGE_EXISTS;
   }
Note: The printing Graphics2D is based on the BufferedImage class and on some platforms does not default to a foreground color of black. If this is the case on your platform, you have to add g2.setColor(Color.black) to the print method before the paint invocation.

Printing a Project Swing Component

Printing a Project Swing component is almost the same as printing an AWT component, except the MyButton subclass does not need a paint method implementation. It does, however, have a print method that calls the paint method for the component. The paint method implementation is not needed because Project Swing components know how to paint themselves.

Here is the complete printbutton.java source code for Project Swing.

class MyButton extends JButton implements Printable {

  public MyButton() {
    super("MyButton");
  }

  public int print(Graphics g, 
                     PageFormat pf, int pi)
                       throws PrinterException {
    if (pi >= 1) {
      return Printable.NO_SUCH_PAGE;
    }

    Graphics2D g2 = (Graphics2D) g;
    g2.translate(pf.getImageableX(), 
                 pf.getImageableY());
    Font  f = new Font("Monospaced", Font.PLAIN,12);
    g2.setFont (f);
    paint(g2);
    return Printable.PAGE_EXISTS;
   }
If you extend a JPanel and implement Printable, you can print a panel component and all of its contents.
public class printpanel extends JPanel 
			implements ActionListener, 
			Printable {
Here is the printpanel.java code that prints a JPanel object and the JButton it contains, and the ComponentPrinterFrame.java code that prints a JFrame object and the JButton, JList, JCheckBox, and JComboBox components it contains.

Printing Graphics in Project Swing

In the same way the AWT example subclassed a Button component and implemented the paint method to draw the button, you can subclass an AWT or Project Swing component and implement the paint method to render 2D graphics to the screen or printer. The ShapesPrint.java" Project Swing application borrowed from The Java Tutorial shows how this is done. It is modified for this article to include a TextLayout object.

The paintComponent method calls the drawShapes method to render the 2D graphics to the screen when the application starts. When you click the Print button, a printer graphics context is created and passed to the drawShapes method for printing.

Print Dialog

It is easy to display a Print dialog so the end user can interactively change the print job properties. The actionPerformed method of the previous Project Swing example is modified here to do just that.

public void actionPerformed(ActionEvent e) {
  PrinterJob printJob = PrinterJob.getPrinterJob();
  printJob.setPrintable((MyButton) e.getSource());
  if(printJob.printDialog()){
    try { printJob.print(); } 
    catch (Exception PrinterExeption) { }
  }
}
Note:In Project Swing, the printJob.setPageable((MyButton) e.getSource()); statement can be written as printJob.setPrintable((MyButton) e.getSource());. The difference is setPrintable is for applications that do not know the number of pages they are printing. If you use setPrintable, you need to add if(pi >= 1){ return Printable.NO_SUCH_PAGE: } to the beginnig of the print method.

Page Setup Dialog

You can add a line of code that tells the PrinterJob object to display a Page dialog so the end user can interactively modify the page format for printing in portrait, landscape, or reverse landscape mode. The actionPerformed method of the previous Project Swing example is modified here to display Page and Print dialogs.

Note: Some platforms do not support a page dialog. On those platforms, the pageDialog call simply returns the passed-in PageFormat object and no dialog appears.
public void actionPerformed(ActionEvent e) {
  PrinterJob printJob = PrinterJob.getPrinterJob();
  printJob.setPrintable((MyButton) e.getSource());
  PageFormat pf = printJob.pageDialog(
                             printJob.defaultPage());
  if(printJob.printDialog()){
    try { printJob.print(); } catch (Exception ex) { }
  }
}

Printing a Collection of Pages

You can use the Book class to print a collection of pages that you append to the book. The pages can be in any order and have different page formats.

The print2button.java example puts the Print and Print 2 buttons of type MyButton on a panel. It creates a book that contains the pages to print. When you click either button, the book prints one copy of the Print button in landscape mode and two copies of the Print 2 button in portrait more, as specified in the actionPerformed method implementation shown here.


Note: Currently a bug restricts the Solaris platform to only print in portrait mode.
public void actionPerformed(ActionEvent e) {
  PrinterJob printJob = PrinterJob.getPrinterJob();

/* Set up Book */
  PageFormat landscape = printJob.defaultPage();
  PageFormat portrait = printJob.defaultPage();
  landscape.setOrientation(PageFormat.LANDSCAPE);
  portrait.setOrientation(PageFormat.PORTRAIT);
  Book bk = new Book();
  bk.append((Printable)b, landscape);
  bk.append((Printable)b2, portrait, 2);
  printJob.setPageable(bk);

  try { printJob.print(); } catch (Exception ex) { }
}

[TOP]


[ This page was updated: 13-Oct-99 ]

Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-99 Sun Microsystems, Inc.
All Rights Reserved. Legal Terms. Privacy Policy.