Imprimir un JFrame y sus componentes

He estado trabajando en un gran progtwig y una de sus funcionalidades debería ser imprimir los contenidos de la ventana principal. Revisé la API y encontré este ejemplo:

http://docs.oracle.com/javase/tutorial/2d/printing/gui.html

fue muy útil, traté de usar ese código en mi progtwig colocando esto dentro del método actionperformed de mi botón de impresión:

PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(this); boolean ok = job.printDialog(); if (ok) { try { job.print(); } catch (PrinterException ex) { /* The job did not successfully complete */ } } 

Si hago clic en el botón Imprimir, aparece un cuadro de diálogo de impresora y cuando digo que imprima, solo imprime un documento en blanco. Sé que el código anterior no es todo lo que necesito, como he visto en los ejemplos de la API hay un método de impresión (), pero aparentemente nunca lo llaman, por lo que es bastante confuso. Intenté llamarlo y usarlo muchas veces, pero sin éxito.

Además, creo que cuando finalmente lo imprima, mi ventana deberá imprimirse con orientación horizontal, incluso puede necesitar algunas escalas. ¿Alguna idea sobre cómo hacer eso?

Me gustaría cualquier ayuda útil para ayudarme a implementar este código con éxito. Sé que debería poder hacerlo solo con solo consultar la documentación (lo he intentado durante casi 2 días) pero no puedo hacerlo funcionar. Aprendí toda la progtwigción que conozco a través de internet. Cualquier ayuda será apreciada.

Aquí hay una solución simple. Tengo una clase de impresora que implementa imprimible y que manejará el trabajo de impresión:

 public static class Printer implements Printable { final Component comp; public Printer(Component comp){ this.comp = comp; } @Override public int print(Graphics g, PageFormat format, int page_index) throws PrinterException { if (page_index > 0) { return Printable.NO_SUCH_PAGE; } // get the bounds of the component Dimension dim = comp.getSize(); double cHeight = dim.getHeight(); double cWidth = dim.getWidth(); // get the bounds of the printable area double pHeight = format.getImageableHeight(); double pWidth = format.getImageableWidth(); double pXStart = format.getImageableX(); double pYStart = format.getImageableY(); double xRatio = pWidth / cWidth; double yRatio = pHeight / cHeight; Graphics2D g2 = (Graphics2D) g; g2.translate(pXStart, pYStart); g2.scale(xRatio, yRatio); comp.paint(g2); return Printable.PAGE_EXISTS; } } 

Luego, para imprimirlo:

 JFrame yourComponent = new JFrame(); PrinterJob pjob = PrinterJob.getPrinterJob(); PageFormat preformat = pjob.defaultPage(); preformat.setOrientation(PageFormat.LANDSCAPE); PageFormat postformat = pjob.pageDialog(preformat); //If user does not hit cancel then print. if (preformat != postformat) { //Set print component pjob.setPrintable(new Printer(yourComponent), postformat); if (pjob.printDialog()) { pjob.print(); } } 

Aquí está mi giro en la idea …

Imprimir para adaptarse …

A4-Fit

Imprimir para llenar …

A4-Fill

 public class TestPrinting { public static void main(String[] args) { try { printComponentToFile(new PrintForm(), true); printComponentToFile(new PrintForm(), false); } catch (PrinterException exp) { exp.printStackTrace(); } } public static void printComponent(JComponent comp, boolean fill) throws PrinterException { PrinterJob pjob = PrinterJob.getPrinterJob(); PageFormat pf = pjob.defaultPage(); pf.setOrientation(PageFormat.LANDSCAPE); PageFormat postformat = pjob.pageDialog(pf); if (pf != postformat) { //Set print component pjob.setPrintable(new ComponentPrinter(comp, fill), postformat); if (pjob.printDialog()) { pjob.print(); } } } public static void printComponentToFile(Component comp, boolean fill) throws PrinterException { Paper paper = new Paper(); paper.setSize(8.3 * 72, 11.7 * 72); paper.setImageableArea(18, 18, 559, 783); PageFormat pf = new PageFormat(); pf.setPaper(paper); pf.setOrientation(PageFormat.LANDSCAPE); BufferedImage img = new BufferedImage( (int) Math.round(pf.getWidth()), (int) Math.round(pf.getHeight()), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = img.createGraphics(); g2d.setColor(Color.WHITE); g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight())); ComponentPrinter cp = new ComponentPrinter(comp, fill); try { cp.print(g2d, pf, 0); } finally { g2d.dispose(); } try { ImageIO.write(img, "png", new File("Page-" + (fill ? "Filled" : "") + ".png")); } catch (IOException ex) { ex.printStackTrace(); } } public static class ComponentPrinter implements Printable { private Component comp; private boolean fill; public ComponentPrinter(Component comp, boolean fill) { this.comp = comp; this.fill = fill; } @Override public int print(Graphics g, PageFormat format, int page_index) throws PrinterException { if (page_index > 0) { return Printable.NO_SUCH_PAGE; } Graphics2D g2 = (Graphics2D) g; g2.translate(format.getImageableX(), format.getImageableY()); double width = (int) Math.floor(format.getImageableWidth()); double height = (int) Math.floor(format.getImageableHeight()); if (!fill) { width = Math.min(width, comp.getPreferredSize().width); height = Math.min(height, comp.getPreferredSize().height); } comp.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height)); if (comp.getParent() == null) { comp.addNotify(); } comp.validate(); comp.doLayout(); comp.printAll(g2); if (comp.getParent() != null) { comp.removeNotify(); } return Printable.PAGE_EXISTS; } } } 

Algunos de los problemas de mayor scope …

  • Usted se convierte en responsable del diseño de los componentes impresos, más o menos. Al menos querrás asegurarte de que encajen o que tengas algún tipo de mecanismo de desbordamiento funcionado …
  • Es posible que tenga que “engañar” a los componentes que aún no se han mostrado en la pantalla para que piensen que son … por lo tanto, todo lo addNotify con addNotify / validate / doLayout . Incluso cuando se muestran en la pantalla, si modifica sus límites, puede necesitar llamar a estos métodos.