Drucken eines JFrame und seiner Komponenten

Ich habe in einem großen Programm gearbeitet und eine seiner functionalitäten sollte sein, den Inhalt des Hauptfensters zu drucken. Ich habe die API überprüft und folgendes Beispiel gefunden:

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

Es war sehr hilfreich, ich habe versucht, diesen Code in meinem Programm zu verwenden, indem ich ihn in die actionperformed-Methode meiner Druckschaltfläche einfügte:

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 */ } } 

Wenn ich auf die Druckschaltfläche klicke, erhalte ich einen Druckerdialog und wenn ich es zum Drucken anschicke, druckt es nur ein leeres Dokument. Ich weiß, dass der obige Code nicht alles ist, was ich brauche, wie ich in den Beispielen der API gesehen habe, gibt es eine print () -Methode, aber anscheinend rufen sie sie nie auf, also ist es ziemlich verwirrend. Ich habe versucht, viele Male anzurufen und zu benutzen, aber ohne Erfolg.

Außerdem glaube ich, dass mein Fenster, wenn ich es zum Drucken fertig habe, in der Querformatausrichtung gedruckt werden muss, sogar eine Skalierung benötigt. Irgendwelche Ideen, wie man das macht?

Ich möchte jede nützliche Hilfe, um mir zu helfen, diesen Code erfolgreich zu implementieren. Ich weiß, ich sollte es alleine schaffen, indem ich die Dokumentation überprüfe (ich habe es jetzt seit fast 2 Tagen versucht), aber ich kann es nicht zum Laufen bringen. Ich habe all die Programmierung gelernt, die ich über das Internet kenne. Jede Hilfe wird sehr geschätzt.

Hier ist eine einfache Lösung. Ich habe eine Druckerklasse, die druckbar implementiert und den Druckauftrag übernimmt:

 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; } } 

Als nächstes, um es zu drucken:

 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(); } } 

Hier ist meine Vorstellung von der Idee …

Drucken, um zu passen …

A4-Fit

Drucken zum Ausfüllen …

A4-Füllen

 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; } } } 

Einige der weiter reichenden Probleme …

  • Sie werden mehr oder weniger für das Layout der gedruckten Komponenten verantwortlich. Zumindest wirst du sicherstellen wollen, dass sie entweder passen oder du hast eine Art Überlauf-Mechanismus ausgearbeitet …
  • Sie müssen möglicherweise Komponenten, die noch nicht auf dem Bildschirm angezeigt worden sind, “tricksen”, um zu denken, dass sie … daher alle addNotify herum mit addNotify / validate / doLayout . Auch wenn Sie auf dem Bildschirm angezeigt werden, müssen Sie diese Methoden aufrufen, wenn Sie ihre Grenzen ändern.