当前位置: 首页 > 面试题库 >

使JComponent适应/缩放到要打印的页面

缑修齐
2023-03-14
问题内容

我正在尝试缩放组件,以便它可以适合单个打印页面(人像或风景)

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

我对图形不太熟悉,因此不胜感激


问题答案:

基本概念是使用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;

    }
}


 类似资料:
  • 我使用PdfiumViewer来打印PDF文件: 在我的,,和事件中,我没有执行任何操作,只是对文件进行一些日志。 PDF文件已打印,但文档每页的左右边距都被剪掉了,因此我正在尝试将每个PDF文档页面与默认打印机中当前默认选择的纸张尺寸相匹配。我该怎么做?

  • 现在需要将这个架构图可以等比例放大缩小,像地图那样的加个按钮点击,求问怎样可以实现? 之前的提问有回答用vue-panzoom和vue2-leaflet的,但是我尝试了下发现用上这个内容就不显示了,也许是适配问题,想请问有没有适用于vue3的?

  • 我有一个表单,允许用户上传图像。 加载映像后,我们对其执行一些缩放,以便在将其传递回服务器之前减小其文件大小。 为此,我们将其放置在画布上并在画布上进行操作。 这段代码将在画布上呈现缩放后的图像,画布大小为320 x 240px: ... 哪里有帆布。宽度和画布。高度是图像高度和宽度x,是基于原始图像大小的比例因子。 但当我使用代码时: ...我只得到画布上图像的一部分,在这种情况下是左上角。我需

  • 问题内容: 我已经阅读了很多有关打印页码的网站,但是当我尝试打印html页面时,仍然无法显示它。 接下来是CSS代码: 我试图把这个页面规则放进去 在其外部,尝试将其放入中,但没有任何帮助使我在页面上显示页码。我尝试使用FireFox和Chrome(您知道基于WebKit的浏览器)。我认为问题出在我的HTML或CSS代码中。 有人可以告诉我一个在具有多个页面的大html页面中实现此规则的示例吗?我

  • 问题内容: 这是Sun教程中的基本打印程序示例: 当显示打印对话框时(第二行),用户可以选择仅打印文档中的页面范围。我能以某种方式获得要打印的页数吗?例如,如果我有一个25页的文档,但是用户选择打印4-10的范围,那么将只打印7页。是否有某种方式可以访问该信息? 我需要它来显示进度条,该进度条随着每打印一页的增加而增加,但是为此,我需要知道将要打印的总页数。 那我怎么得到那个数字呢? 问题答案:

  • 我有一个java的列表。awt。图像,每个分辨率为300 DPI。我想打印它们,当我开始打印这些图像时(使用javax.PrintService API),只打印一些图像的一部分,因为Java的打印/3D类默认使用72DPI(相对于我的图像的300 DPI)。但是,当我使用72 DPI的图像(与Java默认值具有相同的分辨率)时,所有图像都可以很好地打印(打印整个图像时,而不仅仅是其中的一部分)。