用紙の向きと余白の関係を確認するプログラム
前項で説明したことを確認するプログラムです。引数で向きを変えることができます。引数がなければ、PORTRAITです。0:LANDSCAPE、1:PORTRAIT、2:REVERSE_LANDSCAPE、3:REVERSE_PORTRAITです。
print()メソッドの中で、引数として与えられるPageFormatクラスのインスタンスから余白などの情報を得て書き出しています。実行しているOSや使用したプリンタ、年月日なども書かせていますが、テストのための工夫であって、実際の帳票印刷では使うことはないでしょう。
このプログラムでは印字位置をわざわざ余白の値を使って合わせていますが、用紙の辺からの長さで指定すれば余白からは影響を受けません。
import java.awt.*;
import java.awt.geom.*;
import java.awt.print.*;
import static java.awt.Font.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.time.*;
import java.time.format.*;
/** OriTest.java
Orientation と 余白の関係の調査
2019-05-21 adachi
*/
public class OriTest implements Printable {
String PRINTER = "unknown"; //printername
@Override
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex != 0) return NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D)g;
Font fs12 = new Font(SANS_SERIF, PLAIN, 12);
g2.setFont(fs12);
g2.setStroke(new BasicStroke(0.0f));
float mm2pt = 72/25.4f;
double ix = pf.getImageableX();
double iy = pf.getImageableY();
double iw = pf.getImageableWidth();
double ih = pf.getImageableHeight();
Rectangle2D.Double rectg = new Rectangle2D.Double(ix, iy, iw, ih);
g2.draw(rectg);
g2.setPaint(Color.RED);
rectg = new Rectangle2D.Double(ix+1, iy+1, iw-2, ih-2);
g2.draw(rectg);
g2.setPaint(Color.BLACK);
float yptch = 6.0f*mm2pt;
float xp = (float)ix + 2f*mm2pt;
float yp = (float)iy + yptch;
int ct = 1;
g2.drawString(System.getProperty("os.name"), xp, yp); //osname
g2.drawString(PRINTER, xp, yp+yptch*ct++); //printer name
double pt2mm = 25.4/72;
String sfmt = "%s:%5.1f %s:%5.1f";
double pwmm = pf.getWidth()*pt2mm;
double phmm = pf.getHeight()*pt2mm;
double ixmm = ix*pt2mm;
double iymm = iy*pt2mm;
double iwmm = iw*pt2mm;
double ihmm = ih*pt2mm;
String whx = String.format(sfmt,"W",pwmm,"H",phmm);
g2.drawString(whx, xp, yp+yptch*ct++);
whx = String.format(sfmt,"L",ixmm,"R",pwmm-ixmm-iwmm);
g2.drawString(whx, xp, yp+yptch*ct++);
whx = String.format(sfmt,"T",iymm,"B",phmm-iymm-ihmm);
g2.drawString(whx, xp, yp+yptch*ct++);
int ori = pf.getOrientation();
g2.drawString("0:LAND 1:PORT 2:RevL =[ "+ori+" ]", xp, yp+yptch*ct++);
String muki = "Unknown";
if (ori==PageFormat.LANDSCAPE) muki = "LANDSCAPE";
if (ori==PageFormat.PORTRAIT) muki = "PORTRAIT";
if (ori==PageFormat.REVERSE_LANDSCAPE) muki = "REVERSE_LANDSCAPE";
g2.drawString(muki , xp, yp+yptch*ct++);
LocalDateTime d = LocalDateTime.now();
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
g2.drawString(d.format(f), xp, yp+yptch*ct++);
return PAGE_EXISTS;
}
public static void main(String[] args) {
PrintRequestAttributeSet rqset = new HashPrintRequestAttributeSet();
MediaSizeName msname = MediaSizeName.JAPANESE_POSTCARD;
rqset.add(msname);
MediaSize msize = MediaSize.getMediaSizeForName(msname);
float mwidth = msize.getX(MediaPrintableArea.MM);
float mheight = msize.getY(MediaPrintableArea.MM);
float L = 10.1f;
float R = 20.2f;
float T = 10.3f;
float B = 20.4f;
rqset.add(new MediaPrintableArea(
L, T, (mwidth - L - R), (mheight - T - B),
MediaPrintableArea.MM));
if(args.length==0){
rqset.add(OrientationRequested.PORTRAIT);
System.out.println("0:LAND. 1:PORT. 2:RevL. 3:RevP. none:PORT.");
}else if(args[0].equals("0")){
rqset.add(OrientationRequested.LANDSCAPE);
}else if(args[0].equals("1")){
rqset.add(OrientationRequested.PORTRAIT);
}else if(args[0].equals("2")){
rqset.add(OrientationRequested.REVERSE_LANDSCAPE);
}else if(args[0].equals("3")){
rqset.add(OrientationRequested.REVERSE_PORTRAIT);
}
OriTest pable = new OriTest();
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(pable);
if (pj.printDialog(rqset)) {
pable.PRINTER=pj.getPrintService().toString(); //printername
try {
pj.print(rqset);
}
catch (PrinterException e) {
System.err.println(e);
}
}
}
}
PrinterJobで用紙サイズや余白を指定する印刷の実例
より正確にはプリンタ選択をせずに、PrinterJobを使って用紙サイズや向き、余白を指定して印刷する段階の総まとめ的な実例です。あまり使いそうもないCopiesの代わりにOrientationRequestedを入れました。
メインはmainの部分ですが、描画内容も「SomethingPrintable00.java」とは変えて、余白や向きの指定と印刷位置の指定が独立していることと、余白が画像をクリップする様子を確認できるようにしました。
また、色の指定と一点鎖線の例も入れました。
import java.awt.*;
import java.awt.geom.*;
import java.awt.print.*;
import static java.awt.Font.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.time.*;
import java.time.format.*;
/** SomethingPrintable01.java
PrintRequestAttributeSet と PrinterJobを使い
Service を使わない帳票印刷の典型例
プログラム中のコメント行の変更だけで
A3,A4,葉書のどれかと縦置き、横置きの組み合わせで印刷できます
2019-05-26 adachi
*/
public class SomethingPrintable01 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));
float mm2pt = 72/25.4f;
float x0 = 0.0f*mm2pt;
float y0 = 10.5f*mm2pt;
float p = 1.0f*mm2pt;
float h3 = 3.0f*mm2pt;
float h5 = 5.0f*mm2pt;
float h7 = 7.0f*mm2pt;
float h10 = 10.0f*mm2pt;
g2.setStroke(new BasicStroke(0f));
Line2D line = new Line2D.Float();
line.setLine(x0, y0, x0+50.0f*mm2pt, y0);
g2.draw(line);
float x,ye;
for(int i=0;50>=i;i++){
x = x0 + p*i;
ye = (i%5==0) ?h5:h3;
ye = (i%10==0)?h7:ye;
line.setLine(x, y0, x, y0+ye);
g2.draw(line);
}
g2.setFont(new Font(SANS_SERIF, PLAIN, 9));
g2.drawString("PrintableAreaの外側は印字されないことの確認", p*12, y0+h10);
x0 = 20.5f*mm2pt;
y0 = 30.5f*mm2pt;
g2.setColor(Color.RED);
line.setLine(x0, y0, x0+h5, y0);
g2.draw(line);
g2.setColor(new Color(0xff6600));
line.setLine(x0, y0, x0, y0+h5);
g2.draw(line);
g2.setColor(Color.GREEN);
line.setLine(x0, y0, x0-h5, y0);
g2.draw(line);
g2.setColor(Color.BLUE);
line.setLine(x0, y0, x0, y0-h5);
g2.draw(line);
String sfmt = "交点の座標は X:%5.1f Y:%5.1f";
String whx = String.format(sfmt,x0/mm2pt,y0/mm2pt);
g2.drawString(whx, x0+h7, y0);
g2.setColor(Color.BLACK);
x0 = 15.2f*mm2pt;
y0 = 40.5f*mm2pt;
g2.drawString("一点鎖線を描いておきます", x0, y0);
float[] dash = {12.0f, 2.0f, 1.0f, 2.0f};
BasicStroke hasen = new BasicStroke(
0.5f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10f, dash, 0f);
g2.setStroke(hasen);
line.setLine(x0, y0+h3, x0+40*mm2pt, y0+h3);
g2.draw(line);
y0 = 50.5f*mm2pt;
g2.drawString(System.getProperty("os.name"), x0, y0);
LocalDateTime d = LocalDateTime.now();
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
g2.drawString(d.format(f), x0, y0+h5);
return PAGE_EXISTS;
}
public static void main(String[] args) {
Printable pable = new SomethingPrintable01();
PrintRequestAttributeSet rqset = new HashPrintRequestAttributeSet();
//MediaSizeName msname = MediaSizeName.ISO_A3; //A3用紙
//MediaSizeName msname = MediaSizeName.ISO_A4; //A4用紙
MediaSizeName msname = MediaSizeName.JAPANESE_POSTCARD; //葉書
rqset.add(msname);
MediaSize msize = MediaSize.getMediaSizeForName(msname);
float mwidth = msize.getX(MediaPrintableArea.MM);
float mheight = msize.getY(MediaPrintableArea.MM);
float L = 10.1f;
float R = 10.2f;
float T = 10.3f;
float B = 10.4f;
rqset.add(new MediaPrintableArea(
L, T, (mwidth - L - R), (mheight - T - B),
MediaPrintableArea.MM));
rqset.add(OrientationRequested.LANDSCAPE);
//rqset.add(OrientationRequested.REVERSE_LANDSCAPE);
//rqset.add(OrientationRequested.PORTRAIT);//縦の場合
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(pable);
if (pj.printDialog(rqset)) {
try { pj.print(rqset); }
catch (PrinterException e) {
System.err.println(e);
}
}
}
}
余白は小さめに固定するということにしました。なんなら、L,R,T,B別々の指定ををやめ、共通のMにして、
float M = 10.0f;
rqset.add(new MediaPrintableArea(
M, M, (mwidth - 2*M), (mheight - 2*M),
MediaPrintableArea.MM));
とするのもいいかもしれません。
