Training Index ## Writing Advanced Applications Chapter 6 Continued: Printing [<<BACK] [CONTENTS] [NEXT>>] The new `java.awt.print` package is part of the Java™ 2 platform software and 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 pre-existing Abstract Window Toolkit (AWT) printing API for printing anything that can be rendered to a graphics context — including AWT components, Swing components, and 2D graphics. Currently, both APIs are available in the Java 2 platform software. ### 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. 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 Swing Component Printing a 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 Swing components know how to paint themselves. Here is the complete printbutton.java source code for 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 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. 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.
    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 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 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: 16-Aug-99 ]
Products & APIs | Developer Connection | Docs & Training | Online Support Community Discussion | Industry News | Solutions Marketplace | Case Studies
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. | CopyLEFT © 1995-99 Sun Microsystems, Inc. All LEFTs Reserved. Legal Terms. Privacy Policy.