使用 javax.print 库使用属性(托盘控件、双面打印等)进行打印
一段时间以来,我一直在尝试确定一种使用标准Java Print库将具有某些属性的文件(特别是PDF文档)打印到某些托盘或使用双面打印的方法。
有很多关于如何做到这一点的文档,事实上,我已经研究并尝试了这些方法。典型的方式是这样的:
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();
}
}
简而言之,您执行以下操作
- 查找打印机
- 创建打印机作业
- 创建属性集
- 将属性添加到属性集,如托盘和双面打印
- 使用属性集在打印机作业上调用打印
这里的问题是,尽管这是记录的方法,以及我从几个教程中发现的方法,但这种方法...不起作用。现在请记住,我知道这听起来不是很描述,但请听我说。我不会轻易这么说...
PrinterJob 的官方文档实际上提到,在默认实现中忽略 AttributeSet。这里看到的源代码表明这是真的 - 属性被传递并完全忽略。
所以显然,你需要某种扩展版本的类,这可能是基于特定的打印机及其功能?我试图编写一些测试代码来告诉我这些功能 - 我们在办公室设置了各种各样的打印机,无论大小,简单或充满花里胡哨 - 更不用说我的计算机上的几个驱动程序仅用于伪打印机驱动程序,这些驱动程序只是创建文档和模拟打印机而无需使用任何类型的硬件。测试代码如下:
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"));
}
我发现的结果是,每台打印机都无一例外地返回“副本”受支持,而所有其他属性都不受支持。此外,每台打印机的功能都是相同的,无论这看起来多么难以置信。
不可避免的问题是多层次的:如何以注册属性的方式发送属性?此外,如何正确检测打印机的功能?实际上,PrinterJob 类是否实际上以可用的方式进行了扩展,或者属性是否始终被忽略?
我在互联网上找到的例子似乎向我表明,后一个问题的答案是“不,他们总是被忽略”,这对我来说似乎很荒谬(但随着我筛选数百页,这越来越可信)。这个代码是Sun简单地设置的,但从未工作到完成状态吗?如果是这样,是否有任何替代方案?