Articles Projects Tips Downloads Contacts About

Printing/Previewing of the JEditorPane/JTextPane content with any EditorKit set.
By Stanislav Lapitsky

 

In contrast to Pageable editor kit described in article above which provides kit for WYSIWYG editor this library allows direct printing of JEditorPane/JTextPane’s content. The print output is still paginated though but the pagination doesn’t depend on custom kit. The Printer performs paginated layout of views structure based on locations and sizes of all leaves views. In simple case the leaves are fragments of text represented by LabelView class or images. Also e.g. HTMLEditorKit has ComponentViews to render all possible controls like textfields, buttons, checkboxes etc supported in HTML.

The Printer usage demo app uses HTMLEditorKit from SUN to show how this works. It provides print preview as well as direct printing of content. User should specify source JEditorPane with installed kit and set text, Paper, and paper margins.


To print JEditorPane with HTMLEditorKit (or RTFEditorKit or simple StyledEditorKit) download the JEditorPanePrinter.jar and use the code below

                import article.print.*;

                EditorPanePrinter pnl=new EditorPanePrinter(editorPaneInstance, new Paper(), new Insets(18,18,18,18));
                pnl.print();

NOTE: in java 1 inch=72 pixels so insets 18 piels = 0.25".

or user can specify desired PrintService

                EditorPanePrinter pnl=new EditorPanePrinter(editorPaneInstance, new Paper(), new Insets(18,18,18,18));
                pnl.print(printService);

The JEditorPanePrinter class extends JPanel so it can be used as preview by adding in any dialog/frame programmer likes.

Base implementation principles of the Printer.

When user passes Paper and margins to the Printer the real page width and page height is defined (Page Width = Paper width – left margin – right margin, Page Height = Paper Height – top margin – bottom margin). A temporary JEditorPane is created and content of source is cloned. The dummy JEditorPane’s width is set to page width to provide proper horizontal layout.

Then we calculate number of pages by following algorithm:

  1. Each page has startY. For the first page it’s 0.
  2. To define next page’s startY we set desiredY = previous page’s startY + pageHeight.
  3. The line intersects some of leaf views (e.g. 2 LabelViews). For all the intersected views’ rectangles we find minimal y. That’s the real next page’s startY.
  4. So the page contains only the views which fit the page height.
  5. Use the found startY to find next page’s startY.

After this we have list of pages with startY and custom page height (less than initial page height and will be different for different pages).

One more step is excluding views which don’t fit the page bounds. Then each page has own custom shape (see picture below) to leave only fully rendered views. For each such page a child panel is created. All the page panels uses the same dummy pane and own shape to render necessary fragment on page. Thus the panels can be used to render pages on preview or print the pages.

NOTE: ComponentView from SUN has a bit unusual algorithm. In fact it doesn’t render nested component but add the component to container and set its bounds. The component is rendered by container. To fix this on print all the components are rendered separately.

                sourcePane.paint(g);
                for (Component c:sourcePane.getComponents() ) {
                    AffineTransform tmp=((Graphics2D)g).getTransform();
                    g.translate(c.getX(), c.getY());
                    ((Container)c).getComponent(0).paint(g);
                    ((Graphics2D)g).setTransform(tmp);
                }

There is a bug in JDK 1.6. Printing monospaced font sometimes produces incorrectly aligned results.

The JEditorPanePrinter.jar library contains full source code so the described behaviour can be changed to satisfy any user’s needs.

Back to Table of Content