//Menu-Printvoid menuPrint_actionPerformed(ActionEvent e) { PrinterJob job = PrinterJob.getPrinterJob(); PageFormat format = job.pageDialog(job.defaultPage()); job.setPrintable(new PrintableDocument(myTextArea), format); if (job.printDialog()) try { job.print(); } catch(Exception e2) { }}
import java.awt.*;import java.awt.print.*;import java.awt.geom.*;import java.awt.font.*;import javax.swing.*;import javax.swing.text.*;import java.util.*;public class PrintableDocument implements Pageable, Printable { View root; // The root View to be printed PageFormat format; // Paper plus page orientation double scalefactor; // How much to scale before printing int numPages; // How many pages in the document double printX, printY; // coordinates of upper-left of print area double printWidth; // Width of the printable area double printHeight; // Height of the printable area Rectangle drawRect; // The rectangle in which the document is painted // How lenient are we with the bottom margin in widow/orphan prevention? static final double MARGIN_ADJUST = .97; // The font we use for printing page numbers static final Font headerFont = new Font("Serif", Font.PLAIN, 12); public PrintableDocument(JTextComponent textComponent) { this(textComponent, new PageFormat(), .75); } public PrintableDocument(JTextComponent textComponent, PageFormat format, double scalefactor) { // Remember the page format, and ask it for the printable area this.format = format; this.scalefactor = scalefactor; this.printX = format.getImageableX()/scalefactor; this.printY = format.getImageableY()/scalefactor; this.printWidth = format.getImageableWidth()/scalefactor; this.printHeight = format.getImageableHeight()/scalefactor; double paperWidth = format.getWidth()/scalefactor; // Get the document and its root Element from the text component Document document = textComponent.getDocument(); Element rootElement = document.getDefaultRootElement(); // Get the EditorKit and its ViewFactory from the text component EditorKit editorKit =textComponent.getUI().getEditorKit(textComponent); ViewFactory viewFactory = editorKit.getViewFactory(); // Use the ViewFactory to create a root View object for the document root = viewFactory.create(rootElement); root.setParent(new ParentView(root, viewFactory, textComponent)); root.setSize((float)printWidth, (float)printHeight); // Now that the view has formatted itself for the specified width, double documentHeight = root.getPreferredSpan(View.Y_AXIS); // Set up the rectangle that tells the view where to draw itself // We'll use it in other methods of this class. drawRect = new Rectangle(0, 0, (int)printWidth, (int)documentHeight); // Now if the document is taller than one page, we have to // figure out where the page breaks are. if (documentHeight > printHeight) paginate(root, drawRect); // Once we've broken it into pages, figure out how many pages. numPages = pageLengths.size() + 1; } // This is the starting offset of the page we're currently working on double pageStart = 0; protected void paginate(View v, Rectangle2D allocation) { // Figure out how tall this view is, and tell it to allocate // that space among its children double myheight = v.getPreferredSpan(View.Y_AXIS); v.setSize((float)printWidth, (float)myheight); // Now loop through each of the children int numkids = v.getViewCount(); for(int i = 0; i < numkids; i++) { View kid = v.getView(i); // this is the child we're working with // Figure out its size and location Shape kidshape = v.getChildAllocation(i, allocation); if (kidshape == null) continue; Rectangle2D kidbox = kidshape.getBounds2D(); double kidpos = kidbox.getY() + kidbox.getHeight() - pageStart; if ((numkids > 1) && (i == 0)) { if (kidpos < printY + printHeight*MARGIN_ADJUST) continue; breakPage(kidbox.getY()); continue; } if ((numkids > 1) && (i == numkids-1)) { if (kidpos < printY + printHeight) continue; if (kidpos < printY + printHeight/MARGIN_ADJUST) { breakPage(allocation.getY() + allocation.getHeight()); continue; } } if (kidpos < printY+printHeight) continue; if (kid.getViewCount() == 0) { breakPage(kidbox.getY()); continue; } paginate(kid, kidbox); } } // For a document of n pages, this list stores the lengths of pages // 0 through n-2. The last page is assumed to have a full length ArrayList pageLengths = new ArrayList(); // For a document of n pages, this list stores the starting offset of // pages 1 through n-1. The offset of page 0 is always 0 ArrayList pageOffsets = new ArrayList(); // Break a page at the specified Y coordinate. Store the necessary // information into the pageLengths and pageOffsets lists void breakPage(double y) { double pageLength = y-pageStart-printY; pageStart = y-printY; pageLengths.add(new Double(pageLength)); pageOffsets.add(new Double(pageStart)); } public int getNumberOfPages() { return numPages; } public PageFormat getPageFormat(int pagenum) { if (pagenum == numPages-1) return format; double pageLength = ((Double)pageLengths.get(pagenum)).doubleValue(); PageFormat f = (PageFormat) format.clone(); Paper p = f.getPaper(); if (f.getOrientation() == PageFormat.PORTRAIT) p.setImageableArea(printX*scalefactor, printY*scalefactor, printWidth*scalefactor, pageLength*scalefactor); else p.setImageableArea(printY*scalefactor, printX*scalefactor, pageLength*scalefactor, printWidth*scalefactor); f.setPaper(p); return f; } public Printable getPrintable(int pagenum) { return this; } public int print(Graphics g, PageFormat format, int pageIndex) { if (pageIndex >= numPages) return NO_SUCH_PAGE; // Cast the Graphics object so we can use Java2D operations Graphics2D g2 = (Graphics2D)g; // Translate to accomodate the top and left margins g2.translate(format.getImageableX(), format.getImageableY()); // Scale the page by the specified scaling factor g2.scale(scalefactor, scalefactor); if (pageIndex > 0) { Shape originalClip = g.getClip(); g.setClip(new Rectangle(0, (int)-printY, (int)printWidth, (int)printY)); // Compute the header to display, measure it, then display it String numString = "- " + (pageIndex+1) + " -"; // Get string and font measurements FontRenderContext frc = g2.getFontRenderContext(); Rectangle2D numBounds = headerFont.getStringBounds(numString, frc); LineMetrics metrics = headerFont.getLineMetrics(numString, frc); g.setFont(headerFont); // Set the font g.setColor(Color.black); // Print with black ink g.drawString(numString, // Display the string (int)((printWidth-numBounds.getWidth())/2), (int)(-(printY-numBounds.getHeight())/2 + metrics.getAscent())); g.setClip(originalClip); // Restore the clipping region } // Get the staring position and length of the page within the document double pageStart = 0.0, pageLength = printHeight; if (pageIndex > 0) pageStart = ((Double)pageOffsets.get(pageIndex-1)).doubleValue(); if (pageIndex < numPages-1) pageLength = ((Double)pageLengths.get(pageIndex)).doubleValue(); g2.translate(0.0, -pageStart); root.paint(g, drawRect); return PAGE_EXISTS; } static class ParentView extends View { ViewFactory viewFactory; // The ViewFactory for the hierarchy of views Container container; // The Container for the hierarchy of views public ParentView(View v, ViewFactory viewFactory, Container container) { super(v.getElement()); this.viewFactory = viewFactory; this.container = container; } // These methods return key pieces of information required by // the View hierarchy. public ViewFactory getViewFactory() { return viewFactory; } public Container getContainer() { return container; } public void paint(Graphics g, Shape allocation) {} public float getPreferredSpan(int axis) { return 0.0f; } public int viewToModel(float x,float y,Shape a,Position.Bias[] bias) { return 0; } public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { return a; } }}