【问题标题】:How to print a border around the virtual page when the actual page is larger当实际页面较大时如何在虚拟页面周围打印边框
【发布时间】:2019-06-28 18:42:19
【问题描述】:

我的程序打印 A6 尺寸的页面,但是我经常使用较大的纸张。在这种情况下,我想在 A6 虚拟页面周围打印一个边框来帮助我修剪纸张。但如果我使用实际的 A6 纸,我想要一个可行的解决方案。

我在 macOS 上运行。

我将 pageDialog() 配置为所需的页面大小(3.75 x 6.75 英寸)和完整大小的可成像区域。验证后返回的 PageFormat 与该大小和可成像区域匹配。

但是,当我的 Printable 被调用时,PageFormat 不同:纸张尺寸为 3.875 x 7.5 英寸,可成像区域为 3.375 x 6.55 英寸,左边距为 0.25 英寸,上边距为 0.2 英寸.我可以理解上边距,因为 8.5 x 11 英寸纸上的实际打印在纸的顶部。左边距不明显,因为实际打印是水平居中的。 (打印机显然知道纸张宽度,但也许软件不知道打印机会做什么?)

我画了边框:

double paperWidth = 3.75 * 72;
double paperHeight = 6.75 * 72;
g.draw(new Rectangle2D.Double(2, 2, paperWidth - 2, paperHeight - 2));

(2 是一个虚假因素。)

我得到的只是底部的一条细线,但侧面没有。 (我不关心顶部。)如果可成像区域导致剪裁,这是有道理的。

我已尝试更改可成像区域和剪辑区域,但没有任何改变。

pageFormat.getPaper().setImageableArea(0, 0, paperWidth, paperHeight);
g = (Graphics2D) g.create();
g.setClip(0, 0, (int) paperWidth, (int) paperHeight);
g.draw(new Rectangle2D.Double(2, 2, paperWidth - 2, paperHeight - 2));
g.dispose();

【问题讨论】:

    标签: java printing


    【解决方案1】:

    至于你的代码为什么不能工作,我不能说,因为没有足够的证据来确定。似乎很明显的一件事是,您在绘画时忽略了页边距,这将是一个问题。此外,您不能在打印过程中更改PageFormat,因为此信息已用于生成物理打印作业(到打印机)。

    下面的例子基本假设输出页面的期望目标是A6,如果页面大小不合适,它会在代表A6页面的区域周围打印一个边框。

    这个例子还远未完成,因为我没有考虑如果页面变小会发生什么,只是变大了,你需要弄清楚。

    该示例将页面默认为 A4,边距非常小(0.1 厘米),但默认页面的概念应该保持不变

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Shape;
    import java.awt.geom.Rectangle2D;
    import java.awt.image.BufferedImage;
    import java.awt.print.PageFormat;
    import java.awt.print.Paper;
    import java.awt.print.Printable;
    import java.awt.print.PrinterException;
    import java.awt.print.PrinterJob;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    
    public class Test {
    
        public static PaperSize A6_PAPER = new PaperSize(toPPI(4.1), toPPI(5.8));
        public static PaperSize A4_PAPER = new PaperSize(toPPI(8.27), toPPI(11.69));
    
        public static void main(String[] args) throws IOException {
            BufferedImage background = ImageIO.read(new File("/Users/shanew/Downloads/1512455_10152727077279377_24129534228312133_n.jpg"));
            PrinterJob pj = PrinterJob.getPrinterJob();
            if (pj.printDialog()) {
                PageFormat pf = pj.defaultPage();
                Paper paper = pf.getPaper();
    
                double width = A4_PAPER.getWidth();            
                double height = A4_PAPER.getHeight();
                paper.setSize(width, height);
                paper.setImageableArea(
                        fromCMToPPI(0.1),
                        fromCMToPPI(0.1),
                        width - fromCMToPPI(0.1),
                        height - fromCMToPPI(0.1));
                pf.setOrientation(PageFormat.PORTRAIT);
                pf.setPaper(paper);
                PageFormat validatePage = pj.validatePage(pf);
                pj.setPrintable(new FancyOutput(background), validatePage);
                try {
                    pj.print();
                } catch (PrinterException ex) {
                    ex.printStackTrace();
                }
            }
        }
    
        public static class FancyOutput implements Printable {
    
            protected static final Rectangle2D BORDER = new Rectangle2D.Double(0, 0, A6_PAPER.getWidth() - 1, A6_PAPER.getHeight() - 1);
    
            private BufferedImage background;
    
            public FancyOutput(BufferedImage background) {
                this.background = background;
            }
    
            @Override
            public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
                Graphics2D g2d = (Graphics2D) g.create();
                if (page != 0) {
                    return NO_SUCH_PAGE;
                }
                double width = pf.getImageableWidth();
                double height = pf.getImageableHeight();
    
                double x = pf.getImageableX();
                double y = pf.getImageableY();
    
                if (width != A6_PAPER.getWidth() || height != A6_PAPER.getHeight()) {
                    x = x + ((width - A6_PAPER.getWidth()) / 2);
                    y = y + ((height - A6_PAPER.getHeight()) / 2);
    
                    System.out.println(x + "x" + y);
                }
    
                g2d.translate((int) x,
                        (int) y);
                Shape oldClip = g2d.getClip();
                g2d.setClip(BORDER);
                g2d.drawImage(background, 0, 0, null);
    
                g2d.setClip(oldClip);
                if (width != A6_PAPER.getWidth() || height != A6_PAPER.getHeight()) {
                    g2d.setColor(Color.RED);
                    g2d.draw(BORDER);
                }
    
                g2d.dispose();
    
                return PAGE_EXISTS;
            }
    
        }
    
        public static class PaperSize {
    
            private double width;
            private double height;
    
            public PaperSize(double width, double height) {
                this.width = width;
                this.height = height;
            }
    
            public double getWidth() {
                return width;
            }
    
            public double getHeight() {
                return height;
            }
        }
    
        protected static double fromCMToPPI(double cm) {
            return toPPI(cm * 0.393700787);
        }
    
        protected static double toPPI(double inch) {
            return inch * 72d;
        }
    }
    

    【讨论】:

    • 你测试过这段代码吗?在什么操作系统上?传递给 print 方法的 PageFormat 是否显示了打印机中的纸张尺寸?
    • 是的,从屏幕截图可以看出,它是在 Mac OS 上测试的
    • 如果纸张尺寸不同会怎样?传递给 print 方法的 PageFormat 是否显示了打印机中的纸张尺寸?
    • 是的。这就是示例使用它来确定何时绘制板以及如何使输出居中的原因
    • 抱歉,我需要更多说明。我的程序不会根据打印机中的纸张接收信息,而是根据在打印对话框中选择的纸张尺寸接收信息。这是你的经历吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 2021-04-25
    • 2017-07-04
    相关资源
    最近更新 更多