适合/缩放JComponent到正在打印的页面
我正在尝试缩放我的组件,以便它可以放在单个打印的页面上(纵向或横向)
gDiagram.getComponent()
是我试图打印的组件(JPanel)。
以下是我如何基于如何打印单个JPanel的内容?
/** * Prints the diagram. */ public void printDiagram() { PrinterJob pj = PrinterJob.getPrinterJob(); pj.setJobName(" Print Component "); pj.setPrintable(new Printable() { @Override public int print(Graphics g, PageFormat pf, int pageNumber) throws PrinterException { // TODO Auto-generated method stub if (pageNumber > 0) { return Printable.NO_SUCH_PAGE; } Graphics2D g2 = (Graphics2D) g; g2.translate(pf.getImageableX(), pf.getImageableY()); double sx = pf.getImageableWidth() / gDiagram.getComponent().getWidth(); double sy = pf.getImageableHeight() / gDiagram.getComponent().getHeight(); gDiagram.getComponent().paint(g2); g2.scale(sx, sy); return Printable.PAGE_EXISTS; } }); if (!pj.printDialog()) { return; } try { pj.print(); } catch (PrinterException ex) { System.out.println(ex); } }
我不太熟悉graphics,所以任何帮助,将不胜感激
基本的概念是使用AffineTransformation
来对结果输出进行缩放。
在我的testing中,我能够拍摄7680×4800的图像,并打印在595×842的页面上(缩小了93%)。
import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.File; import java.io.IOException; import java.text.NumberFormat; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class PrintTest { public static void main(String[] args) { new PrintTest(); } public PrintTest() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } final TestPane imagePane = new TestPane(); JButton print = new JButton("Print"); print.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { printComponent(imagePane); } }); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(imagePane); frame.add(print, BorderLayout.SOUTH); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private BufferedImage bg; public TestPane() { try { bg = ImageIO.read(new File("path/to/a/image")); } catch (IOException ex) { Logger.getLogger(PrintTest.class.getName()).log(Level.SEVERE, null, ex); } } @Override public Dimension getPreferredSize() { return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); if (bg != null) { int x = (getWidth() - bg.getWidth()) / 2; int y = (getHeight() - bg.getHeight()) / 2; g2d.drawImage(bg, x, y, this); } g2d.dispose(); } } public void printComponent(Component comp) { PrinterJob pj = PrinterJob.getPrinterJob(); pj.setJobName(" Print Component "); pj.setPrintable(new ComponentPrintable(comp)); if (!pj.printDialog()) { return; } try { pj.print(); } catch (PrinterException ex) { System.out.println(ex); } } public class ComponentPrintable implements Printable { private Component comp; private ComponentPrintable(Component comp) { this.comp = comp; } @Override public int print(Graphics g, PageFormat pf, int pageNumber) throws PrinterException { // TODO Auto-generated method stub if (pageNumber > 0) { return Printable.NO_SUCH_PAGE; } // Get the preferred size ofthe component... Dimension compSize = comp.getPreferredSize(); // Make sure we size to the preferred size comp.setSize(compSize); // Get the the print size Dimension printSize = new Dimension(); printSize.setSize(pf.getImageableWidth(), pf.getImageableHeight()); // Calculate the scale factor double scaleFactor = getScaleFactorToFit(compSize, printSize); // Don't want to scale up, only want to scale down if (scaleFactor > 1d) { scaleFactor = 1d; } // Calcaulte the scaled size... double scaleWidth = compSize.width * scaleFactor; double scaleHeight = compSize.height * scaleFactor; // Create a clone of the graphics context. This allows us to manipulate // the graphics context without begin worried about what effects // it might have once we're finished Graphics2D g2 = (Graphics2D) g.create(); // Calculate the x/y position of the component, this will center // the result on the page if it can double x = ((pf.getImageableWidth() - scaleWidth) / 2d) + pf.getImageableX(); double y = ((pf.getImageableHeight() - scaleHeight) / 2d) + pf.getImageableY(); // Create a new AffineTransformation AffineTransform at = new AffineTransform(); // Translate the offset to out "center" of page at.translate(x, y); // Set the scaling at.scale(scaleFactor, scaleFactor); // Apply the transformation g2.transform(at); // Print the component comp.printAll(g2); // Dispose of the graphics context, freeing up memory and discarding // our changes g2.dispose(); comp.revalidate(); return Printable.PAGE_EXISTS; } } public static double getScaleFactorToFit(Dimension original, Dimension toFit) { double dScale = 1d; if (original != null && toFit != null) { double dScaleWidth = getScaleFactor(original.width, toFit.width); double dScaleHeight = getScaleFactor(original.height, toFit.height); dScale = Math.min(dScaleHeight, dScaleWidth); } return dScale; } public static double getScaleFactor(int iMasterSize, int iTargetSize) { double dScale = 1; if (iMasterSize > iTargetSize) { dScale = (double) iTargetSize / (double) iMasterSize; } else { dScale = (double) iTargetSize / (double) iMasterSize; } return dScale; } }