SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Javaの標準機能だけで実現する帳票印刷

Javaの標準機能だけで実現する帳票印刷の基本

Javaの標準機能だけで実現する帳票印刷 第1回

(1)Printableなクラス

 ここからプログラムの説明になります。まず(1)Printableなクラスを作って、(2)PrinterJobで印刷する手順を説明し、実際の文字や線の描画はその後にします。

 Printableインターフェースを持つクラスの大枠は次のようなものです。

public class SomethingPrintable00 implements Printable {
    @Override
    public int print(Graphics g, PageFormat pf, int pageIndex) {
        if (pageIndex != 0) return NO_SUCH_PAGE;
        Graphics2D g2 = (Graphics2D)g;
          /*.....
          ここに実際の文字や線の描画が入ります
        g2.drawString("印刷する文字列", x位置, y位置); //文字の印字
        g2.drawLine(始点x,始点y,終点x,終点y);        //線の描画
          .....*/

        return PAGE_EXISTS;
    }
}

 Printableはprint()というメソッドを持たねばなりません。引数もこの3つに決まっています。このメソッドは印刷時にシステムによって呼び出されます。自分で呼び出すことはありません。

 pageIndexにページ番号が入って呼び出されます。ページ番号は0から始まります。今回は1ページしか書きませんから、pageIndex==0のときは字を描いたり線を引いたりしたあと、PAGE_EXISTSを返します。0でないときはNO_SUCH_PAGEを返します。

 システムは、NO_SUCH_PAGEが返されるまでpageIndexを増加させながらprint()メソッドを呼び出します。一度NO_SUCH_PAGEが返されるとそれ以上呼び出しません。

 PAGE_EXISTS、NO_SUCH_PAGEは、Printableのフィールドにあるintの定数です。実際の値はPAGE_EXISTS=0、NO_SUCH_PAGE=1ですが値を知っている必要はありません。

 Graphicsは、描画対象や描画色やフォントなど、描画操作に必要な状態情報をまとめたクラスです。 このインスタンスが引数でgという名前で与えられるので、これに対して、色やフォントの設定を変更したり、文字を描いたり、線を引いたりするメソッドを使って描画していきます。

 歴史的な事情で、Graphics2D g2 = (Graphics2D)g;を最初に書きます。引数には、Graphicsと書いてありますが、実際には拡張されたGraphics2Dのインスタンスが渡されてくるので、Graphics2DにキャストしておくことでGraphicsクラスのメソッドと、拡張されたGraphics2Dのメソッドの両方を使うことができます。

 PageFormatには印刷されるページのサイズと印刷方向がまとめられています。

 帳票印刷では、決められた大きさの用紙に印刷するよう設計しますから、印刷時に印字領域のサイズを取得して大きさを調整するという使い方はしないでしょう。ここでも使っていません。

(2)PrinterJobで印刷

 mainに書かれたものが、Printableなクラスから印刷物を得る方法です。

 mainの中にある必要はありません。帳票印刷などではデータを読み込んだり、計算したりのプログラムの中から、呼び出すことになろうかと思いますが、いまは複雑な準備がいらないのでmainの中に入れてしまったということです。

 ここに示した方法は、用紙や余白の指定を省いて、最低限の指示だけにしました。コンピュータに設定されたデフォルトのプリンタのデフォルトな用紙に印刷されます。

PrinterJob pj = PrinterJob.getPrinterJob();
Printable pable = new SomethingPrintable00();
pj.setPrintable(pable);
if (pj.printDialog()) {
    try { pj.print(); }
    catch (PrinterException e) {
        System.err.println(e);
    }
}

 手順としては4ステップです。

  1. PrinterJobのインスタンスを作って名前をつける(ここではpj)
    昔の自分を思い出すとこれがなかなか腑に落ちなかった。何もないところから突然作れるなら、作らなくても使えるようにしておけばいいのに……と。形式的にはPrinterJobクラス内のスタティックメソッドでPrinterJobクラスのインスタンスを作るということでPrinterJobクラスが見慣れてくると、理解できないことはない。

  2. Printableなクラスのインスタンスを渡す
    new SomethingPrintable()で、Printableなクラスのインスタンスを作りpableとし、これを引数としてPrinterJobのインスタンス(pj)にsetPrintableメソッドで渡している。

  3. 印刷ダイアログを出す
    pj.printDialog()でダイアログが表示される。ユーザーがキャンセルしなければtrueが返る。falseが返った場合は印刷しないようにしている。印刷ダイアログは省略できる。その場合はデフォルトのプリンタのデフォルト設定で印刷される。

  4. 印刷の指示を出す
    pj.print()のことだが、もちろんprint()はPrintableなクラスのメソッドではなく、PrinterJobのメソッドである。例外を捉えるためにtry-catchに入れなければならない。

 用紙のサイズ、向き、余白などを指定したいときには、もう少し複雑になります。別に項目を立てて改めて解説します。

 ちなみに、印刷について調べると、java.awt.PrintJobを使う方法が解説されていることがあります。PrinterJobと名前が似ているので最初は混乱しました。ここで使っているのはjava.awt.print.PrinterJobの方です。後にもう一つ紹介するのは、javax.print.DocPrintJobを使う方法です。Docがついている分印象が違いますが、DocPrinterJobではありません。注意が必要です。

長さの単位

 メソッドで使われる長さの単位は、1/72インチ(=1ポイント)です。これを整数で指定するのでは72dpiにしかなりません。これではページプリンタの解像度が600dpiとすると不足します。しかし、Graphics2Dではfloatやdoubleで位置を指定できます。小数で指定すれば、0.1ポイント単位で指定するだけでも720dpiということになります。floatでも十進6桁強の精度がありますから十分です。

 換算は(mmの値)÷25.4×72=(ptの値)なので、72/25.4fの値を用意して掛け算することにします。

float mm2pt = 72/25.4f; 

 Graphics2Dのメソッドにはfloatを使うものとdoubleを使うものがありますが、floatのみというメソッドがありますからfloatに統一しておきます。精度的には十分でしょう。

 ちなみに精度を計算しておきましょう。Javaでfloatの最小値は1.40239846×10-45です。これが分解できる最小値です。単位はポイントなのでmmに換算するには72で割って25.4を掛けます。およそ4.94735×10-46mmです。原子の大きさが10-8mm程度ですから、かなりのオーバースペックということになります。

 Java API仕様ドキュメントのMediaPrintableAreaの項には、「印刷可能領域属性の値が、整数型としてマイクロメートル(µm)単位で内部に格納される」とありますから、実際には内部的な描画の精度もµm単位なのかもしれません。

次のページ
文字の描き方

この記事は参考になりましたか?

Javaの標準機能だけで実現する帳票印刷連載記事一覧

もっと読む

この記事の著者

安達 順一(アダチ ジュンイチ)

私立高校に理科・情報の教員として勤めていました。Linuxサーバー/クライアントの授業システムを作り、移動プロファイルで運用していました。教員用にもLinuxサーバーを用意し成績処理プログラムを書きました。情報の学校設定科目ではウェブページ制作とjavaのプログラミングの初歩の授業を作りました。情報...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11483 2019/05/09 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー