目次 | 前の項目 | 次の項目 | Java 2D API |
Java 印刷 API は、「コールバック」印刷モデルに基づいています。 このモデルでは、アプリケーションではなく印刷システムが、ページを印刷するときの制御を行います。 アプリケーションは、印刷するドキュメントについての情報を提供し、印刷システムは、ページのレンダリングが必要になると、それをアプリケーションに要求します。印刷システムは、同じページのレンダリングを 2 回以上要求したり、実際とは異なる順序でページのレンダリングを要求したりする場合があります。 印刷システムからどのページが要求されても、アプリケーションは正しいページイメージを生成できなければなりません。 この点、印刷システムはウィンドウツールキットと似ています。 ウィンドウツールキットは、いつでも、どのような順序でも、コンポーネントに再描画を要求できます。
コールバック印刷モデルは、従来のアプリケーション駆動の印刷モデルよりも柔軟性があり、より広範なシステムとプリンタでの印刷に対応しています。 たとえば、逆の順序で出力ページがスタックされるプリンタの場合、印刷システムはアプリケーションに逆の順序でページを生成するように要求することでスタックのページを正しい順序にすることができます。
このモデルを使うアプリケーションは、十分なメモリまたはディスク領域がないためページ全体のビットマップを蓄積できないコンピュータからでも、ビットマッププリンタに印刷できます。 この場合、ページは一連の小さなビットマップつまり「バンド」として印刷されます。 たとえば、1 ページの 10 分の 1 に相当する大きさのメモリしか利用できない場合、ページは 10 個のバンドに分割されます。 印刷システムは、アプリケーションに対し、ページごとにレンダリングを 10 回要求し、1 回で 1 つのバンドを埋めます。 アプリケーションは、バンドの数またはサイズを意識する必要はありません。 要求されたときにそのページをレンダリングできれば十分です。
アプリケーションは、印刷機能をサポートするために、次の 2 つの処理を行う必要があります。
ユーザは、アプリケーションのボタンをクリックしたりメニュー項目を選択したりして、印刷を開始します。 ユーザが印刷操作を起動すると、アプリケーションは、PrinterJob オブジェクトを作成し、それを使って印刷処理を管理します。アプリケーションは、印刷ジョブを設定し、ユーザに対して印刷ダイアログを表示し、印刷処理を開始します。
ドキュメントを印刷する場合、アプリケーションは印刷システムからの要求に対して各ページをレンダリングする必要があります。 この仕組みをサポートするため、アプリケーションは、Printable インタフェースを実装した「ページペインタ」を提供します。 印刷システムでページのレンダリングが必要になると、印刷システムはページペインタの print メソッドを呼び出します。ページペインタの print メソッドが呼び出されると、メソッドにはページイメージのレンダリングに使う Graphics コンテキストが渡されます。 また、ページの幾何学的レイアウトを指定する PageFormat オブジェクトと、印刷ジョブ内でのページの順番を示す整数の「ページインデックス」も渡されます。
印刷システムは、Graphics と Graphics2D の両方のレンダリングをサポートしています。 Java 2DTM の Shape、Text、および Image を印刷するには、print メソッドに渡す Graphics オブジェクトを Graphics2D にキャストします。
ページによって異なるページペインタと書式を使うドキュメントを印刷するには、「ページング可能 (Pageable) ジョブ」を使います。 Pageable ジョブを作るには、Book クラスを使うか、または Pageable インタフェースの独自の実装を使います。 単純な印刷操作を実装する場合は、Pageable 印刷ジョブを使う必要はありません。 すべてのページが同じページ書式とページペインタを共有する場合は、Printable を使うことができます。
ページペインタの主要な機能は、印刷システムから提供されるグラフィックスコンテキストを使って、ページをレンダリングすることです。 ページペインタは、次の Printable.print メソッドを実装しています。public int print(Graphics g, PageFormat pf, int pageIndex)
print メソッドに渡されるグラフィックコンテキストは、Graphics または Graphics2D のインスタンスです。 どちらを使うかは、Java Virtual Machine にロードされているパッケージによって決まります。 Graphics2D の機能を使うには、Graphics オブジェクトを Graphics2D オブジェクトにキャストします。 print に渡される Graphics インスタンスは、PrinterGraphics も実装しています。
Printable に渡される PageFormat では、印刷するページの幾何学的な配置 (ジオメトリ) が記述されています。 print に渡されるグラフィックスコンテキストの座標系は、そのページに固定されています。 座標系の原点は、用紙の左上隅です。X 座標の値は右に向かって、Y 座標の値は下に向かってそれぞれ増加し、単位は 1/72 インチです。ページの向きが縦の場合、x 軸は用紙の「幅」の方向になり、y 軸は用紙の「高さ」の方向になります。 用紙の高さは幅より長いのが普通ですが、そうでない場合もあります。 ページの向きが横の場合は、軸と用紙の関係が逆になり、x 軸が用紙の「高さ」方向、y 軸が用紙の「幅」方向になります。
用紙の縁まで印刷できるプリンタは少ないので、PageFormat ではページの「イメージング可能領域」が指定されています。これは、ページの中で安全にレンダリングできる部分です。 イメージング可能領域が指定されても、座標系は変わりません。 イメージング可能領域は、ページの内容をレンダリングするときに、プリンタが印刷できない領域まで広がることがないようにするためのものです。
print に渡されるグラフィックコンテキストにはクリッピング領域の情報が含まれていて、この情報では、イメージング可能領域の中で描画する必要のある部分が記述されています。 印刷システムが必要なクリッピング処理を行うため、コンテキストにページ全体を描画しても安全です。 ただし、クリッピング領域を使ってレンダリングされる範囲を制限することで、ページの中の印刷されない部分まで描画することによるオーバーヘッドを除くことができます。 グラフィックスコンテキストからクリッピング領域を取得するには、Graphics.getClip を呼び出します。
ページがレンダリングされている間でもユーザがアプリケーションと対話を続けることができるよう、印刷操作をすべて「バックグラウンド」で起動することが望ましい場合があります。 そのためには、独立したスレッドで PrinterJob.print を呼び出します。クリッピング領域を使ってレンダリングのオーバーヘッドを減らすことを、強くお勧めします。
copyArea、setXOR、合成などのように、前のイメージの内容についての情報が必要なグラフィックス操作は、できる限り避ける必要があります。 このような操作を行うと、レンダリングが遅くなり、結果の整合性が保たれない場合があります。
Printable ジョブは、印刷を行うもっとも簡単な方法です。 使うページペインタは 1 つだけで、アプリケーションは Printable インタフェースを実装する単一のクラスを提供します。 印刷を行うときは、印刷システムがページペインタの print メソッドを呼び出して、各ページをレンダリングします。 ページのインデックスは 0 から始まり、ページは順番どおりに要求されます。ただし、次のページに進む前に、同じページのレンダリング要求が何回もページペインタに対して行われる場合があります。 最後のページが印刷されると、ページペインタの print メソッドは NO_SUCH_PAGE を返します。
- すべてのページは、同じページペインタと PageFormat を使います。 印刷ダイアログを提示する場合、印刷システムはページ数の情報を利用できないため、ドキュメントのページ数は表示されません。
- 印刷システムは、常に、インデックスの順番にページの印刷をページペインタに要求します。 ページのインデックスは 0 から始まります。 ページが飛ぶことはありません。 たとえば、ユーザがドキュメントの 2 ページ目と 3 ページ目の印刷を要求した場合、ページペインタの呼び出しで指定されるインデックスは 0、1、および 2 になります。 印刷システムは、次のページの印刷に移る前に、同じページのレンダリングを複数回要求する場合があります。
- ドキュメントの末尾に達すると、ページペインタはそれを印刷システムに通知します。
- すべてのページペインタは、同じスレッドで呼び出されます。
- 印刷システムによっては、目的の出力結果が得られないことがあります。 たとえば、プリンタから出力されるページが正しい順番になっていなかったり、部数が複数の場合にページの丁合いが正しくなかったりする場合があります。
Pageable ジョブは、Printable ジョブより柔軟性があります。 Printable ジョブのページとは異なり、Pageable ジョブのページはレイアウトと実装が違っていてもかまいません。 Pageable ジョブを管理するには、Book クラスを使うか、または独自に Pageable クラスを実装します。 Pageable を使うと、印刷システムは、印刷するページ数、各ページで使うページペインタ、および各ページで使う PageFormat を特定できます。 決まった構造と書式を持つドキュメントを印刷する必要があるアプリケーションは、Pageable ジョブを使う必要があります
- ページごとに異なるページペインタと PageFormat を使うことができます。
- 印刷システムは、ページペインタに任意の順番でページの印刷を要求でき、途中のページが省かれる場合があります。 たとえば、ユーザがドキュメントの 2 ページ目と 3 ページ目の印刷を要求した場合、ページペインタの呼び出しで指定されるインデックスは 1 と 2 だけで、ページインデックス 0 は省略されます。
- Pageable ジョブでは、ドキュメントのページ数の情報があらかじめ必要になることはありません。 ただし、Printable ジョブとは異なり、どのような順序でもページをレンダリングできなければなりません。 順序指定は飛んでいる場合があり、印刷システムは、次のページの印刷に移る前に、同じページのレンダリングを複数回要求することがあります。 たとえば、ドキュメントの 2 ページ目と 3 ページ目を印刷する要求の場合、呼び出しで要求されるページのインデックスが 2、2、1、1、1 という順序になることもあります。
アプリケーションは、印刷ジョブが完了するまでの一連の手順に沿って、PrinterJob オブジェクトを制御します。 次に示すのは、もっとも簡単な手順です。
- PrinterJob.getPrinterJob を呼び出して、新しい PrinterJob オブジェクトを取得します。
- 印刷で使う PageFormat を決めます。 デフォルトの PageFormat を取得するには、defaultPage を呼び出します。 ユーザが書式を指定できるようダイアログボックスを表示するには、pageDialog を呼び出します。
- PrinterJob に印刷されるジョブの特性を指定します。 Printable ジョブの場合は、setPrintable を呼び出します。 Pageable ジョブの場合は、setPageable を呼び出します。 setPageable に渡すには Book オブジェクトが最善です。
- 印刷ジョブのそのほかのプロパティを指定します。 印刷する部数やバナーページに印刷するジョブの名前などです。
- 必要がある場合は、printDialog を呼び出し、ダイアログボックスをユーザに提示します。 これは省略可能です。 このダイアログの内容と表示形式は、プラットフォームやプリンタの種類により異なります。 大部分のプラットフォームでは、ユーザは、このダイアログボックスでプリンタの選択を変更できます。 ユーザが印刷ジョブをキャンセルすると、printDialog メソッドから FALSE が返されます。
- Printerjob.print を呼び出して、ジョブを印刷します。 このメソッドでは、適切なページペインタの print が呼び出されます。
次の場合、印刷の途中でジョブが終了することがあります。
印刷ジョブが停止する前に生成されたページは、印刷される場合とされない場合があります。一般に、print メソッドから戻った時点では、印刷ジョブは完了していません。 プリンタドライバ、プリンタサーバ、またはプリンタ自体での処理がまだ行われているのが普通です。 PrinterJob オブジェクトの状態は、印刷されている実際のジョブの状態を反映しない場合があります。
PrinterJob の状態は処理手順の過程で変化するので、メソッドによって、呼び出すと不正になるタイミングがあります。 たとえば、print を呼び出したあとで setPageable を呼び出しても無意味です。 不正な呼び出しを検出すると、PrinterJob は java.lang.IllegalStateException をスローします。
Java 印刷 API では、ユーザインタフェース用のダイアログをアプリケーションが明示的に呼び出すことが要求されます。 このようなダイアログは、プラットフォーム (Windows など) または JavaTM 2 SDK の実装で提供される場合があります。 対話型アプリケーションの場合、このようなダイアログを使うのが一般的です。 ただし、バッチ用印刷アプリケーションの場合は、ダイアログは必要ありません。 たとえば、夜間にデータベースのレポートを自動的に生成して印刷する場合など、ダイアログの表示は不要です。 ユーザの介入を必要としない印刷ジョブのことを、「サイレント」印刷ジョブと呼ぶ場合があります。
PageFormat に含まれるページ設定情報をユーザが変更できるようにするには、ページ設定ダイアログを表示します。 ページ設定ダイアログを表示するには、PrinterJob.pageDialog を呼び出します。 ページ設定ダイアログは、pageDialog に渡すパラメータで初期化されます。 ユーザがダイアログの [OK] ボタンをクリックすると、PageFormat のインスタンスが複製されて、ユーザの選択に従って変更されたあと、メソッドから返されます。 ユーザがダイアログでキャンセルを選択した場合は、変更されていない元の PageFormat が pageDialog から返されます。
通常、メニューの印刷項目または印刷ボタンが起動されると、アプリケーションはユーザに対して印刷ダイアログを提示します。 印刷ダイアログを表示するには、PrinterJob の printDialog を呼び出します。 PrinterJob に提供されている Printable または Pageable で設定されているページ数とページ書式に基づいて、ダイアログでのユーザの選択が制限されます。 印刷ダイアログでユーザが [OK] をクリックすると、printDialog からは TRUE が返されます。 ユーザが印刷ダイアログでキャンセルを選択すると、メソッドからは FALSE が返され、印刷ジョブが破棄されたものとして処理する必要があります。