目次 | 前へ | 次へ

第 7 章

印刷

アプリケーションでは、Java 印刷 API を使って次の処理が可能です。

  • AWT と Java 2D™ のすべてのグラフィックスを印刷する。合成されたグラフィックスおよびイメージを含む。
  • ソフト丁合い、逆順印刷、ブックレット印刷など、文書編成機能の制御。
  • 両面印刷やホッチキス留めなど、プリンタ固有の機能の実行。
  • Windows や Solaris など、すべてのプラットフォームでの印刷。コンピュータに直接接続されているプリンタだけでなく、ネットワーク印刷プロトコルを使ってプラットフォームのソフトウェアからアクセスできるプリンタを含む。

これらの機能の中には、Java™ 2 SDK の印刷 API と実装ではサポートされていないものもあります。将来的には、これらの機能をすべてサポートするように API が拡張される予定です。たとえば、アプリケーションが制御できる印刷ジョブの名前付きプロパティーのセットを増やすことで、別のプリンタ制御機能が追加されます。

7.1 インタフェースとクラス

インタフェース
説明
Printable
Printable インタフェースは、ページペインタごとに実装されます。ページペインタは、印刷システムがページをレンダリングするために呼び出すアプリケーションクラスです。システムは、ページペインタの print メソッドを呼び出し、ページのレンダリングを要求します。
Pageable
Pageable インタフェースは、印刷システムで印刷されるドキュメントが実装します。システムは、Pageable のメソッド群を使って、ドキュメントのページ数、各ページで使われる書式、および各ページのレンダリングに使うページペインタを判断できます。
PrinterGraphics
ページをレンダリングするためにページペインタが使う Graphics2D オブジェクトは、PrinterGraphics インタフェースを実装します。これにより、アプリケーションは、印刷を制御する PrinterJob オブジェクトを取得できます。
クラス
説明
Book
インタフェース: Pageable
ページごとに異なるページ書式とページペインタを使用できるドキュメントを表します。このクラスは、Pageable インタフェースを使って、PrinterJob と対話します。
PageFormat
印刷するページのサイズと向き、および印刷に使う Paper を記述します。たとえば、用紙の向きのは、PageFormat で表されます。
Paper
1 枚の用紙の物理的特性を記述します。
PrinterJob
印刷を制御する重要なクラスです。アプリケーションは、PrinterJob のメソッド群を呼び出し、ジョブのセットアップ、ユーザーへの印刷ダイアログの表示 (オプション)、ジョブの中でのページの印刷などを行います。

7.2 印刷のコンセプト

Java 印刷 API は、コールバック印刷モデルに基づいています。このモデルでは、アプリケーションではなく印刷システムが、ページを印刷するときの制御を行います。アプリケーションは、印刷するドキュメントについての情報を提供し、印刷システムは、各ページのレンダリングが必要になると、それをアプリケーションに要求します。

印刷システムは、特定のページのレンダリングを 2 回以上要求したり、実際とは異なる順序でページのレンダリングを要求したりする場合があります。印刷システムからどのページが要求されても、アプリケーションは正しいページイメージを生成できなければなりません。この点、印刷システムはウィンドウツールキットと似ています。ウィンドウツールキットは、いつでも、どのような順序でも、コンポーネントに再描画を要求できます。

コールバック印刷モデルは、従来のアプリケーション駆動の印刷モデルよりも柔軟性があり、より広範なシステムとプリンタでの印刷に対応しています。たとえば、逆の順序で出力ページがスタックされるプリンタの場合、印刷システムはアプリケーションに逆の順序でページを生成するように要求することで最終のスタックを正しい読み取り順序にすることができます。

このモデルを使うアプリケーションは、十分なメモリーまたはディスク領域がないためページ全体のビットマップをバッファリングできないコンピュータからでも、ビットマッププリンタに印刷できます。この場合、ページは一連の小さなビットマップ、つまりバンドとして印刷されます。たとえば、1 ページの 10 分の 1 をバッファリングできるだけのメモリーしか利用できない場合、ページは 10 個のバンドに分割されます。印刷システムは、アプリケーションに対し、ページごとにレンダリングを 10 回要求し、1 回で 1 つのバンドを埋めます。アプリケーションは、バンドの数またはサイズを意識する必要はありません。要求されたときにそのページをレンダリングできれば十分です。

7.2.1 印刷のサポート

アプリケーションは、印刷機能をサポートするために、次の 2 つのタスクを行う必要があります。

  • ジョブ制御 - 印刷ジョブの起動と管理。
  • イメージング - 印刷システムから要求された各ページのレンダリング。

7.2.1.1 ジョブの制御

ユーザーは通常、アプリケーションのボタンをクリックしたりメニュー項目を選択したりして、印刷を開始します。ユーザーが印刷操作を起動すると、アプリケーションは、PrinterJob オブジェクトを作成し、それを使って印刷処理を管理します。

アプリケーションは、印刷ジョブを設定し、ユーザーに対して印刷ダイアログを表示し、印刷処理を開始します。

7.2.1.2 イメージング

ドキュメントを印刷する場合、アプリケーションは印刷システムからの要求に対して各ページをレンダリングする必要があります。このメカニズムをサポートするため、アプリケーションは、Printable インタフェースを実装したページペインタを提供します。印刷システムでページのレンダリングが必要になると、印刷システムはページペインタの print メソッドを呼び出します。

ページペインタの print メソッドが呼び出されると、メソッドにはページイメージのレンダリングに使う Graphics コンテキストが渡されます。また、ページの幾何学的レイアウトを指定する PageFormat オブジェクトと、印刷ジョブ内でのページの順番を示す整数のページインデックスも渡されます。

印刷システムは、GraphicsGraphics2D の両方のレンダリングをサポートしています。Java 2D™ の ShapesText、および Images を印刷するには、print メソッドに渡す Graphics オブジェクトを Graphics2D にキャストします。

ページによって異なるページペインタと書式を使うドキュメントを印刷するには、ページング可能 (Pageable) ジョブを使います。Pageable ジョブを作るには、Book クラスを使うか、または Pageable インタフェースの独自の実装を使います。単純な印刷操作を実装する場合は、Pageable 印刷ジョブを使う必要はありません。すべてのページが同じページ書式とページペインタを共有する場合は、Printable を使うことができます。

7.2.2 ページペインタ

ページペインタの主要なジョブは、印刷システムから提供されるグラフィックスコンテキストを使って、ページをレンダリングすることです。ページペインタは、次の Printable.print メソッドを実装しています。

public int print(Graphics g, PageFormat pf, int pageIndex)  

print メソッドに渡されるグラフィックコンテキストは、Graphics または Graphics2D のインスタンスです。どちらを使うかは、Java 仮想マシンにロードされているパッケージによって決まります。Graphics2D の機能を使うには、Graphics オブジェクトを Graphics2D オブジェクトにキャストします。print に渡される Graphics インスタンスは、PrinterGraphics インタフェースも実装しています。

Printable に渡される PageFormat では、印刷するページの幾何学的な配置 (ジオメトリ) が記述されています。print に渡されるグラフィックスコンテキストの座標系は、そのページに固定されています。座標系の原点は、用紙の左上隅です。X 座標の値は右に向かって、Y 座標の値は下に向かってそれぞれ増加し、単位は 1/72 インチです。ページの向きが縦の場合、x 軸は用紙の「幅」の方向になり、y 軸は用紙の「高さ」の方向になります。用紙の高さは幅より長いのが普通ですが、そうでない場合もあります。ページの向きが横の場合は、軸と用紙の関係が逆になり、x 軸が用紙の「高さ」方向、y 軸が用紙の「幅」方向になります。

用紙の縁まで印刷できるプリンタは少ないので、PageFormat ではページのイメージング可能領域が指定されています。これは、ページの中で安全にレンダリングできる部分です。イメージング可能領域が指定されても、座標系は変わりません。イメージング可能領域は、ページの内容をレンダリングするときに、プリンタが印刷できない領域まで広がることがないようにするためのものです。

print に渡されるグラフィックコンテキストにはクリッピング領域の情報が含まれていて、この情報では、イメージング可能領域の中で描画する必要のある部分が記述されています。印刷システムが必要なクリッピング処理を行うため、コンテキストにページ全体を描画しても常に安全です。ただし、クリッピング領域を使ってレンダリングされる範囲を制限することで、ページの中の印刷されない部分までレンダリングすることによるオーバーヘッドを除くことができます。グラフィックスコンテキストからクリッピング領域を取得するには、Graphics.getClip を呼び出します。クリッピング領域を使ってレンダリングのオーバーヘッドを減らすことを、強くお勧めします。

ページがレンダリングされている間でもユーザーがアプリケーションと対話を続けることができるよう、印刷操作をすべて「バックグラウンド」で起動することが望ましい場合があります。そのためには、独立したスレッドで PrinterJob.print を呼び出します。

copyAreasetXOR、合成などのように、前のイメージの内容についての情報が必要なグラフィックス操作は、できるかぎり避ける必要があります。このような操作を行うと、レンダリングが遅くなり、結果の整合性が保たれない場合があります。

7.2.3 Printable ジョブと Pageable ジョブ

Printable ジョブは、印刷を行うもっとも簡単な方法です。使うページペインタは 1 つだけで、アプリケーションは Printable インタフェースを実装する単一のクラスを提供します。印刷を行うときは、印刷システムがページペインタの print メソッドを呼び出して、各ページをレンダリングします。ページのインデックスは 0 から始まり、ページは順番どおりに要求されます。ただし、次のページに進む前に、各ページのレンダリング要求が何回もページペインタに対して行われる場合があります。最後のページが印刷されると、ページペインタの print メソッドは NO_SUCH_PAGE を返します。

Printable ジョブの場合:

  • すべてのページは、同じページペインタと PageFormat を使います。印刷ダイアログを表示する場合、印刷システムはページ数の情報を利用できないため、ドキュメントのページ数は表示されません。
  • 印刷システムは、常に、インデックスの順番に各ページを印刷するようにページペインタに要求します。ページのインデックスは 0 から始まります。ページが飛ぶことはありません。たとえば、ユーザーがドキュメントの 2 ページ目と 3 ページ目の印刷を要求した場合、ページペインタの呼び出しで指定されるインデックスは 0、1、および 2 になります。印刷システムは、次のページの印刷に移る前に、同じページのレンダリングを複数回要求する場合があります。
  • ドキュメントの末尾に達すると、ページペインタはそれを印刷システムに通知します。
  • すべてのページペインタは、同じスレッドで呼び出されます。
  • 印刷システムによっては、目的の出力結果が得られないことがあります。たとえば、プリンタから出力されるページスタックが正しい順番になっていなかったり、部数が複数の場合にページの丁合いが正しくなかったりする場合があります。

Pageable ジョブは、Printable ジョブより柔軟性があります。Printable ジョブのページとは異なり、Pageable ジョブのページはレイアウトと実装が違っていてもかまいません。Pageable ジョブを管理するには、Book クラスを使うか、または独自に Pageable クラスを実装します。Pageable を使うと、印刷システムは、印刷するページ数、各ページで使うページペインタ、および各ページで使う PageFormat を特定できます。決まった構造と書式を持つドキュメントを印刷する必要があるアプリケーションは、Pageable ジョブを使う必要があります。

Pageable ジョブの場合:

  • ページごとに異なるページペインタと PageFormats を使うことができます。
  • 印刷システムは、ページペインタに任意の順番でページの印刷を要求でき、途中のページが省かれる場合があります。たとえば、ユーザーがドキュメントの 2 ページ目と 3 ページ目の印刷を要求した場合、ページペインタの呼び出しで指定されるインデックスは 1 と 2 だけで、ページインデックス 0 は省略されます。
  • Pageable ジョブでは、ドキュメントのページ数をあらかじめ把握しておく必要はありません。ただし、Printable ジョブとは異なり、どのような順序でもページをレンダリングできなければなりません。順序指定は飛んでいる場合があり、印刷システムは、次のページの印刷に移る前に、同じページのレンダリングを複数回要求することがあります。たとえば、ドキュメントの 2 ページ目と 3 ページ目の印刷を要求する場合、呼び出しで要求されるページのインデックスが 2、2、1、1、1 という順序になることもあります。

7.2.4 PrinterJob の一般的なライフサイクル

アプリケーションは、印刷ジョブが完了するまでの一連の手順に沿って、PrinterJob オブジェクトを制御します。次に示すのは、アプリケーションで使用されるもっとも簡単な手順です。

  • PrinterJob.getPrinterJob を呼び出して、新しい PrinterJob オブジェクトを取得します。
  • 印刷で使う PageFormat を決めます。デフォルトの PageFormat を取得するには、defaultPage を呼び出します。ユーザーが書式を指定できるようにダイアログボックスを表示するには、pageDialog を呼び出します。
  • PrinterJob に印刷されるジョブの特性を指定します。Printable ジョブの場合は、setPrintable を呼び出します。Pageable ジョブの場合は、setPageable を呼び出します。setPageable に渡すには Book オブジェクトが最善です。
  • 印刷ジョブのそのほかのプロパティーを指定します。印刷する部数やバナーページに印刷するジョブの名前などです。
  • printDialog を呼び出し、ダイアログボックスをユーザーに提示します。これはオプションです。このダイアログの内容と表示形式は、プラットフォームやプリンタの種類により異なります。大部分のプラットフォームでは、ユーザーは、このダイアログボックスでプリンタの選択を変更できます。ユーザーが印刷ジョブをキャンセルすると、printDialog メソッドから FALSE が返されます。
  • Printerjob.print を呼び出して、ジョブを印刷します。このメソッドでは、適切なページペインタの print が呼び出されます。

次の場合、印刷の途中でジョブが中断することがあります。

  • PrinterException のスロー - print メソッドがこの例外をキャッチすると、ジョブは停止します。ページペインタは、致命的なエラーを検出すると、PrinterException をスローします。
  • PrinterJob.cancel の呼び出し - 印刷処理のループが終了され、ジョブがキャンセルされます。ダイアログボックスを表示し、ボックスのボタンをクリックすることでユーザーが印刷をキャンセルできるようにするには、独立したスレッドでダイアログボックスを表示し、cancel メソッドを呼び出します。

印刷ジョブが停止する前に生成されたページは、印刷される場合とされない場合があります。

一般に、print メソッドから戻った時点では、印刷ジョブは完了していません。プリンタドライバ、プリンタサーバー、またはプリンタ自体での処理がまだ行われているのが普通です。PrinterJob オブジェクトの状態は、印刷されている実際のジョブの状態を反映しない場合があります。

PrinterJob の状態はライフサイクル中に変化するため、特定のメソッドを特定のタイミングで呼び出すと不正になります。たとえば、print を呼び出したあとで setPageable を呼び出しても無意味です。不正な呼び出しを検出すると、PrinterJobjava.lang.IllegalStateException をスローします。

7.2.5 ダイアログ

Java 印刷 API では、ユーザーインタフェース用のダイアログをアプリケーションが明示的に呼び出すことが要求されます。このようなダイアログは、プラットフォーム (Windows など) または Java™ 2 SDK の実装で提供される場合があります。対話型アプリケーションの場合、このようなダイアログを使うのが一般的です。ただし、バッチ用印刷アプリケーションの場合は、ダイアログは必要ありません。たとえば、夜間にデータベースのレポートを自動的に生成して印刷する場合などは、ダイアログの表示は不要です。ユーザーの介入を必要としない印刷ジョブのことを、サイレント印刷ジョブと呼ぶ場合があります。

7.2.5.1 ページ設定ダイアログ

PageFormat に含まれるページ設定情報をユーザーが変更できるようにするには、ページ設定ダイアログを表示します。ページ設定ダイアログを表示するには、PrinterJob.pageDialog を呼び出します。ページ設定ダイアログは、pageDialog に渡すパラメータで初期化されます。ユーザーがダイアログの「OK」ボタンをクリックすると、PageFormat のインスタンスが複製されて、ユーザーの選択に従って変更されたあと、メソッドから返されます。ユーザーがダイアログでキャンセルを選択した場合は、変更されていない元の PageFormatpageDialog から返されます。

7.2.5.2 印刷ダイアログ

通常、メニューの印刷項目または印刷ボタンが起動されると、アプリケーションはユーザーに対して印刷ダイアログを表示します。印刷ダイアログを表示するには、PrinterJob の printDialog メソッドを呼び出します。PrinterJob に提供されている Printable または Pageable のページ数とページ書式に基づいて、ダイアログでのユーザーの選択が制限されます。印刷ダイアログでユーザーが「OK」をクリックすると、printDialog からは TRUE が返されます。ユーザーが印刷ダイアログでキャンセルを選択すると、メソッドからは FALSE が返され、印刷ジョブが破棄されたとみなされます。

7.3 Printable での印刷

基本的な印刷処理は、次の手順で行います。

  • Printable インタフェースを実装し、印刷する各ページをレンダリングできるページペインタを提供する。
  • PrinterJob を作成する。
  • setPrintable を呼び出し、ドキュメントの印刷方法を PrinterJob に伝える。
  • PrinterJob オブジェクトの print を呼び出して、ジョブを開始する。

次の例では、Printable ジョブを使って 5 ページを印刷し、各ページに緑色でページ番号を付けます。ジョブの制御は main メソッドで行い、このメソッドで PrinterJob を取得して制御します。レンダリングは、ページペインタの print メソッドで行われます。

import java.awt.*; import java.awt.print.*; 
public class SimplePrint implements Printable  
{    
  private static Font fnt = new Font("Helvetica",Font.PLAIN,24); 
   
  public static void main(String[] args)  
  {      
    // Get a PrinterJob      
    PrinterJob job = PrinterJob.getPrinterJob();      
    // Specify the Printable is an instance of SimplePrint 
    job.setPrintable(new SimplePrint());      
    // Put up the dialog box      
    if (job.printDialog())  
    {    
      // Print the job if the user didn't cancel printing  
      try { job.print(); } 
      catch (Exception e) 
        { /* handle exception */ } 
    }      
    System.exit(0);    
  } 
 
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  {      
    // pageIndex 0 to 4 corresponds to page numbers 1 to 5. 
    if (pageIndex >= 5) return Printable.NO_SUCH_PAGE;    
    g.setFont(fnt);      
    g.setColor(Color.green);      
    g.drawString("Page " + (pageIndex+1), 100, 100);      
    return Printable.PAGE_EXISTS;    
  }  
} 

7.3.1 Graphics2D を使ったレンダリング

ページペインタの print メソッドの中で Graphics2D の機能を実行するには、最初に Graphics コンテキストを Graphics2D にキャストします。

次の例では、ページ番号を赤と緑のグラデーションでレンダリングします。そのために、GradientPaintGraphics2D コンテキストで設定されています。

import java.awt.*; import java.awt.print.*; 
public class SimplePrint2D implements Printable  
{    
  private static Font fnt = new Font("Helvetica",Font.PLAIN,24); 
   
  private Paint pnt = new GradientPaint(100f, 100f, Color.red,                                            136f, 100f, Color.green, true); 
   
  public static void main(String[] args)  
  {      
    // Get a PrinterJob      
    PrinterJob job = PrinterJob.getPrinterJob();      
    // Specify the Printable is an instance of SimplePrint2D 
    job.setPrintable(new SimplePrint2D());      
    // Put up the dialog box      
    if (job.printDialog())  
    {    
      // Print the job if the user didn't cancel printing  
      try { job.print(); }           
      catch (Exception e) { /* handle exception */ }      
    }      
  System.exit(0);    
  } 
 
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  {      
    // pageIndex 0 to 4 corresponds to page numbers 1 to 5. 
    if (pageIndex >= 5) return Printable.NO_SUCH_PAGE; 
    Graphics2D g2 = (Graphics2D) g; 
    // Use the font defined above 
    g2.setFont(fnt); 
    // Use the gradient color defined above 
    g2.setPaint(pnt); 
    g2.drawString("Page " + (pageIndex+1), 100f, 100f); 
    return Printable.PAGE_EXISTS;    
  }  
} 

7.3.2 ファイルの印刷

ページペインタの print メソッドが同じページに対して繰り返し呼び出される場合、メソッドはそのたびに同じ出力を生成しなければなりません。

同じページに対して繰り返しレンダリング要求があるたびに、常に同じ出力を生成する方法はいくつもあります。たとえば、テキストファイルの特定のページを印刷システムが要求するたびに、同じ出力が生成されるようにするには、ページペインタで、ページごとのファイルポインタを格納して再使用したり、実際のページデータを格納したりします。

次の例では、テキストファイルの「リスト表示」が印刷されています。ファイルの名前は、main メソッドに引数として渡されています。PrintListingPainter クラスは、レンダリングを要求された新しいページの開始位置で、使われているファイルポインタを格納します。同じページをふたたびレンダリングするときは、ファイルポインタを記憶してある位置にリセットします。

import java.awt.*;  
import java.awt.print.*;  
import java.io.*; 
 
public class PrintListing  
{    
  public static void main(String[] args)  
  {      
    // Get a PrinterJob 
    PrinterJob job = PrinterJob.getPrinterJob(); 
    // Ask user for page format (e.g., portrait/landscape) 
    PageFormat pf = job.pageDialog(job.defaultPage()); 
    // Specify the Printable is an instance of 
    // PrintListingPainter; also provide given PageFormat 
    job.setPrintable(new PrintListingPainter(args[0]), pf); 
    // Print 1 copy    
    job.setCopies(1);      
    // Put up the dialog box      
    if (job.printDialog())  
    { 
      // Print the job if the user didn't cancel printing 
      try { job.print(); } 
      catch (Exception e) { /* handle exception */ }      
    }      
    System.exit(0);    
  }  
} 
 
class PrintListingPainter implements Printable  
{ 
  private RandomAccessFile raf;    
  private String fileName;    
  private Font fnt = new Font("Helvetica", Font.PLAIN, 10); 
  private int rememberedPageIndex = -1;    
  private long rememberedFilePointer = -1;    
  private boolean rememberedEOF = false; 
   
  public PrintListingPainter(String file)  
  {  
    fileName = file;      
    try 
    {  
      // Open file       
      raf = new RandomAccessFile(file, "r");      
    }  
    catch (Exception e) { rememberedEOF = true; }    
  } 
 
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  { 
  try  
  {  
    // For catching IOException      
    if (pageIndex != rememberedPageIndex)  
    {  
      // First time we've visited this page 
      rememberedPageIndex = pageIndex;   
      // If encountered EOF on previous page, done  
      if (rememberedEOF) return Printable.NO_SUCH_PAGE; 
      // Save current position in input file 
      rememberedFilePointer = raf.getFilePointer(); 
    }  
    else raf.seek(rememberedFilePointer); 
    g.setColor(Color.black);      
    g.setFont(fnt);  
        int x = (int) pf.getImageableX() + 10; 
        int y = (int) pf.getImageableY() + 12;     
    // Title line      
    g.drawString("File: " + fileName + ", page: " +                                          (pageIndex+1),  x, y); 
    // Generate as many lines as will fit in imageable area 
    y += 36; 
    while (y + 12 < pf.getImageableY()+pf.getImageableHeight()) 
    { 
      String line = raf.readLine(); 
      if (line == null) 
      {  
        rememberedEOF = true; 
        break;  
                } 
        g.drawString(line, x, y);  
        y += 12;      
      } 
      return Printable.PAGE_EXISTS;     
    }  
    catch (Exception e) { return Printable.NO_SUCH_PAGE;} 
  }  
} 

7.4 Pageable と Book での印刷

Pageable ジョブは、ドキュメントの体裁を 1 ページずつ明示的に構成するアプリケーションに適しています。Book クラスは Pageables を手軽に使うための手段ですが、Book が目的に合わない場合は、Pageable の構造を独自に作ることもできます。ここでは、Book の使用方法を説明します。

いくぶん複雑にはなりますが、印刷システムの柔軟性が増すため、Printable ジョブよりも Pageable ジョブの方が実用に適しています。Pageables の大きな利点は、通常はドキュメントのページ数を把握でき、印刷ダイアログボックスでユーザーに対して表示できることです。これによりユーザーは、ジョブが正しく指定されているか確認したり、印刷するページの範囲を選択したりできます。

Book は、ページの集合を表します。Book の中のページは、同じサイズや向き、または同じページペインタを共有する必要はありません。たとえば、1 つの Book で、2 ページは縦方向のレターサイズ、1 ページは横方向のレターサイズであってもかまいません。

Book の最初の作成時には、このオブジェクトは空の状態です。Book にページを追加するには、append メソッドを使います。このメソッドは、ページのサイズ、印刷可能領域、向きを定義する PageFormat オブジェクトと、Printable インタフェースを実装するページペインタを受け取ります。

Book の複数のページで、同じページ書式とページペインタを共有できます。append メソッドの 3 番目のパラメータでページ数を指定すると、append はオーバーロードされて、同じ属性の一連のページを追加できるようになります。

Book の総ページ数がわからない場合は、append メソッドに UNKNOWN_NUMBER_OF_PAGES を渡すことができます。このようにすると、印刷システムは、NO_SUCH_PAGE が返されるまで、ページのインデックスを増やしながらページペインタを呼び出します。

setPage メソッドを使うと、ページのページ書式またはページペインタを変更できます。変更するページの識別には、Book でのそのページの位置を示すページインデックスを使います。

印刷ジョブを準備するには、setPageable を呼び出して Book を渡します。setPageable メソッドと setPrintable メソッドは、一緒には使用できません。つまり、PrinterJob を準備するときは、どちらか一方だけを呼び出すようにします。

7.4.1 Pageable ジョブの使用方法

次の例では、Book を使って、最初の簡単な印刷例と同じものを生成しています。この例はごく単純なものなので、Printable ジョブの代わりに Pageable ジョブを使うことにそれほど利点はありませんが、Book の基本的な使用法を示しています。この場合も、Printable インタフェースを実装し、ページペインタの print メソッドでページをレンダリングする必要があることに注意してください。

import java.awt.*;  
import java.awt.print.*; 
 
public class SimplePrintBook implements Printable  
{    
  private static Font fnt = new Font("Helvetica",Font.PLAIN,24); 
  public static void main(String[] args)  
  {      
    // Get a PrinterJob      
    PrinterJob job = PrinterJob.getPrinterJob();      
    // Set up a book      
    Book bk = new Book();      
    bk.append(new SimplePrintBook(), job.defaultPage(), 5);      
    // Pass the book to the PrinterJob      
    job.setPageable(bk);      
    // Put up the dialog box      
    if (job.printDialog())  
    { 
      // Print the job if the user didn't cancel printing  
      try { job.print(); }           
      catch (Exception e) { /* handle exception */ }      
    }      
    System.exit(0);    
  } 
 
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  {      
    g.setFont(fnt);      
    g.setColor(Color.green);      
    g.drawString("Page " + (pageIndex+1), 100, 100);      
    return Printable.PAGE_EXISTS;    
  } 
} 

7.4.2 複数のページペインタの使用方法

次の例では、表紙と本文に対して、2 つの異なるページペインタが使われています。表紙は横置きモードで印刷し、本文は縦置きモードで印刷しています。

import java.awt.*;  
import java.awt.print.*; 
 
public class PrintBook  
{ 
  public static void main(String[] args)  
  {      
    // Get a PrinterJob      
    PrinterJob job = PrinterJob.getPrinterJob();      
    // Create a landscape page format     
    PageFormat pfl = job.defaultPage();   
    pfl.setOrientation(PageFormat.LANDSCAPE);      
    // Set up a book      
    Book bk = new Book();      
    bk.append(new PaintCover(), pfl);      
    bk.append(new PaintContent(), job.defaultPage(), 2);      
    // Pass the book to the PrinterJob      
    job.setPageable(bk);      
    // Put up the dialog box      
    if (job.printDialog())  
    {  
      // Print the job if the user didn't cancel printing 
      try { job.print(); }  
      catch (Exception e) { /* handle exception */ }      
    }      
  System.exit(0);    
  }  
} 
 
class PaintCover implements Printable  
{    
  Font fnt = new Font("Helvetica-Bold", Font.PLAIN, 72); 
  
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  {      
    g.setFont(fnt);      
    g.setColor(Color.black);      
         int yc = (int) (pf.getImageableY() +               pf.getImageableHeight()/2); 
    g.drawString("Widgets, Inc.", 72, yc+36);      
    return Printable.PAGE_EXISTS;    
  }  
} 
class PaintContent implements Printable  
{    
  public int print(Graphics g, PageFormat pf, int pageIndex) 
  throws PrinterException  
  {     
    Graphics2D g2 = (Graphics2D) g;      
    int useRed = 0;      
   int xo = (int) pf.getImageableX(); 
        int yo = (int) pf.getImageableY();  
    // Fill page with circles or squares, alternating red & green 
        for (int x = 0; x+28 < pf.getImageableWidth(); x += 36) 
    for (int y = 0; y+28 < pf.getImageableHeight(); y += 36) 
    {  
      if (useRed == 0) g.setColor(Color.red); 
      else g.setColor(Color.green); 
      useRed = 1 - useRed; 
      if (pageIndex % 2 == 0) g.drawRect(xo+x+4, yo+y+4, 28, 28); 
      else g.drawOval(xo+x+4, yo+y+4, 28, 28); 
    }      
    return   Printable.PAGE_EXISTS;    
  }  
} 

 


目次 | 前へ | 次へ

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.