【问题标题】:Using PrinterJob to print an Image (Graphics2D)使用 PrinterJob 打印图像 (Graphics2D)
【发布时间】:2013-01-05 04:17:49
【问题描述】:

有没有一种方法可以让 Java 中的 PrinterJob 不实际打印到打印机,以便获取每个页面的图形对象?我尝试将 PrintService 设置为 null,但 Java 不允许这样做。

这样我就可以检索文档的准确打印预览,而无需在不同的上下文中从头开始重建 PrinterJobs 函数。

这是我程序中打印功能的代码:

public int print(Graphics graphics, PageFormat pageFormat, int page) throws PrinterException {

    deepCopyString = string;

    FontMetrics metrics = graphics.getFontMetrics(font);
    int lineHeight = metrics.getHeight();

    arrangePage(graphics, pageFormat, metrics);

    if (page > pageBreaks.length){
        return NO_SUCH_PAGE;
    }

    Graphics2D g = (Graphics2D) graphics;

    g.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
    g.setFont(font);

    int begin = (page == 0) ? 0 : pageBreaks[page-1];
    int end = (page == pageBreaks.length) ? lines.length : pageBreaks[page];

    int y = 0;
    int x = 0;

    for (int line = begin; line < end; line++){
        x = 0;
        y += lineHeight;

        checkSyntax(line);

        String l = lines[line];

        for (int c = 0; c < l.length(); c++){
            applySyntax(c, line);

            metrics = graphics.getFontMetrics(font);
            String ch = Character.toString(l.charAt(c));

            g.setFont(font);
            g.drawString(ch, x, y);

            x += metrics.charWidth(l.charAt(c));
            //System.out.println(c + "/"+l.length());
        }

        //g.drawString(lines[line], 0, y);
    }

    reset();

    records.add(g);

    return PAGE_EXISTS;
}

您已经可以看到 Graphics 对象已被记录,因此我可以在另一个组件中绘制它们,但它会继续并在记录完成之前将它们发送到我的打印机,因此没有什么用。

总的来说,这可能是个坏主意,而且我对打印还很陌生。如果这确实是一个糟糕的解决方法,请随时将我引导到可以解释更好方法的来源。

【问题讨论】:

    标签: java graphics printing export awt


    【解决方案1】:

    基本上,您想创建自己的 Graphics 上下文,您可以在其中进行绘制。您还需要构造一个 PageFormat 可以传递给 print 方法。

    public class TestPrint implements Printable  {
    
        private BufferedImage background;
        public static final float DPI = 72;
    
        public static void main(String[] args) {
            new TestPrint();
        }
    
        public TestPrint() {
    
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
    
                    try {
                        background = ImageIO.read(new File("C:/Users/shane/Dropbox/MegaTokyo/MgkGrl_Yuki_by_fredrin.jpg"));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
    
                    float width = cmToPixel(21f, DPI);
                    float height = cmToPixel(29.7f, DPI);
    
                    Paper paper = new Paper();
                    float margin = cmToPixel(1, DPI);
                    paper.setImageableArea(margin, margin, width - (margin * 2), height - (margin * 2));
                    PageFormat pf = new PageFormat();
                    pf.setPaper(paper);
    
                    BufferedImage img = new BufferedImage(Math.round(width), Math.round(height), BufferedImage.TYPE_INT_RGB);
                    Graphics2D g2d = img.createGraphics();
                    g2d.setColor(Color.WHITE);
                    g2d.fill(new Rectangle2D.Float(0, 0, width, height));
                    try {
                        g2d.setClip(new Rectangle2D.Double(pf.getImageableX(), pf.getImageableY(), pf.getImageableWidth(), pf.getImageableHeight()));
                        print(g2d, pf, 0);
                    } catch (PrinterException ex) {
                        ex.printStackTrace();
                    }
                    g2d.dispose();
    
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new JLabel(new ImageIcon(img)));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                }
            });
    
        }
    
        public float cmToPixel(float cm, float dpi) {
    
            return (dpi / 2.54f) * cm;
    
        }
    
        public int print(Graphics graphics, PageFormat pageFormat, int page) throws PrinterException {
    
            if (page > 0) {
                return NO_SUCH_PAGE;
            }
    
            Graphics2D g = (Graphics2D) graphics;
    
            g.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
            if (background != null) {
    
                int x = (int)Math.round((pageFormat.getImageableWidth() - background.getWidth()) / 2f);
                int y = (int)Math.round((pageFormat.getImageableHeight() - background.getHeight()) / 2f);
    
                g.drawImage(background, x, y, null);
    
            }
    
            g.setColor(Color.BLACK);
            g.draw(new Rectangle2D.Double(0, 0, pageFormat.getImageableWidth() - 1, pageFormat.getImageableHeight() - 1));
    
            return PAGE_EXISTS;
        }
    }
    

    现在,很明显,打印到屏幕上的内容和打印到打印机上的内容会有所不同,因为我们实际上并没有使用相同的硬件设备,但基本概念适用

    【讨论】:

    • 那么,如果我直接从可打印对象调用 print() 方法,那么它实际上不会将纸张发送到打印机?
    • 不,它将使用您提供的图形上下文进行渲染 - 这是一种经典的打印预览方法...
    • 非常感谢您的帮助。
    • @MadProgrammer 如果图像具有像此图像salishseacentre.org/wp-content/uploads/2009/09/dl-photos/300/… 这样的大尺寸,您的代码将不起作用我该怎么办?任何想法
    • @ShanXeeshi For example
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 2013-11-08
    相关资源
    最近更新 更多