2013-07-28 2 views
3

Я пытаюсь масштабировать свой компонент, так что он может поместиться на одной печатной страницы (книжная или альбомная)Fit/Scale 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: // StackOverflow .com/a/7028497/230513) использует 'AffineTransformOp'. – trashgod

+0

Будет ли компонент, начинающий масштабироваться, вписываться в страницу? – MadProgrammer

+0

@MadProgrammer Привет - Я не понимаю ваш вопрос извините –

ответ

7

Основная концепция заключается в использовании AffineTransformation для обеспечить масштабирование полученного результата.

В моих тестах, я был в состоянии принять образ 7680x4800 и получить напечатанный на странице 595x842 (масштабируется вниз что-то вроде 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; 

    } 
} 
+0

should // Распечатать компонент comp.printAll (g2); be comp.paintAll (g2); ? Если нет, какая разница? : S –

+0

Существует ряд отличий. Для начала компоненты Swing имеют двойной буфер, это делает обновления более плавными, вам не нужны эти накладные расходы при печати. Кроме того, вы также можете настроить вывод для печати (что вам все равно). Кроме того, если он не подключен к собственному одноранговому узлу (т.е. не показан на экране), я видел, что компоненты генерируют исключение. Это 'printAll', нет метода' paintAll';) – MadProgrammer

+0

Прохладный. Вы имели в виду иметь compSize.width для обоих? /Calcaulte масштабированный размер ... двойной масштабWidth = compSize.width * масштабFactor; двойной масштабHeight = compSize.width * scaleFactor; –

Смежные вопросы