すでにJavaプラットフォームを使用している方なら、おそらく、次から次へと変更される印刷APIに私と同じくらい不満を感じているでしょう。Merlinは、さらにJavaプラットフォームに別の印刷機能と印刷方法を提供します。この最新の変更はJava Print Service APIと呼ばれ、1999年以降Javaコミュニティー・プロセスを通じて進められてきました。幸運にも、新たなAPIは優れた追加変更であり、当面の間、印刷サポートの大きな変更としては最後のものになるでしょう。
新たなPrint Service APIによる印刷は、発見、指定、印刷の3つのプロセスで構成されます。もうひとつ、4番目のプロセスはオプションですが、印刷タスクの進行に伴う通知です。この記事で使用しているすべてのクラスとインターフェースは、javax.print パッケージ内にあるか、またはそのサブパッケージ内にあります (参考文献を参照)。
印刷ジョブを実行する最初のステップは、印刷を行うプリンターまたはプリンターのセットの特定です。プリンター・オブジェクトは印刷サービスと呼ばれ、識別プロセスは検索と呼ばれます。検索タスクのサポート・クラスには、PrintServiceLookup という適切な名前が付いています。印刷サービスを検索するには、リスト1で示されている3つのメソッドのうちの1つを使用します。
リスト1. 印刷サービスの検索
public static final PrintService
lookupDefaultPrintService()
public static final PrintService[]
lookupPrintServices(DocFlavor flavor, AttributeSet attributes)
public static final MultiDocPrintService[]
lookupMultiDocPrintServices(DocFlavor[] flavors,
AttributeSet attributes)
|
上記の3つのメソッドは、それぞれ異なるタスクに使用されます。
-
lookupDefaultPrintService()は、デフォルトの印刷サービスを戻します。 -
lookupPrintServices()は、特定の文書タイプ (GIFなど) を特定の属性セット (両面など) での印刷をサポートするプリンターのセットを戻します。 -
lookupMultiDocPrintServices()は、一度に複数の文書の印刷をサポートします。
使用する印刷サービスを決定したら、次に印刷ジョブを作成します。後でこのジョブに出力を送信します。検索によって戻されたPrintService は、次に示すようにcreatePrintJob() メソッドでこのジョブを作成するために使用することができます。
PrintService printService =
PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob job = printService.createPrintJob();
|
印刷を行う場所を指定するほかに、印刷文書の書式を指定しなければなりません。これには、DocFlavor クラス (またはそのサブクラスの1つ) を使うことになります。DocFlavor クラスは、印刷するオブジェクトのMIME (Multipurpose Internet Mail Extensions) タイプの特定に使用されます。MIMEタイプは、電子データがどのように解釈されるかを示します。e-mailや添付ファイルを使用している際にMIMEタイプを偶然見つけたことがあるかもしれませんが、MIME仕様はデータ形式を特定するためのより汎用的なメカニズムを記述したものです。
Merlinは、書式を定義するためにDocFlavorの7つのサブクラスを内部クラスとして提供しています。これらのクラスは、バイト指向、文字指向、およびサービス指向というMIMEタイプの3つのサブセットに分けることができます。バイト指向のフレーバーは以下のとおりです。
-
BYTE_ARRAY -
INPUT_STREAM -
URL
文字指向のフレーバーは以下のとおりです。
-
CHAR_ARRAY -
READER -
STRING
そしてサービス指向の内部クラスはSERVICE_FORMATTED です。
各フレーバーのタイプが、それぞれMIMEタイプのセットをサポートします。これらのMIMEタイプは、さらに内部クラスとして定義されています。バイト指向には、次のように19のフレーバーがあります。
-
AUTOSENSE -
GIF -
JPEG -
PCL -
PDF -
PNG -
POSTSCRIPT -
TEXT_HTML_HOST -
TEXT_HTML_US_ASCII -
TEXT_HTML_UTF_16 -
TEXT_HTML_UTF_16BE -
TEXT_HTML_UTF_16LE -
TEXT_HTML_UTF_8 -
TEXT_PLAIN_HOST -
TEXT_PLAIN_US_ASCII -
TEXT_PLAIN_UTF_16 -
TEXT_PLAIN_UTF_16BE -
TEXT_PLAIN_UTF_16LE -
TEXT_PLAIN_UTF_8
文字指向のストリームはバイト指向ほど大掛かりなものではなく、書式は次の2種類のみです。
-
TEXT_HTML -
TEXT_PLAIN
サービス指向のストリームには、次の3つの書式があります。
-
PAGEABLE -
PRINTABLE -
RENDERABLE_IMAGE
フレーバーは、次のように設定します (この例では、PNGイメージとして)。
DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG; |
印刷する際には、文書をどのように印刷するかを示す属性を指定することができます。属性の例としては、印刷部数、印刷するページ、文書イメージ (たとえば、横長か縦長か) などがあります。属性を指定するには、次の2つのクラスのうちの1つを使用する必要があります。
-
DocAttributeSetは、1つの文書に対する特性を指定します。 -
PrintRequestAttributeSetは、1つの印刷ジョブに対する特性を指定します。
印刷実行の属性を指定するには、適切なセットのインスタンス (DocAttributeSet またはPrintRequestAttributeSet) を作成し、印刷実行のための希望の属性を含めます。指定しない属性については、適切なデフォルトが設定されます。javax.print.attribute パッケージには約70種類の属性があり、それぞれ別のクラスとして定義されています。各属性は、1つまたは複数の属性セットに対して使用されます。この記事で使用している2つの属性セットのほかに、別の2つの属性セットを情報の照会に利用することができます。javax.print.attribute パッケージは、すべてのタイプの検索に共通の場所を提供しています。
以下は、PrintRequestAttributeSet を使用してオブジェクトを5部印刷する印刷実行です。
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(new Copies(5));
|
利用可能なすべての属性のリストについては、javax.print.attribute パッケージをご覧ください。
Doc インターフェースは、データを印刷ジョブに与えるためのものです。ここでは、このインターフェースのインプリメンターはSimpleDoc クラスです。単一のコンストラクターにより、最初のパラメーターが内容、2番目がフレーバー、3番目が属性として内容を指定します。コンストラクターを以下に示します。
public SimpleDoc(Object printData, DocFlavor flavor, DocAttributeSet attributes) |
これではまだ、データがどのようなものか疑問がのこります。これは、DocFlavorによって解決できます。DocFlavor.INPUT_STREAM のフレーバーを指定した場合、データはそのInputStream によって識別されます。フレーバーがDocFlavor.BYTE_ARRAY である場合、データはバイト配列です (byte [ ])。
そこでPNGイメージ・ファイルを印刷する場合は、リスト2の構文を使用することになります。
リスト2. 内容の設定
DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG;
String filename = ...;
FileInputStream fis = new FileInputSteam(filename);
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(fis, flavor, das);
|
プリンターを特定し、出力書式、属性、内容を指定すると、あとは印刷するだけです。実際の印刷ジョブは、リスト3に示すように、PrintService から取り出したDocPrintJob のprint() メソッドによって実行されます。
リスト3. 印刷ジョブ
DocPrintJob job = ...;
PrintRequestAttributeSet pras = ...;
Doc doc = ...;
job.print(doc, pras);
|
print() を呼び出してメカニズムを起動し、内容を別のスレッドの印刷サービスに送ります。
この記事でまだ説明していないことが一点あります。それは印刷ダイアログについてです。ダイアログはシステムのポップアップであり、これによってプリンター属性をグラフィカルに設定することができます。図1は、新たなJava Print Service APIの印刷ダイアログです。
図1. プリンター・ダイアログ
面白いことに、新たなAPIでは、プリンター・ダイアログのデフォルトの振る舞いが変更されました。デフォルトでは、ダイアログが表示されません。そのため、ServiceUI クラスを使用して、上記のような印刷ダイアログを作成する必要があります。
ServiceUI クラスは、プリンター選択ダイアログを表示するためのメソッドを一つ提供しています。
printDialog(GraphicsConfiguration gc, int x, int y, PrintService[] services, PrintService defaultService, DocFlavor flavor, PrintRequestAttributeSet attributes) |
次に、リスト4に示すように、戻されたPrintService を使用してDocPrintJob を取得し、それを使用して印刷します。
リスト4. ダイアログによる印刷
String filename = ...;
PrintRequestAttributeSet pras = ...;
DocFlavor flavor = ...;
PrintService printService[] =
PrintServiceLookup.lookupPrintServices(flavor, pras);
PrintService defaultService =
PrintServiceLookup.lookupDefaultPrintService();
PrintService service = ServiceUI.printDialog(null, 200, 200,
printService, defaultService, flavor, pras);
if (service != null) {
DocPrintJob job = service.createPrintJob();
FileInputStream fis = new FileInputStream(filename);
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(fis, flavor, das);
job.print(doc, pras);
}
|
最後に実施例を見てみましょう。この実施例では、新たなPrint Service APIの機能を実際に使ってみることができます。次のコードは、基本的に、これまで紹介したすべてのコード例を1つの実施可能なプログラムに統合したものです。プログラムを実行する際には、必ずPNGイメージ・ファイル名をコマンド・ラインに入力してください。異なる書式で印刷する場合は、DocFlavor を変更してください。
リスト5. 印刷例
import javax.print.*;
import javax.print.attribute.*;
import java.io.*;
public class Printing {
public static void main(String args[]) throws Exception {
String filename = args[0];
PrintRequestAttributeSet pras =
new HashPrintRequestAttributeSet();
DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG;
PrintService printService[] =
PrintServiceLookup.lookupPrintServices(flavor, pras);
PrintService defaultService =
PrintServiceLookup.lookupDefaultPrintService();
PrintService service = ServiceUI.printDialog(null, 200, 200,
printService, defaultService, flavor, pras);
if (service != null) {
DocPrintJob job = service.createPrintJob();
FileInputStream fis = new FileInputStream(filename);
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(fis, flavor, das);
job.print(doc, pras);
Thread.sleep(10000);
}
System.exit(0);
}
}
|
次回のMerlinの魔術の記事では、画面またはコンポーネントの内容を印刷する方法について説明します。また、印刷に関連するイベント処理タスクや、印刷操作からsleep() コールを取り除く方法についても説明します。
- 完全なJava Print Service APIの使用法を学ぶには、Sun Microsystemsの公式文書をご覧ください。
- TheJSR-006 Unified Printing API では、新たな印刷サービスの起源について簡単に説明しています。
- John Zukowskiによる、以下の 「Merlinの魔術」 シリーズもご一読ください。
- Swingの新たなSpinnerコンポーネント: JSpinner を使用して、ユーザーがピック・リストから素早く日付、数値および選択肢を選べるようにする
- もう1つのシンプルなフレーム: AWT Frameを最大化し、その装飾を取り外す
- 長期の永続性: JavaBeanコンポーネントの状態をXMLにシリアライズする
- 挿入順序を保持する: 新たにリンクされたHashSetとHashMapの実装を使ってみる
- タブ付きペインのスクロール: 大き過ぎて収まりきらない場合にどうするか
- Porter-Duffのルール!: Java 2Dが残りの4つのルールを追加
- プリファレンスを使ってみる: JSR 10、Preferences API Specificationによりプリファレンス・データと構成データの操作が可能に
- AWTの概要: サイジング、カラー、マウス・ホイール、および入力イベントの変更に関する詳細
- 例外とロギング: J2SEに対する有用な変更を活用し、問題を根絶し適切に応じよう
- アサーションの使用: Javaコードでアサーションを有効 / 無効にする方法
- developerWorksJavaテクノロジー・ゾーンでJavaプログラミングに関するさまざまな記事をご覧ください。

John Zukowskiは、JZ Ventures, Inc.の戦略的Javaコンサルティングを推進し、数多くのjGuruのコミュニティー主導のJava FAQsで常任指導者として活躍しています。最新の著書には、Apressから出版された「 Java Collections」および「 Definitive Guide to Swing for Java 2」 (第2版) があります。彼のメール・アドレスはjaz@zukowski.net です。