使 JComponent 适合/缩放到正在打印的页面 [英] Fit/Scale JComponent to page being printed
问题描述
我正在尝试缩放我的组件,使其适合单个打印页面(纵向或横向)
I'm trying to scale my component so it can fit on a single printed page (portrait or landscape)
gDiagram.getComponent()
是我要打印的组件 (JPanel).
is the component (JPanel) I'm trying to print.
这是我到目前为止基于 我怎么做打印单个 JPanel 的内容?
Here's what I've got so far based on 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);
}
}
我不太熟悉图形,所以任何帮助将不胜感激
I'm not too familiar with graphics, so any help would be appreciated
推荐答案
基本概念是使用 AffineTransformation
为结果输出提供缩放.
The basic concept is to use an AffineTransformation
to provide scaling to the resulting output.
在我的测试中,我能够拍摄 7680x4800 的图像并打印在 595x842 的页面上(缩小了大约 93%)
In my tests, I was able to take an image of 7680x4800 and get printed on a page of 595x842 (scaled down by something like 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;
}
}
这篇关于使 JComponent 适合/缩放到正在打印的页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!