Home | Articles

New Printing Package

Printing press The java.awt.print package provides printing capabilities that give you the power and flexibility you need to meet your application printing requirements.

The new printing package provides enhanced functionality over what is available in the preexisting AWT printing API for printing anything that can be rendered to a graphics context—including AWT components, Swing components, and 2D graphics.

About the New Printing Model

The java.awt.print 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.

The java.awt.print API is designed so anything that can be rendered through a graphics context represented by a Graphics or Graphics2D object can be printed.

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.

Interfaces

Classes

Exceptions

Printing an AWT Component

My AWT Button 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();


static class MyButton extends Button 
                     implements Printable {

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

  public void paint(Graphics g) {
    System.out.println("mybutton paint");
//To see the label text, you must specify a font for
//the printer graphics context
  Font  f = new Font("Monospaced",Font.PLAIN,12);
  System.out.println (f);
  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 {
  System.out.println("mybutton print");
    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());
    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 will need to add g2.setColor(Color.black) to the print method before the paint invocation.

Printing a Swing Component

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

Here is the complete printbuttonswing.java source code for Swing.

static class MyButton extends JButton 
                              implements Printable {

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

  public int print(
  Graphics g, PageFormat pf, int pi)
                           throws PrinterException {
    System.out.println("mybutton print");
    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);
  System.out.println (f);
  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 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 Swing component and implement the paint method to render 2D graphics to the screen or printer. The ShapesPrint.java" Swing application borrowed from The Java Tutorial shows how this is done. It is modified for this article to include a TextLayout object.

A bunch of shapes

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 Swing example is modified here to do just that.

A print dialog box

public void actionPerformed(ActionEvent e) {
  System.out.println("action");
  PrinterJob printJob = PrinterJob.getPrinterJob();
  printJob.setPrintable((MyButton) e.getSource());
  if(printJob.printDialog()){
    try { printJob.print(); } 
    catch (Exception PrinterExeption
    ) { }
  }
}
Note:In 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 beginning 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 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) {
  System.out.println("action");
  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.

Print collection
of pages 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:

public void actionPerformed(ActionEvent e) {
  System.out.println("action");
  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) { }
}

Conclusion

The new java.awt.print package provides easy-to-use printing capabilities that let an application send one page or a collection of pages to the printer. Anything that can be rendered to a graphics context can be printed. This includes 2D graphics, AWT components, and Swing components.

© 1994-2005 Sun Microsystems, Inc.