J2PanelPrinter is a Java 2 component for printing the contents of any JPanel or JPanel subclass.  J2PanelPrinter can also be used for smaller (<1 page) Components, Containers wtth smaller Components, and Images (for larger, multi-page Components, we recommend you use J2ComponentPrinter).  For example, the JPanel may be used for printing diagrams and figures drawn with regular Java Graphics (or Graphics2D) method calls, where these appear in the paint method of the JPanel.  J2PanelPrinter has special methods and constructors to make it easy to print an individual Component (or JComponent) or an individual Image without placing these inside a JPanel.

J2PanelPrinter can print the JPanel as a Java Pageable or as a Flowable, so that it may be used with J2FlowPrinter as part of a series of Flowables printed back-to-back.  J2PanelPrinter is frequently used for JPanel instances containing small pieces of content that fit within a printed page.  These include images, titles, captions, legends, etc. intermixed with other J2PrinterWorks printing components in a J2FlowPrinter container.

J2PanelPrinter Pagination

J2PanelPrinter is often used for printing smaller Components such a JLabels and JPanels containing smaller Components less than one page in size such as Images and Graphics-drawn diagrams.  However, J2PanelPrinter can also be used for printing JPanel instances containing larger pieces of content that may span multiple pages, provided they can be paginated effectively using one of the following four pagination modes supported by J2PanelPrinter that control where page breaks will occur:

SHRINK_TO_FIT (the default) means shrink the JPanel, Component, or Image to fit within remaining space on the current page.  But if this causes the JPanel, Component, or Image to be smaller than it would be to shrink-to-fit on the next full page, then skip to the top of the next page and shrink to fit in order to print it there.  Scaling is performed by the same amount in both X and Y (the aspect ratio is preserved). The value of getMaximumPaginationGap() is ignored in this mode.

SHRINK_TO_WIDTH means shrink the JPanel, Component, or Image to fit within the width of the current page, and paginate the scaled result across multiple vertical pages, breaking as necessary on pixel boundaries to print the entire JPanel, Component, or Image. Scaling is performed by the same amount in both X and Y (the aspect ratio is preserved).  If beginning on a partial page, then skip to the top of the next page if the available space is less than getMaximumPaginationGap() percent of the full page height (default 20%).

TILE means print the JPanel, Component, or Image across multiple horizontal and/or vertical pages without scaling by breaking the JPanel, Component, or Image as necessary on pixel boundaries (rather than anything to do with the content). If beginning on a partial page, the value of getMaximumPaginationGap() determines when to start on a new page.

BREAK_ON_COMPONENTS means if the JPanel is used as a Container, then examine its contained Components and find the maximum horizontal and vertical boundaries where page break(s) can be inserted without slicing through any Components. Only the first level of contained Components is examined, so the contents of any nested Containers (JPanel, JTextPane, etc.) will be kept together on the same page (unless larger than a page, in which case it will be sliced (like TILE) as needed on pixel boundaries). If beginning on a partial page, the value of getMaximumPaginationGap() determines when to start on a new page.

Though J2PanelPrinter can print Java Components such as JTextPane, JTable, JTree, or JList components, typically it only makes sense if these components are small, as J2PanelPrinter can only break on component boundaries or pixel boundaries and will not paginate larger versions of these components on meaningful content (e.g., line, row, column, node, item) boundaries.  Instead, you should use J2TablePrinter for JTable pagination on table row/column boundaries, J2TextPrinter for JTextPane pagination on text line boundaries, J2TreePrinter for JTree pagination on tree node boundaries, and J2ListPrinter for JList pagination on list item boundaries.  Alternatively, you can use J2ComponentPrinter which can also perform reasonably effective paginatation of these components using BREAK_ON_COLOR mode, breaking on boundaries of a given color such as "white space".  Since J2ComponentPrinter also supports SHRINK_TO_FIT, TILE, and BREAK_ON_COMPONENTS pagination modes, it can be used in place of J2PanelPrinter for most all purposes.

J2PanelPrinter will print the JPanel either left, right, or center justified horizontally or top, bottom, or center justified vertically. You can specify whether to use a white background when printing the JPanel, and/or whether to draw an outside line around the JPanel.  J2PanelPrinter prints the JPanel "WYSIWYG", so that the layout and relative size of the JPanel and all of its contents will be printed exactly as defined.


You will find it useful to begin your program with:
    import com.wildcrest.j2printerworks.*;

rather than spell out the full package name for all J2PrinterWorks classes.

J2PanelPrinter can instantiated with a zero-argument constructor:
    J2PanelPrinter panelPrinter = new J2panelPrinter();   

This creates a J2PanelPrinter object and initializes all values to their defaults (see the J2PanelPrinter Javadoc documentation).  To specify the JPanel to be printed by J2PanelPrinter, you can use the J2PanelPrinter method setPanel:
At this point panelPrinter is a Pageable suitable for printing by J2Printer.

Alternatively, you can use the single-argument J2PanelPrinter constructor:
    J2PanelPrinter panelPrinter = new J2PanelPrinter(yourJPanel);

In addition, J2PanelPrinter provides two convenience constructors for handling the common special cases of single Images and single Components (like JLabel, JTextArea, etc.):
    J2PanelPrinter imagePrinter = new J2PanelPrinter(yourImage);
    J2PanelPrinter componentPrinter = new J2PanelPrinter(yourComponent);
There are also two corresponding convenience methods for setting these values:

The following is a simple but complete Java program (J2PanelPrinterSimplestTest.java) that displays and prints a JPanel using J2PanelPrinter:

import java.awt.*;
import javax.swing.*;
import com.wildcrest.j2printerworks.*;

class J2PanelPrinterSimplestTest {
    static public void main(String args[]){
        JPanel panel = new JPanel();
        JLabel label = new JLabel();
        label.setFont(new Font("Serif",Font.PLAIN,14));
        label.setText("<html>This is an example of <i>a JLabel</i><br>"
                    + "displayed  inside <u>a JPanel</u> and<br>"
                    + "printed using <b>J2PrinterWorks</b></html>");
        panel.setPreferredSize(new Dimension(200,75);

        JFrame frame = new JFrame("J2PanelPrinter test");

        J2Printer printer = new J2Printer();
        J2PanelPrinter panelPrinter = new J2PanelPrinter(panel);


Most of the methods of J2PanelPrinter are set and get methods for controlling its property values. The full list of J2PanelPrinter methods, what they do, and their default values are given in the J2PanelPrinter Javadoc documentation .

General properties

Whether J2PanelPrinter is used as a Pageable or a Flowable, you can control whether the J2PanelPrinter operates in shrink-to-fit, shrink-to-width, tile, or break-on-components mode, whether it is left, right, or center justified horizontally on a page, top, bottom, or center justified within the remaining space on a page, whether to use a white background when printing the JPanel, and whether to draw an outside line around the JPanel.

Pagination mode

J2PanelPrinter has four modes for controlling the pagination of the JPanel to be printed, SHRINK_TO_FIT, SHRINK_TO_WIDTH, TILE, and BREAK_ON_COMPONENTS, described above in the section J2PanelPrinter Pagination.  To control the pagination mode of J2PanelPrinter, use the following method:

setPageRule (int pageRule)
          Sets the page rule for mapping each Component into the printed page.

Horizontal and vertical alignment

J2PanelPrinter will print your JPanel either left, center, or right justified horizontally on the page between the left and right margins.  The default value for horizontal alignment is CENTER.

Similarly, J2PanelPrinter will print your JPanel either top, center, or bottom justified vertically on the page between the gap below the header and gap above the footer.  The default value for vertical alignment is TOP.

setHorizontalAlignment (int horizontalAlignment)
          Sets the horizontal alignment (LEFT, CENTER, RIGHT) for printing the JPanel on the page.

setVerticalAlignment (int verticalAlignment)
          Sets the vertical alignment (TOP, CENTER, BOTTOM) for printing the JPanel on the page.

White background

By default, J2PanelPrinter will print your JPanel with the JPanel background color, which might be the background color of the window in which it is displayed.  You can specify whether whether the JPanel when printed should have a white background using the method:

setWhiteBackground (boolean whiteBackground)
          Sets whether to print the JPanel with a white background.

Outside line

J2PanelPrinter lets you control whether to draw a line surrounding the JPanel and what color this line should be using the following methods:

setOutsideLines (boolean showOutsideLines)
          Sets whether to print outside border lines around JPanel.

setOutsideLineColor (java.awt.Color outsideLineColor)
          Sets Color of outside border lines.

Pageable properties

When J2PanelPrinter is used as a Pageable, it can have its own ("local") headers & footers (left, center, and right), margins (left, right, top, and bottom), and orientation (portrait & landscape).  Headers and footers can be specified as a String or a JLabel, can be different on the first page vs. the rest of the pages of the Pageable, and can include date, time, and page numbering.  The methods are the same as the parallel set of methods described in the J2Printer section under "Pageable properties".

If "local" values are not specified for this J2PanelPrinter instance, the "global" (overall, default) values set using the parallel J2Printer methods will be used.  You can force the J2Printer "global" values to be used by calling the J2PanelPrinter method(s) with the argument J2Printer.GLOBAL.

The Pageable properties of J2PanelPrinter will be ignored when the J2PanelPrinter is used as a Flowable.  This is because in this case the Pageable is the containing J2FlowPrinter, so page properties such as headers, footers, margins, and orientation will be controlled by the J2FlowPrinter Pageable, not the J2PanelPrinter used as a Flowable.  Note, however, that scaling does work for J2PanelPrinter used as either a Pageable or a Flowable, that is, the J2PanelPrinter can appear at its own scale within an overall J2FlowPrinter sequence.

Fit-to-page scaling

In addition to regular percentage scaling accomplished using the setScale method, J2PanelPrinter also supports fit-to-page scaling when J2PanelPrinter is used as a Pageable using the following method:

setMaximumPages (int pagesWide, int pagesHigh)
          Set the maximum number of vertical and/or horizontal pages for printing the J2PanelPrinter (will minify to fit).

The setMaximumPages method causes your J2PanelPrinter to be scaled down until it fits within pagesWide pages horizontally and pagesHigh pages vertically.  This method cannot be used to magnify and instead will only minify your JPanel (hence the name setMaximumPages).  The method works by starting at a scale of 1.0 and reducing the scale in increments of 0.005 (half a percent) until your J2PanelPrinter fits within the prescribed limits.  There is only one scaling factor, which is used both horizontally and vertically, so no distortions are introduced.  If either pagesWide or pagesHigh is set to 0 or less, this is taken as a signal that the scaling in that dimension is unconstrained, that is, the J2PanelPrinter can use as many pages as it needs. 

The current pagination rule is applied before setMaximumPages is carried out.  Thus, setMaximumPages has no effect in SHRINK_TO_FIT mode, since SHRINK_TO_FIT is equivalent to setMaximumPages(1,1).  Likewise, setMaximumPages basically ignores "pagesWide" in SHRINK_TO_WIDTH mode, since SHRINK_TO_WIDTH is equivalent to setMaximumPages(1,0), but "pagesHigh" can still have an additional effect.  Note that you can use BREAK_ON_COMPONENTS along with setMaximumPages(1,0) to ensure the document will be one page wide but still break on component boundaries for vertical pagination.

NOTE: This method causes the rescaling to take place at the time it is called and does NOT remember or maintain the page limits you specify. Thus, if you change any printing parameters including your document content, headers, footers, margins, paper size, orientation, etc., you must call setMaximumPages again.

The percentage and fit-to-page scaling features interact.  You can call setMaximumPages(pagesWide, pagesHigh) to specify a number of pages and then use the method getScale() to find out the resulting scaling factor.  Or you can call setScale(factor) to scale to a desired percentage and then use getNumberOfPages() to find out the number of resulting pages.  The getNumberOfPages() method works for both magnification and minification (thus you could use it to implement your own fit-to-page feature for magnification, which you might call setMinimumPages(pagesWide, pagesHigh)).

Additional features

J2PanelPrinter WYSIWYG support

J2PanelPrinter inherently performs WYSIWYG printing since it images your JPanel instance directly using the Java print and paint methods.  This means you will print all of your JPanel's specified fonts, relative sizes, layout, colors, etc.  The general rule is: whatever your JPanel displays is what J2PanelPrinter will print.  

Non-GUI JPanel printing

It is not necessary that the JPanel you print be in a JFrame visible on the screen.  You may be printing from a server application and have no display.  Or you may have a JPanel displayed but wish to print from a different non-GUI copy of the JPanel.  The latter situation can arise when you want to set the printing JPanel properties different from your on-screen JPanel display, such as to force different background, size, layout, or fonts as appropriate for a printed page.  In such cases, you can use code like:

  JPanel panel2 = (JPanel) (J2Printer.clone(panel1));
  panel2.setSize(panel2.getPreferredSize()); // size required

This code assumes your JPanel is serializable, since this is how we implement the clone method.  If necessary, you can implement writeObject and readObject methods for your JPanel in order to make it serializable.  

Java Borders

You can use the Java Swing Borders classes to add various kinds of borders to your JPanel, and these will be printed by J2PanelPrinter.  Borders work when using J2PanelPrinter as either a Pageable or a Flowable.  You can use both the Java Borders feature and the J2PanelPrinter method setOutsideLines(true) at the same time (the Java Border will be inside the outside line).  Some examples of Java Borders are:
    jPanel1.setBorder(new LineBorder(Color.green,20));
    jPanel1.setBorder(new EmptyBorder(10,10,10,10));
    jPanel1.setBorder(new CompoundBorder(new LineBorder(Color.green,20),new EmptyBorder(10,10,10,10)));

Using J2PanelPrinter as a JavaBean

The J2PrinterWorks components are designed to work as a JavaBeans components in visual builder environments.  However, J2PrinterWorks uses APIs unique to the Java 2 system, and not all visual development environments currently work and build visually with Java 2-based components.  In particular, WebGain/Symantec Visual Cafe has to be specially configured to allow you to import the J2PrinterWorks components into its component library and exhibits other problems when using it visually. In contrast, Borland JBuilder and IBM VisualAge for Java can read and use J2PrinterWorks.jar as either a set of JavaBeans components or programmatically as classes.  See Installation & Compatibility for further details.  Since the J2PrinterWorks components are not GUI components per se, the need to work with them visually isn't great, so that using them programmatically isn't much of a limitation.

If J2PrinterWorks.jar is properly installed, you will see the J2PrinterWorks components, including J2Printer and J2PanelPrinter, in the component palette of your visual programming environment.  Click on the J2Printer bean and drop it on your work area and likewise drag the J2PanelPrinter bean and drop it on your work area.  You will see icons representing instances of these beans.  These will not be displayed at run-time.

When you bring up the property sheet for either component, you will be able to see and edit their properties.  The properties may be set as desired, with values as defined in the Javadoc documentation .

You can make the J2Printer bean print by using your visual programming environment to perform event wiring from an actionPerformed event such as a button push to the J2Printer "print" event target method.  You can use this to print the instance of J2PanelPrinter, using the setComponent method or the J2PanelPrinter constructor itself to specify your Component or subclass thereof (e.g. JComponent, JPanel, JLabel, etc.).

All the J2PrinterWorks properties are bound properties.  You may use your visual programming environment to do property-to-property binding in either direction between the J2PrinterWorks components and your other beans.  None of the J2PrinterWorks properties are constrained properties.  This frees you from having to place try...catch blocks around your "set" calls in regular programming.

J2PrinterWorks components are fully serializable.  After customizing any properties, instances can be saved along with any other beans to which they may be wired.  When reloaded, the instances will come back with their customized values.  No J2PrinterWorks properties are declared transient.

Copyright 2009, Wildcrest Associates (http://www.wildcrest.com )