2013-07-28 20 views
3

我想我的扩展组件,因此它可以适应一个打印页面(纵向或横向)飞度/缩放JComponent的页面被打印

gDiagram.getComponent() 

是组件(JPanel中)我想上打印。

这是我到目前为止已经有基于How can I print a single JPanel's contents?

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

我不是太熟悉的图形,所以任何帮助,将不胜感激

+0

这[示例](HTTP(通过像93%按比例缩小) .com/a/7028497/230513)使用'AffineTransformOp'。 – trashgod

+0

组件是否会缩放到页面上? – MadProgrammer

+0

@MadProgrammer嗨 - 我不明白你的问题对不起 –

回答

7

的基本概念是使用AffineTransformation来为结果输出提供缩放。 //计算器:

在我的测试中,我能够采取的7680x4800的图像,并得到印595x842页面上

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; 

    } 
} 
+0

应该//打印组件 comp.printAll(g2); be comp.paintAll(g2); ? 如果不是,有什么区别? :S –

+0

有一些差异。首先Swing组件是双缓冲的,这使得更新更加无缝,打印时不需要这些开销。此外,您还可以自定义输出以进行打印(您并不关心)。另外,如果没有连接到本地对等体(即没有显示在屏幕上),我看到组件会抛出异常。它是'printAll',没有'paintAll'方法;) – MadProgrammer

+0

很酷。 你的意思是两者都有compSize.width? /Calcaulte尺寸缩放... double scaleWidth = compSize.width * scaleFactor; double scaleHeight = compSize.width * scaleFactor; –