Joakim Karlsson Joakim Karlsson - 15 days ago 8
Java Question

Send a JPanel to the printer

Is it possible to just send a JPanel or any other component to the printer? Or do I have to implement all the drawing to the graphics object by hand?

I have tried to use the Print* functions of the JPanel to print to the graphics object but the page that gets printed is blank.

Answer

Check out the Java printing API and tutorial along with JComponent.print(Graphics).

Here is a rudimentary class which will print any component which fits on 1 page (I can't take credit for this, I got the code from Marty Hall's tutorial):

package dol.lpc.lib.gui;

import java.awt.*;
import java.awt.print.*;
import javax.swing.*;

/**
 * Generic component printer.  This object allows any AWT or Swing component  (or DCT system)
 * to be printed by performing it pre and post print responsibilities.
 * <p>
 * When printing components, the role of the print method is nothing more than to scale the Graphics, turn off double
 * buffering, and call paint.  There is no particular reason to put that print method in the component being printed.  A
 * better approach is to build a generic printComponent method to which you simply pass the component you want printed.
 * <p>
 * With Swing, almost all components have double buffering turned on by default. In general, this is a great benefit,
 * making for convenient and efficient painting. However, in the specific case of printing, it can is a huge problem.
 * First, since printing components relies on scaling the coordinate system and then simply calling the component's
 * paint method, if double buffering is enabled printing amounts to little more than scaling up the buffer (off-screen
 * image) which results in ugly low-resolution printing like you already had available. Secondly, sending these huge
 * buffers to the printer results in huge print spooler files which take a very long time to print. Consequently this
 * object globally turns off double buffering before printing and turns it back on afterwards.
 * <p>
 * Threading Design : [x] Single Threaded  [ ] Threadsafe  [ ] Immutable  [ ] Isolated
 */

public class ComponentPrinter extends Object implements Printable {

    // *****************************************************************************
    // INSTANCE PROPERTIES
    // *****************************************************************************

    private Component component; // the component to print

    // *****************************************************************************
    // INSTANCE CREATE/DELETE
    // *****************************************************************************

    public ComponentPrinter(Component com) {
        component=com;
    }

    // *****************************************************************************
    // INSTANCE METHODS
    // *****************************************************************************

    public void print() throws PrinterException {
        PrinterJob printJob=PrinterJob.getPrinterJob();

        printJob.setPrintable(this);
        if(printJob.printDialog()) {
            printJob.print();
        }
    }

    public int print(Graphics gc, PageFormat pageFormat, int pageIndex) {
        if(pageIndex>0) {
            return NO_SUCH_PAGE;
        }

        RepaintManager mgr=RepaintManager.currentManager(component);
        Graphics2D g2d = (Graphics2D)gc;

        g2d.translate(pageFormat.getImageableX(),pageFormat.getImageableY());
        mgr.setDoubleBufferingEnabled(false);  // only for swing components
        component.paint(g2d);
        mgr.setDoubleBufferingEnabled(true);   // only for swing components
        return PAGE_EXISTS;
    }

    // *****************************************************************************
    // STATIC METHODS
    // *****************************************************************************

    static public void printComponent(Component com) throws PrinterException {
        new ComponentPrinter(com).print();
    }

} // END PUBLIC CLASS