Javaで印刷プレビューを表示する


Posted on 2022/1/29 at 1:20


Javaで印刷データを作成するにはPrintableインターフェースを実装したクラスを作成し、print()メソッドをオーバーライドしその中で描画処理を書きます。

印刷ミスを防ぐ為にも、プレビューで確認したいと思ったのですが、標準機能には無く自分で作る必要があるようなので、作成してみました。

せっかく作ったのでライブラリ「jprintpreview.jar」として公開することにしました。

ライセンス

オープンソースとしては緩めのMITライセンスです。簡単に説明すると

「改変、再配布、商用利用など自由に無料で使うことができますが、本ソフトウェアによって発生した損害については保障いたしません。 使用する場合はこのソフトウェアの著作権表示とライセンスの全文またはライセンスの全文が 掲載されているWEBページのURLを、ソースコードもしくは同梱の別ファイルに記述してくださいね」というライセンスです。

具体的には以下の記述です。

		
Copyright (c) 2022 Rennana.net
Released under the MIT license
https://licenses.opensource.jp/MIT/MIT.html
		
		

ライブラリ機能

印刷データであるPrintableインターフェースを実装したクラスの描画内容を表示するというシンプルな機能です。

現在のところ以下の機能を実装しています。

  • プリンター名によるPrintServiceの検索
  • PrintRequestAttributeSetによる余白・印刷の向き・用紙サイズの設定
  • プレビューサイズの拡大・縮小
  • 拡大・縮小印刷
  • Pageableを作成すれば、複数ページの表示も可能

サンプルコード

printpreview.jarをクラスパスに追加して、以下のサンプルコードを実行します。

  
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.OrientationRequested;

import net.rennana.jprintpreview.util.LookUtil;
import net.rennana.jprintpreview.viewer.JPrintPreview;
import net.rennana.jprintpreview.viewer.JPrintable;

public class PreviewSample {

	public static void main(String[] args) {
		LookUtil.setLookAndFeels(LookUtil.Windows);
		PreviewSample test = new PreviewSample();
		test.preview();
	}

	public void preview() {
		try {
			PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
			MediaSize mediaSize = MediaSize.ISO.A4;
			attrs.add(mediaSize.getMediaSizeName());
			attrs.add(OrientationRequested.LANDSCAPE);
			float mediaW = mediaSize.getX(MediaSize.MM);
			float mediaH = mediaSize.getY(MediaSize.MM);
			float marginTop = 20f;
			float marginRight = 10f;
			float marginBottom = 20f;
			float marginLeft = 10f;
			MediaPrintableArea area = new MediaPrintableArea(
					marginLeft, marginTop,
					(mediaW-marginLeft-marginRight),
					(mediaH-marginTop-marginBottom),
					MediaPrintableArea.MM);
			attrs.add(area);
			JPrintPreview preview = new JPrintPreview(attrs);
			MyPrintable printable = new MyPrintable();
			preview.setDefaultPrintService();
			preview.setPrintable(printable);
			preview.setSize(1280, 1000);
			preview.preview();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	class MyPrintable extends JPrintable {
		@Override
		public int paint(Graphics2D g2, PageFormat pf, int pageIndex) throws PrinterException {
			if (pageIndex > 0)
				return Printable.NO_SUCH_PAGE;
			g2.setColor(Color.LIGHT_GRAY);
			g2.drawLine(0,
					(int) pf.getImageableHeight()/2,
					(int) pf.getImageableWidth(),
					(int) pf.getImageableHeight()/2);
			g2.drawLine(
					(int) pf.getImageableWidth()/2,
					0,
					(int) pf.getImageableWidth()/2,
					(int) pf.getImageableHeight());
			g2.drawRect(0, 0, 
					(int) pf.getImageableWidth(), 
					(int) pf.getImageableHeight());
			g2.setColor(Color.RED);
			Font font = g2.getFont();
			Font f = new Font(font.getFontName(), Font.PLAIN, 40);
			g2.setFont(f);
			FontMetrics fm = g2.getFontMetrics(f);

			// 中央の描画
			String str = "中央";
			int strW = fm.stringWidth(str);
			int strH = fm.getHeight();
			int x = (int) ((pf.getImageableWidth()/2) - (strW/2));
			int y = (int) ((pf.getImageableHeight()/2) - (strH/2)) + fm.getAscent();
			g2.drawString(str, x, y);
			int padding = 0;
			g2.setStroke(new BasicStroke(2));
			g2.drawRect(
					x - padding,
					y - padding - fm.getAscent(),
					strW + (padding * 2),
					strH + (padding * 2));
			// 左上の描画
			str = "左上";
			strW = fm.stringWidth(str);
			x = 0;
			y = fm.getAscent();
			g2.drawString(str, x, y);
			g2.drawRect(
					x - padding,
					y - padding - fm.getAscent(),
					strW + (padding * 2),
					strH + (padding * 2));
			// 左下の描画
			str = "左下";
			strW = fm.stringWidth(str);
			x = 0;
			y = (int) (pf.getImageableHeight() - fm.getDescent());
			g2.drawString(str, x, y);
			g2.drawRect(
					x - padding,
					y - padding - fm.getAscent(),
					strW + (padding * 2),
					strH + (padding * 2));
			// 右上の描画
			str = "右上";
			strW = fm.stringWidth(str);
			x = (int) (pf.getImageableWidth() - strW);
			y = fm.getAscent();
			g2.drawString(str, x, y);
			g2.drawRect(
					x - padding,
					y - padding - fm.getAscent(),
					strW + (padding * 2),
					strH + (padding * 2));			
			// 右下の描画
			str = "右下";
			strW = fm.stringWidth(str);
			x = (int) (pf.getImageableWidth() - strW);
			y = (int) (pf.getImageableHeight() - fm.getDescent());
			g2.drawString(str, x, y);
			g2.drawRect(
					x - padding,
					y - padding - fm.getAscent(),
					strW + (padding * 2),
					strH + (padding * 2));
						
			return Printable.PAGE_EXISTS;
		}
	}
}
  

プログラムの実行結果

Printableをプレビュークラス(JPrintPreviewクラス)にセットするだけなので、 PDFを扱うことができるPDFBoxライブラリからPDFPrintableを生成し、プレビュークラスへセットすれば印刷前に内容を確認することができます。

関連記事

Javaでプリンター名を指定して印刷する方法【ライブラリなし】

Javaでプリンター名を指定して文字列を印刷する方法についての紹介です。

関連記事

Javaでプリンター名を指定して画像を印刷する【ライブラリなし】

Java標準機能でプリンター名を指定して画像を印刷する方法についての紹介です。

関連記事

Javaで文字列を描画する【Graphics】

Java(Graphics)で文字列を描画する際の描画位置の指定方法と、サンプルコードです。