SHOEISHA iD

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

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

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

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

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

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

文字と線を0.1mm単位で指定場所に印刷するプログラム例

 Javaで普通に印刷すればこの精度は出せます。理論上はもっと細かくできますが、プリンタの解像度や紙送りなどの動作の精度、湿度による紙の伸びなどでこの辺が妥当なところでしょう。

 PrinterJobクラスを使っての印刷で最低限必要なことは2つです。

  • Printableなクラスを作ります。この中に文字列と線の大きさ、太さや印字位置などを記述します。
  • そのインスタンスをPrinterJobにセットして印刷を指示します。

 まずプログラムと実行結果を示してから、この段階で何ができるかを解説します。

SomethingPrintable00.java
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import static java.awt.Font.*;

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.setFont(new Font(SERIF, PLAIN, 12));
        g2.setStroke(new BasicStroke(0.5f));
        float mm2pt = 72/25.4f;
        g2.drawString("枠内に文字を書きます", 32.8f*mm2pt, 35.9f*mm2pt);
        float x = 30.1f*mm2pt;
        float y = 30.2f*mm2pt;
        float w = 50.3f*mm2pt;
        float h = 8.4f*mm2pt;
        Rectangle2D waku = new Rectangle2D.Float(x, y, w, h);
        g2.draw(waku);
        g2.setFont(new Font(SANS_SERIF, PLAIN, 9));
        g2.drawString("9ポイントの文字です", 32.8f*mm2pt, 44.7f*mm2pt);

        g2.setFont(new Font(SERIF, PLAIN, 10));
        g2.drawString("最も細い線二本を0.5mm間隔で描きます。", 30.1f*mm2pt, 50.0f*mm2pt);
        g2.setStroke(new BasicStroke(0f));
        Line2D line = new Line2D.Float();
        y = 52.0f*mm2pt;
        line.setLine(x, y, 50.0f*mm2pt, y);
        g2.draw(line);
        y = 52.5f*mm2pt;
        line.setLine(x, y, 60.0f*mm2pt, y);
        g2.draw(line);
        g2.drawString("太さ2ポイントの線です。", 30.2f*mm2pt, 60.4f*mm2pt);
        g2.setStroke(new BasicStroke(2f));
        y = 62.2f*mm2pt;
        line.setLine(x, y, 70.2f*mm2pt, y);
        g2.draw(line);

        return PAGE_EXISTS;
    }

    public static void main(String[] args) {
        PrinterJob pj = PrinterJob.getPrinterJob();
        Printable pable = new SomethingPrintable00();
        pj.setPrintable(pable);
        if (pj.printDialog()) {
            try { pj.print(); }
            catch (PrinterException e) {
                System.err.println(e);
            }
        }
    }
}


実行結果

 印刷結果をスキャンした画像です。A4縦で印刷されたものの左上の一部だけです。クリックすると大きくなります。

検証はEPSON PX-1700FとCANON PIXUS MP493で行っています。細かなことを言うとWindows 10のドライバではPX-1700FでA3の使用に問題があり、EPSONのドライバを入れる必要があります。LINUXとMP493の組み合わせでは4mm下がって印刷されます。

 うぐいす色(薄い緑)で書かれた部分は説明のため書き加えたところです。印字位置の数字はプログラム内に書かれたものを示しますが実測値ともほぼ一致します。

印刷例:SomethingPrintable00.javaの印字結果
印刷例:SomethingPrintable00.javaの印字結果

 印刷に使われる座標系は用紙の左上が原点でx軸は右を、y軸は下を向いています。長さの単位はポイントです。1インチ=72ポイントです。プログラム中でmmをポイントに換算して使っています。

 デフォルトの余白がいくらかあるはずですが、それにもかかわらず、印字位置は用紙の縁からの距離を指定します。これはちょっと意外でしたが、便利です。

 ちなみに、Java API仕様ドキュメントのPaperの項によればデフォルトの余白は25.4mm(1インチ)です。余白の範囲には印字しません。余白の変更の方法は次回に説明します。今回のプログラム例は余白を避けてレイアウトしています。

 印刷前にダイアログがでます。デフォルトプリンタに印刷されるようになっていますが、他のプリンタに変更できます。

印刷ダイアログ:印刷前に出るダイアログ(Linux)
印刷ダイアログ:印刷前に出るダイアログ(Linux)
印刷ダイアログ:印刷前に出るダイアログ(Windows)
印刷ダイアログ:印刷前に出るダイアログ(Windows)

 ダイアログはOSによって多少違います。上に示したのはLinux(Debian 9)とWindows(Windows 10)のものです。Windowsでは、[プロパティ]のボタンが生きていて、プリンタのネイティブな設定ダイアログを開くことができますが、Linuxではできません。

 また、Linuxでは用紙や余白の設定をする「ページ設定」のタブがありますが、Windowsではなく、pageDialog()メソッドで別に出す必要があります。これは引数のないprintDialog()メソッドの場合だけの違いのようで、次回に紹介するPrintRequestAttributeSetのインスタンスを引数に取る場合は同じになります。

 ダイアログは共通になるはずなのですが、OSの事情やプリンタドライバも絡んでいて、Javaからは細かくコントロールできないようです。

 帳票印刷では、印刷ダイアログに到達する前に、用紙の選択や余白のコントロールは済ませなければならないはずです。これをJavaから行う方法は次回以降に取り扱います。

次のページ
(1)Printableなクラス

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

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

もっと読む

この記事の著者

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

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

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

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

この記事をシェア

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

イベント

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

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

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

メールバックナンバー