模块  java.desktop

Package javax.print.attribute

提供描述Java™打印服务属性类型的类和接口,以及如何将它们收集到属性集中。

什么是属性?

设置打印作业时,客户端指定两件事: 打印数据处理指令。 打印数据是要打印的实际内容。 处理指令告诉打印机如何打印打印数据,例如:使用什么介质,打印多少份,以及是否在纸张的一面或两面打印。 客户端使用Java Print Service API的属性定义指定这些处理指令。

打印数据和处理指令是分开的实体。 这意味着:

  • 您可以使用不同的处理说明在不同时间打印相同的打印数据。
    例如,您可以在美国信纸大小的白纸上打印幻灯片演示文稿,双面,装订,20份副本,以便为演讲提供讲义; 并且您可以在美国信纸大小的透明胶片上打印相同的幻灯片演示文稿,单面,一个副本以制作用于谈话的实际幻灯片。
  • 您可以在不同时间使用相同的处理说明来打印不同的数据。 例如,您可以将默认处理说明设置为:美国信纸大小的纸张,双面,装订。 无论何时打印作业,它都会使用这些设置进行打印,除非您明确覆盖它们。
处理指令没有指定打印作业如何处理请求; 每个处理指令仅是对打印作业结果的描述。 打印作业确定它实现处理指令指定的结果的方式。 将处理指令表示为描述性项目为实现打印作业提供了更大的灵活性。

属性类别和值

每台打印机都具有一组功能,例如能够在不同纸张尺寸上打印或能够打印多个副本。 每个功能都有一系列值。 例如,打印机的方向功能可能具有以下值范围:[landscape,portrait]。 对于每个打印请求,功能都设置为这些值之一。 Java Print Service API使用术语属性类别来引用打印机功能,使用术语属性值来引用功能的值。

在Java Print Service API中,属性类别由实现Attribute接口的Java类表示。 属性值是此类或其子类之一的实例。 例如,要指定副本数,应用程序将构造具有所需副本数的Copies类的实例,并将Copies实例用作打印请求的一部分。 在这种情况下, Copies类表示属性类别, Copies实例表示属性值。

属性角色

当向打印机提交打印作业时,客户端提供描述打印数据特征的属性,例如文档名称,以及应如何打印打印数据,例如双面,五份。 如果打印作业由多个打印数据组成,则不同的部分可能具有不同的处理指令,例如第一个文档的8 x 11英寸介质和另一个文档的11 x 17英寸介质。

一旦打印机开始处理打印作业,就可以获得有关作业的其他信息,其中可能包括:作业状态(例如已完成排队 )以及到目前为止打印的页数。 这些信息也是属性。 属性还可以描述打印机本身,例如:打印机名称,打印机位置和排队的作业数。

Java Print Service API使用Attribute五个子接口定义了这些不同类型的属性:

每个属性类都实现一个或多个这些标记子接口,以指示可以在API中使用该属性的位置。 如果属性类实现多个标记子接口,则该属性可以在多个上下文中使用。 例如,媒体属性可以应用到一个文档中打印作业的DocAttribute或整个打印作业为PrintRequestAttribute 某些低级属性从不单独使用,但始终聚合为更高级别的属性。 这些低级属性类仅实现接口Attribute ,而不是任何标记子接口。

Java Print Service API定义了一组标准属性类,这些属性类是根据Internet打印协议(IPP)1.1版中的属性建模的。 标准属性类位于子包javax.print.attribute.standard以使实际属性类在概念上与包javax.print.attribute定义的通用装置javax.print.attribute

属性集

在提交打印作业时,客户端通常需要提供多个处理指令。 例如,客户端可能需要指定A4的介质尺寸和横向。 要发送多个处理指令,客户端会将属性收集到属性集中,Java Print Service API使用AttributeSet接口表示该属性集。

AttributeSet接口类似于Map接口:它提供了值的键的映射,其中每个键都是唯一的,并且可以包含不超过一个值。 但是, AttributeSet接口旨在专门支持Java Print Service API的需求。 AttributeSet要求:

  1. AttributeSet每个键对应一个类别,键的值只能是属于键所代表的类别的属性值之一。 因此,与Map不同, AttributeSet限制键的可能值:属性类别不能设置为不属于该类别的属性值。
  2. 同一类别中的两个属性不能存在于同一个集合中。 例如,属性集合不能同时包含“单面”属性和“双面”属性,因为这两个属性会给打印机提供冲突的指令。
  3. 只有实现Attribute接口的属性才能添加到集合中。
javax.print.attribute包中包含HashAttributeSet作为属性集接口的具体实现。 HashAttributeSet提供基于哈希映射的属性集。 您可以使用此实现或提供您自己的接口AttributeSet的实现。

Java Print Service API提供了属性集的四个特化,这些特化仅限于包含四种属性中的一种,如Attribute Roles部分所述:

请注意,此处仅列出了四种属性集,但有五种属性。 接口SupportedValuesAttribute表示为另一个属性提供支持的值的属性。 Supported-values属性永远不会聚合到属性集中,因此没有为它们定义属性集子接口。

在某些上下文中,属性集是只读的,这意味着只允许客户端检查属性集的内容但不更改它们。 在其他上下文中,属性集是读写的,这意味着允许客户端检查和更改属性集的内容。 对于只读属性集,调用变异操作会抛出UnmodifiableSetException

javax.print.attribute包括每个属性javax.print.attribute一个具体实现:

所有这些类都扩展为HashAttributeSet并强制执行限制,即只允许属性集包含相应类型的属性。

属性类设计

属性值是一个小的原子数据项,例如整数或枚举值。 由于以下原因,Java Print Service API不使用原始数据类型(如int)来表示属性值:
  • 原始数据类型不是类型安全的。 例如,编译器不应允许“副本”属性值用于“sides”属性。
  • 某些属性必须表示为多个值的记录。 一个例子是打印机分辨率,它需要两个数字,例如600和300代表600 x 300 dpi。
对于类型安全并统一表示所有属性,Java Print Service API将每个属性类别定义为类,例如类Copies ,类Sides和类PrinterResolution 每个属性类都包含一个或多个包含属性值的原始数据项。 在添加属性,查找同一类别中的现有属性以及查找给定其类别的属性时,属性集操作会在属性类别对象之间执行频繁的比较。 由于属性类别由类表示,因此可以使用Class.equals方法执行快速属性值比较。

即使Java Print Service API包含大量不同的属性类别,也只有几种不同类型的属性值。 大多数属性可以由少量数据类型表示,例如:整数值,整数范围,文本或整数值的枚举。 类别接受的属性值的类型称为属性的抽象语法。 为了提供一致性并减少代码重复,Java Print Service API定义了抽象语法类来表示每个抽象语法,并且尽可能将这些类用作标准属性的父类。 抽象语法类是:

  • EnumSyntax提供了类型安全的枚举,其中枚举值表示为单例对象。 每个枚举单例都是包含隐藏的int值的枚举类的实例。
  • IntegerSyntax是整数值属性的抽象语法。
  • TextSyntax是文本值属性的抽象语法,包括提供文本字符串自然语言的语言环境。
  • SetOfIntegerSyntax是表示范围或整数集的属性的抽象语法
  • ResolutionSyntax是表示分辨率值的属性的抽象语法,例如600x300 dpi。
  • Size2DSyntax是表示二维尺寸的属性的抽象语法,例如纸张尺寸为8.5 x 11英寸。
  • DateTimeSyntax是属性的抽象语法,其值为日期和时间。
  • URISyntax是属性的抽象语法,其值为统一资源指示符。
抽象语法类独立于使用它们的属性。 实际上,与打印无关的应用程序可以使用抽象语法类。 虽然大多数标准属性类扩展了一个抽象语法类,但是不需要任何属性类来扩展其中一个类。 抽象语法类仅提供可由许多属性类共享的方便实现。

每个属性类直接或间接地实现Attribute接口,以将其标记为打印属性。 可以出现在某些上下文中的受限属性集中的属性类也实现了一个或多个子接口Attribute 大多数属性类还扩展了适当的抽象语法类以获得实现。 考虑Sides属性类:


 public class Sides
     extends EnumSyntax
     implements DocAttribute, PrintRequestAttribute, PrintJobAttribute
 {
     public final Object getCategory()
     {
         return Sides.class;
     }
 ...
 }
 

由于每个属性类都实现了Attribute ,因此每个属性类都必须为getCategory方法提供实现,该方法返回属性类别。 Sides的情况下, getCategory方法返回Sides.class getCategory方法是最终的,以确保标准属性类的任何供应商定义的子类出现在同一类别中。 每个属性对象一旦构造就是不可变的,这样属性对象引用就可以自由传递。 要获取不同的属性值,请构造不同的属性对象。

属性供应商

Java Print Service API旨在使供应商能够:
  • javax.print.attribute.standard中定义的任何标准属性定义新的特定于供应商的值。
  • 定义新的属性类别,表示供应商打印机的标准属性尚未支持的专有功能。
要为属性定义新值,客户端可以在运行时使用任意值构造此类属性的实例。 但是,使用抽象语法类EnumSyntax的枚举属性在编译时将所有可能的属性值指定为属性类的单例实例。 这意味着无法在运行时构造新的枚举值。 要为标准枚举属性定义新的特定于供应商的值,供应商必须定义一个新的属性类,指定新的单例实例。 要确保新属性值与标准属性值属于同一类别,新属性类必须是标准属性类的子类。

要定义新的属性类别,供应商定义新的属性类。 与标准属性类一样,此属性类实现Attribute或其子接口之一,并扩展了抽象语法类。 供应商可以使用现有的抽象语法类或定义新的语法类。 在使用Attribute任何地方都可以使用新的供应商定义的属性,例如在AttributeSet

使用属性

典型的打印应用程序使用PrintRequestAttributeSet因为print-request属性是客户端通常指定的属性类型。 此示例演示如何创建一个print-request属性的属性集,并找到可以根据指定的属性打印文档的打印机:

 FileInputStream psStream;
 try {
     psstream = new FileInputStream("file.ps");
 } catch (FileNotFoundException ffne) {
 }
 if (psstream == null) {
     return;
 }
 //Set the document type. See the DocFlavor documentation for
 //more information.
 DocFlavor psInFormat = DocFlavor.INPUT_STREAM.POSTSCRIPT;
 Doc myDoc = new SimpleDoc(pstream, psInFormat, null);
 PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
 aset.add(new Copies(5));
 aset.add(MediaSize.A4);
 aset.add(Sides.DUPLEX);
 PrintService[] services =
     PrintServiceLookup.lookupPrintServices(psInFormat, aset);
 if (services.length > 0) {
     DocPrintJob job = services[0].createPrintJob();
     try {
         job.print(myDoc, aset);
     } catch (PrintException pe) {}
 }
 

请注意:在javax.print API中,方法的null参考参数不正确,除非在方法上明确记录为具有有意义的解释。 相反的用法是不正确的编码,并且可能立即或稍后导致运行时异常。 IllegalArgumentExceptionNullPointerException是此类情况的典型和可接受的运行时异常的示例。

从以下版本开始:
1.4