使用 javax.print 库打印属性(托盘控制、双面打印等...) [英] Printing with Attributes(Tray Control, Duplex, etc...) using javax.print library

查看:67
本文介绍了使用 javax.print 库打印属性(托盘控制、双面打印等...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间以来,我一直在尝试确定一种使用标准 Java 打印库来打印具有某些属性的文件(特别是 PDF 文档)的方法——特别是, 到某些纸盘或使用双面打印.

I've been trying for some time to determine a way to use the standard Java Print library to print files - specifically, PDF documents - with certain attributes - specifically, to certain trays or using duplex.

存在大量关于如何完成此操作的文档,事实上,我已经研究并尝试了这些方法.典型的方式是这样的:

There exists plenty of documentation on how this should be done, and indeed, I've researched and tried these methods. The typical way is something like this:

public static void main (String [] args) {
    try {

        PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null, null);

        //Acquire Printer
        PrintService printer = null;
        for (PrintService serv: pservices) {
            System.out.println(serv.toString());
            if (serv.getName().equals("PRINTER_NAME_BLAH")) {
                printer = serv;
            }
        }

        if (printer != null) {
            System.out.println("Found!");


            //Open File
            FileInputStream fis = new FileInputStream("FILENAME_BLAH_BLAH.pdf");

            //Create Doc out of file, autosense filetype
            Doc pdfDoc = new SimpleDoc(fis, DocFlavor.INPUT_STREAM.AUTOSENSE, null);

            //Create job for printer
            DocPrintJob printJob = printer.createPrintJob();

            //Create AttributeSet
            PrintRequestAttributeSet pset = new HashPrintRequestAttributeSet();

            //Add MediaTray to AttributeSet
            pset.add(MediaTray.TOP);

            //Add Duplex Option to AttributeSet
            pset.add(Sides.DUPLEX);

            //Print using Doc and Attributes
            printJob.print(pdfDoc, pset);

            //Close File
            fis.close();

        }

    }
    catch (Throwable t) {
        t.printStackTrace();
    }
}

简而言之,您执行以下操作

In short, you do the following

  1. 找到打印机
  2. 创建打印机作业
  3. 创建一个属性集
  4. 向AttributeSet添加属性,例如Tray和Duplex
  5. 使用 AttributeSet 调用打印机作业的打印

这里的问题是,尽管有记录的这样做的方法,以及我从几个教程中发现的,但这种方法......不起作用.现在请记住,我知道这听起来不太好描述,但请听我说完.我不是随便说的...

The problem here is that, despite being the documented way of doing this, as well as what I've found from several tutorials, this method... doesn't work. Now keep in mind, I know that doesn't sound very descript, but hear me out. I don't say that lightly...

PrinterJob 的官方文档 实际上提到在默认实现中忽略 AttributeSet.此处看到的源代码 表明这是真的 - 属性被传入并被完全忽略.

The official documentation for PrinterJob actually mentions that the AttributeSet is ignored in the default implementation. Source code seen here shows this to be true - the attributes are passed in and ignored entirely.

很明显,您需要类的某种扩展版本,这可能基于特定的打印机及其功能?我试图编写一些测试代码来告诉我这些功能 - 我们在办公室设置了各种各样的打印机,或大或小,简单或充满花里胡哨 - 更不用说我电脑上的几个驱动程序只是为了伪- 打印机驱动程序,无需使用任何硬件即可创建文档和模拟打印机.测试代码如下:

So apparently, you need some sort of extended version of the class, which is possibly based on the specific printers and their capabilities? I attempted to write some test code that would tell me such capabilities - we have a large variety of printers set up at the office, large or small, simple or full of bells and whistles - not to mention several drivers on my computer just for pseudo-printer drivers that just create documents and simulate printers without going to any sort of hardware. The test code is as follows:

public static void main (String [] args) {

    PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null, null);

    for (PrintService serv: pservices) {
        System.out.println(serv.toString());

        printFunctionality(serv, "Trays", MediaTray.class);
        printFunctionality(serv, "Copies", Copies.class);
        printFunctionality(serv, "Print Quality", PrintQuality.class);
        printFunctionality(serv, "Color", ColorSupported.class);
        printFunctionality(serv, "Media Size", MediaSize.class);
        printFunctionality(serv, "Accepting Jobs", PrinterIsAcceptingJobs.class);
    }
}

private static void printFunctionality(PrintService serv, String attrName, Class<? extends Attribute> attr) {
    boolean isSupported = serv.isAttributeCategorySupported(attr);
    System.out.println("    " + attrName + ": " + (isSupported ? "Y" : "N"));
}

我发现的结果是,每台打印机都无一例外地返回支持副本",而所有其他属性都不支持.此外,每台打印机的功能都是相同的,无论这看起来多么令人难以置信.

The results I found were that every printer, without exception, returned that "copies" were supported, and all other attributes were not. Furthermore, every printer's capabilities were identical, regardless of how implausible that would seem.

不可避免的问题是多层次的:如何以注册的方式发送属性?此外,如何正确检测打印机的功能?确实,PrinterJob 类实际上是以可用的方式扩展的,还是总是忽略属性?

The inevitable question is multi-layered: How does one send in attributes in a way that they are registered? Additionally, how does one properly detect the capabilities of a printer? Indeed, is the PrinterJob class actually extended in a usable way at all, or are the Attributes always ignored?

我在整个互联网上找到的例子似乎向我暗示后一个问题的答案是不,它们总是被忽略",这对我来说似乎很荒谬(但随着我筛选数百页,越来越可信).Sun 只是简单地设置了这段代码,但从未运行 到完成状态吗?如果是这样,还有其他选择吗?

Examples I've found throughout The Internet seem to suggest to me that the answer to the latter question is "No, they are always ignored", which seems ridiculous to me (but increasingly more believable as I sift through hundreds of pages). Is this code that Sun simply set up but never got working to a completed state? If so, are there any alternatives?

推荐答案

因此,我们不可避免地找到了一种打印到不同托盘和不同设置的方法,但不是直接打印.我们发现无法通过 printJob.print 方法发送属性,而且这一点并没有改变.但是,我们能够设置打印作业的名称,然后使用低级 Perl 脚本拦截打印作业,解析名称,并在那里设置纸盘和双面打印设置.这是一个极端的黑客,但它有效.Java 打印机属性不起作用仍然是正确的,如果您想设置它们,您将需要另一种方法.

So, we inevitably found a way to print to different trays and with different settings, but not directly. We found it impossible to send attributes via the printJob.print method, and that much hasn't changed. However, we were able to set the name of the print job, then intercept the print job with a low-level Perl script, parse the name, and set the tray and duplex settings there. It's an extreme hack, but it works. It still remains true that Java Printer Attributes do not work, and you will need to find another way if you want to set them.

这篇关于使用 javax.print 库打印属性(托盘控制、双面打印等...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆