Printing

Earlier in this chapter, we hinted at the possibility that you could draw the same stuff on the screen and the printer. It’s true; all you really need to do is get a Graphics2D object that represents a printer rather than an area of the screen. Java’s printing API provides the necessary plumbing. There isn’t room here to describe the whole Printing API, but we will provide you with a short example that will let you get your feet wet (and your paper flowing).

The printing classes are tucked away in the java.awt.print package. You can print anything that implements the Printable interface. This interface has only one method—you guessed it, print()—which is like the paint() methods we’ve already worked with. It accepts a Graphics object that represents the drawing surface of the printer’s page. It also accepts a PageFormat object that encapsulates information about the paper on which you’re printing. Finally, print() is passed the number of the page that is being rendered. All Swing components implement a print() method, which you can use or override to customize their printed appearance.

Your print() implementation should either render the requested page or state that it doesn’t exist. You can do this by returning special values from print(), either Printable.PAGE_EXISTS or Printable.NO_SUCH_PAGE.

You can control a print job, including showing print and page setup dialogs, using the PrinterJob class. The following class enables you to get something on paper. In this example, we work both sides of the printing equation: implementing a simple Printable interface to generate our data and printing it with the PrinterJob API.

    //file: UnbelievablySimplePrint.java
    import java.awt.*;
    import java.awt.print.*;

    public class UnbelievablySimplePrint implements Printable
    {
      private static Font sFont = new Font("Serif", Font.PLAIN , 64);

      public int print(Graphics g, PageFormat Pf, int pageIndex)
          throws PrinterException
      {
        if (pageIndex > 0) return NO_SUCH_PAGE;
        Graphics2D g2 = (Graphics2D)g;
        g2.setFont(sFont);
        g2.setPaint(Color.black);
        g2.drawString("Save a tree!", 96, 144);
        return PAGE_EXISTS;
      }

      public static void main(String[] args) {
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(new UnbelievablySimplePrint());
        if (job.printDialog()) {
          try {
            job.print();
          }
          catch (PrinterException e) {}
        }
        System.exit(0);
      }
    }

There’s not much to this example. We’ve created an implementation of Printable, called UnbelievablySimplePrint. It has a very simple print() method that draws some text.

The rest of the work, in the main() method, has to do with setting up the print job. First, we create a new PrinterJob and tell it what we want to print:

    PrinterJob job = PrinterJob.getPrinterJob();
    job.setPrintable(new UnbelievablySimplePrint());

Then, we use the printDialog() method to show the standard print dialog. If the user presses the OK button, printDialog() returns true and main() goes ahead with the printing.

Notice that in the print() method, we perform the familiar cast from Graphics to Graphics2D. The full power of the 2D API is available for printing. In a real application, you’d probably have some subclass of Component that was also a Printable. The print() method could simply call the component’s paint() method to create a component that performs the same rendering to both the screen and the printer.

Get Learning Java, 4th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.