[Chapter 17] Printing
Author: John Zukowski
Date: Thu Jul 31 14:58:02 1997

#

| Chapter 17 |

# 17. Printing

Contents:
PrintGraphics Interface
PrintJob Class
Component Methods
Printing Example
Printing Arbitrary Content

Java 1.1 introduces the ability to print, a capability that was sadly missing in Java 1.0, even though the `Component` class had `print()` and `printAll()` methods. However, it is possible to print arbitrary content, including multipage documents. The printing facility in Java 1.1 is designed primarily to let a program print its display area or any of the components within its display.

Printing is implemented with the help of one public interface, `PrintGraphics`, and one public class, `PrintJob`, of AWT. The real work is hidden behind classes provided with the toolkit for your platform. On Windows NT/95 platforms, these classes are `sun.awt.windows.WPrintGraphics` and `sun.awt.windows.WPrintJob`. Other platforms have similarly named classes.

Printing from an applet has security implications and is restricted by the `SecurityManager`. It is reasonable to suppose that a browser will make it possible to print a page containing an applet; in fact, Netscape has done so ever since Navigator 3.0. However, this ability might not take advantage of Java's printing facility. It isn't reasonable to suppose that an applet will be able to initiate a print job on its own. You might allow a signed applet coming from a trusted source to do so, but you wouldn't want to give any random applet access to your printer. (If you don't understand why, imagine the potential for abuse.)

## 17.1 PrintGraphics Interface

Printing is similar to drawing an object on the screen. Just as you draw onto a graphics context to display something on the screen, you draw onto a "printing context" to create an image for printing. Furthermore, the printing context and graphics context are very closely related. The graphics context is an instance of the class `Graphics`. The printing context is also an instance of `Graphics`, with the additional requirement that it implement the `PrintGraphics` interface. Therefore, any methods that you use to draw graphics can also be used for printing. Furthermore, the `paint()` method (which a component uses to draw itself on the screen) is also called when a component must draw itself for printing.

In short, to print, you get a special `Graphics` object that implements the `PrintGraphics` interface by calling the `getGraphics()` method of `PrintJob` (discussed later in this chapter) through `Toolkit`. You then call a component's `print()` or `printAll()` method or a container's `printComponents()` method, with this object as the argument. These methods arrange for a call to `paint()`, which can draw on the printing context to its heart's content. In the simple case where you're just rendering the component on paper, you shouldn't have to change `paint()` at all. Of course, if you are doing something more complex (that is, printing something that doesn't look exactly like your component), you'll have to modify `paint()` to determine whether it's painting on screen or on paper, and act accordingly. The code would look something like this:

    public void paint(Graphics g) {
        if (g instanceof PrintGraphics) {
            // Printing
        }else {
            // Painting
        }
    }

If the graphics object you receive is an instance of `PrintGraphics`, you know that `paint()` has been called for a print request and can do anything specific to printing. As I said earlier, you can use all the methods of `Graphics` to draw on `g`. If you're printing, though, you might do anything from making sure that you print in black and white to drawing something completely different. (This might be the trick you use to print the contents of a component rather than the component itself. However, as of Java 1.1, it's impossible to prevent the component from drawing itself. Remember that your `paint()` method was never responsible for drawing the component; it only drew additions to the basic component. For the time being, it's the same with printing.)

When you call `printComponents()` on a `Container`, all the components within the container will be printed. Early beta versions of 1.1 only painted the outline of components within the container. The component should print as it appears on the screen.

### Methods

public abstract PrintJob getPrintJob ()

  The `getPrintJob()` method returns the `PrintJob` instance that created this `PrintGraphics` instance.

  This seems like circular logic: you need a `PrintJob` to create a `PrintGraphics` object, but you can get a `PrintJob` only from a `PrintGraphics` object. To break the circle, you can get an initial `PrintJob` by calling the `getPrintJob()` method of `Toolkit`. `getPrintJob()` looks like it will be useful primarily within `paint()`, where you don't have access to the original `PrintJob` object and need to get it from the graphics context.

System-provided `PrintGraphics` objects inherit their other methods from the `Graphics` class, which is discussed in Chapter 2, Simple Graphics.[1] The one method that's worth noting here is `dispose()`. In a regular `Graphics` object, calling `dispose()` frees any system resources the object requires. For a `PrintGraphics` object, `dispose()` sends the current object to the printer prior to deallocating its resources. Calling `dispose()` is therefore equivalent to sending a form feed to eject the current page.

> [1] Anything can implement the `PrintGraphics` interface, not just subclasses of `Graphics`. However, in order for `paint()` and `print()` to work, it must be a subclass of `Graphics`.

Reading and Writing the Clipboard |  | PrintJob Class