住所の自動分割印刷のためのプログラムリストです。
ZipJusho.java, AfreJusho.java の2つが掲載されています。
この他に、AjustString.java, Linemm.java が必要です。
葉書に郵便番号と住所を印刷します。
住所は横書きです。
住所のために、AfureJusho.java を使用します。
この他、
郵便番号のために、AjustString.java が必要です。
線を引くために、Linemm.java が必要ですが、実用には郵便番号枠は不要なので、この部分を削除すれば、これは不要です。
実際の葉書によりフィットさせるため解説の時に比べて大きさを少し変更しました。フォントサイズを10ポイントから12ポイントにして、領域の幅を57mmとし、行ピッチを5.2mmと変更しています。
package print01;
import java.awt.*;
import java.awt.print.*;
import java.awt.geom.Line2D;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintJobAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintJobAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.OrientationRequested;
import javax.swing.*;
import static java.awt.Font.*;
import static java.awt.RenderingHints.*;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
/** 横書きで住所を書く。1行に入りきらない時はあふれ改行文字候補で行を分ける。
* AfreJusho.javaを使用 */
public class ZipJusho extends JPanel implements Printable,ChangeListener {
double pcardlongside = 148d*72/25.4; //
double pcardshortside = 100d*72/25.4; // w=283.46457 h=419.52756
double pwidth = pcardshortside; //用紙の横幅。用紙を変更する時はここ
double pheight = pcardlongside; //用紙の縦幅
double wZh = pwidth/pheight; //横÷縦
Dimension prevsize; //previewSize preferredSizeで使用
double scale; //Graphics2D#.scale()に使用
JSpinner vspinner,hspinner;
String jusho1;
public ZipJusho(String jusho,JSpinner hspinner, JSpinner vspinner){
jusho1 = jusho;
this.hspinner = hspinner;
this.vspinner = vspinner;
hspinner.addChangeListener(this);
vspinner.addChangeListener(this);
setBackground(Color.white);
prevsize = new Dimension(); //(int)pwidth,(int)pheight);
prevsize.setSize(pwidth*2,pheight*2); //newではintしか認められないがsetはdoubleも許容される
setPreferredSize(prevsize); //これは初期値 (new Dimension(595,841)におなじ)
}
@Override
public void stateChanged(ChangeEvent e){
repaint();
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int viewpw = getParent().getWidth();
int viewph = getParent().getHeight();
JScrollPane sp = (JScrollPane) getParent().getParent();
int hbarh = sp.getHorizontalScrollBar().getHeight();
int vbarw = sp.getVerticalScrollBar().getWidth();
boolean hbarAri = sp.getHorizontalScrollBar().isVisible();
boolean vbarAri = sp.getVerticalScrollBar().isVisible();
if (vbarAri) viewpw += vbarw;
if (hbarAri) viewph += hbarh;
if((double)(viewpw-vbarw)/viewph > wZh){
prevsize.setSize(viewpw-vbarw, (viewpw-vbarw)/wZh);
scale = (viewpw-vbarw)/pwidth;
}else if( wZh > (double)viewpw / (viewph-hbarh) ){
prevsize.setSize((viewph-hbarh)*wZh, viewph-hbarh);
scale = (viewph-hbarh)/pheight;
}else{
if ( (double)viewpw/viewph > wZh ) {
prevsize.setSize(viewph*wZh, viewph);
scale = viewph/pheight;
}else{
prevsize.setSize(viewpw, viewpw/wZh);
scale = viewpw/pwidth;
}
}
setPreferredSize(prevsize);
//System.out.println(scale); //test
g2.scale(scale,scale);
drawPage(g2);
}
@Override
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex != 0) return NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D) g;
drawPage(g2);
return PAGE_EXISTS;
}
public void drawPage(Graphics2D g2){
g2.setRenderingHint(KEY_ANTIALIASING,VALUE_ANTIALIAS_ON);
g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_ON);
double trdx = (double)hspinner.getValue();
double trdy = (double)vspinner.getValue();
float mm2pt = 72/25.4f;
g2.translate(trdx*mm2pt,-trdy*mm2pt);
float hbas1 = 44.0f;
float hbas2 = 66.0f;
float hptch1 = 13.9f/2;
float hptch2 = 20.5f/3;
float hwbox1 = 6.4f;
float hwbox2 = 5.8f;
float vbas = 20.3f;
float vwrec = 8.3f;
String zip = "2345678";
g2.setFont(new Font(SANS_SERIF, PLAIN, 16));
AjustString kp;
BasicStroke finestroke = new BasicStroke(0.4f);
Linemm line = new Linemm(); //drawline with new class
g2.setPaint(Color.black);
float vbk = 1.5f; //vbasそのままだと下線に接するのでもどす値(mm)
//AjustStringを使った文字(blue)
//g2.setPaint(Color.blue);
for(int i=0; 3>i; i++){
kp = new AjustString(g2,zip.substring(i,i+1),hwbox1);
kp.drawCenter(hbas1+hptch1*i,vbas-vbk);
}
for(int i=0; 4>i; i++){
kp = new AjustString(g2,zip.substring(i+3,i+4),hwbox2);
kp.drawCenter(hbas2+hptch2*i,vbas-vbk);
}
//郵便番号枠(red) はじめ
g2.setPaint(Color.red);
g2.setStroke(finestroke);
for(int i=0; 3>i; i++){
line.setLR(hbas1+hptch1*i,hbas1+hwbox1+hptch1*i);
line.setY(vbas-vwrec);
g2.draw(line); //Rectangle TOP
line.setY(vbas);
g2.draw(line); //Rectangle bottom
line.setTB(vbas-vwrec,vbas);
line.setX(hbas1+hptch1*i);
g2.draw(line); //Rectangle left
line.setX(hbas1+hwbox1+hptch1*i);
g2.draw(line); //Rectangle right
}
for(int i=0; 4>i; i++){
line.setLR(hbas2+hptch2*i,hbas2+hwbox2+hptch2*i);
line.setY(vbas-vwrec);
g2.draw(line); //Rectangle TOP
line.setY(vbas);
g2.draw(line); //Rectangle bottom
line.setTB(vbas-vwrec,vbas);
line.setX(hbas2+hptch2*i);
g2.draw(line); //Rectangle left
line.setX(hbas2+hwbox2+hptch2*i);
g2.draw(line); //Rectangle right
}
//郵便番号枠(red) おわり
Font font09 = new Font(Font.SERIF, Font.PLAIN, 9);
Font font10 = new Font(Font.SERIF, Font.PLAIN, 10);
Font font11 = new Font(Font.SERIF, Font.PLAIN, 11);
Font font12 = new Font(Font.SERIF, Font.PLAIN, 12);
AfureJusho af;
float x = 35f;
float ybas = 40f;
float y = ybas;
float horwidth = 48f; //55f;
g2.setPaint(Color.black);
g2.setFont(font10);
af = new AfureJusho(g2, jusho1, horwidth);
af.drawLeft(x,y);
while(af.hasNext()){
af.nextLine();
y += 4.8f;
af.drawRight(x,y);
}
//左右の境界を示す線 はじめ
g2.setPaint(new Color(255,204,204));
g2.setStroke(finestroke);
y = ybas;
line.setLR(x,x+0.2f);
line.setY(y);
g2.draw(line); //(x,y)
line.setTB(y-5f,y+12f);
line.setX(x);
g2.draw(line); //|...
line.setX(x+horwidth);
g2.draw(line); //...|
//左右の境界を示す線 おわり
}
public static void main(String[] args) {
PrinterJob pj = PrinterJob.getPrinterJob();
PrintRequestAttributeSet reqset = new HashPrintRequestAttributeSet();
//MediaSizeName medname = MediaSizeName.ISO_A4;
MediaSizeName medname = MediaSizeName.JAPANESE_POSTCARD;
reqset.add(medname);
MediaSize medsize = MediaSize.getMediaSizeForName(medname);
float medwidth = medsize.getX(MediaPrintableArea.MM);
float medheight = medsize.getY(MediaPrintableArea.MM);
//System.out.println("w="+medwidth + " h="+medheight);//test
//System.out.println("w="+medwidth*72/25.4f + " h="+medheight*72/25.4f);//test
float topmm = 5.5f; //landscape前のTOP
float bottomm = 7.7f;
float leftmm = 6.6f;
float rightmm = 5.5f;
reqset.add(new MediaPrintableArea(
leftmm, topmm,
(medwidth - leftmm - rightmm),
(medheight - topmm - bottomm), MediaPrintableArea.MM));
//reqset.add(OrientationRequested.REVERSE_LANDSCAPE);
//reqset.add(OrientationRequested.LANDSCAPE);
reqset.add(OrientationRequested.PORTRAIT);
SpinnerModel vmodel = new SpinnerNumberModel(0.0d, -10.0d, +10.0d, 0.10d);
SpinnerModel hmodel = new SpinnerNumberModel(0.0d, -10.0d, +10.0d, 0.10d);
JSpinner vspinner = new JSpinner(vmodel);
JSpinner hspinner = new JSpinner(hmodel);
((JSpinner.DefaultEditor)(vspinner.getEditor())).getTextField().setColumns(5);
((JSpinner.DefaultEditor)(hspinner.getEditor())).getTextField().setColumns(5);
//印刷位置の微調整(±10mmまで)
JLabel vlabel = new JLabel("上へ(mm)");
JLabel hlabel = new JLabel(" 右へ(mm)");
JPanel spnnpanel = new JPanel();
spnnpanel.add(vlabel);
spnnpanel.add(vspinner);
spnnpanel.add(hlabel);
spnnpanel.add(hspinner);
String jusho = "青森県弘前市大字桜ヶ丘𠀋四丁目13𠮟番地1 県営𡈽住宅";
jusho = "定められた改行候補がなければAjustStringの様にわけるはずです";
jusho = "青森県弘前市桜ヶ丘𠀋四丁目234𠮟番地567 県営𡈽住宅";
jusho = "青森県弘前市大字赤松原3丁目456番地の78 市営住宅A-1234";
jusho = "青森県上北郡おいらせ町中下田135-1788";
jusho = "青森県上北𡋽郡おいらせ町中𥐮下𡈽田135-𣷓𩸽1788";
ZipJusho zipjusho = new ZipJusho(jusho,hspinner,vspinner);
//System.out.println(zipbidou.getPreferredSize());//test
JScrollPane scrollPane = new JScrollPane(zipjusho);
JPanel previewSpinnerPanel = new JPanel(new BorderLayout()); //p
previewSpinnerPanel.add(scrollPane,BorderLayout.CENTER); //p
previewSpinnerPanel.add(spnnpanel,BorderLayout.SOUTH); //p
String[] goOrNot = {"印刷","中止"};
JOptionPane pane = new JOptionPane(
//b notborderbox,
previewSpinnerPanel, //p
JOptionPane.PLAIN_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null,goOrNot,goOrNot[0]
);
JDialog dialog = pane.createDialog("印刷プレビュー" );
dialog.pack();
dialog.setResizable(true);
dialog.setVisible(true);
String svalue = (String)pane.getValue();
do{
if (svalue!=null && svalue.equals("印刷")) {
pj.setPrintable(zipjusho); //printable instance
if (pj.printDialog( reqset )) {
boolean debug = true;
try { pj.print( reqset ); }
catch (PrinterException e) {
System.err.println(e);
}
}
dialog.setVisible(true);
svalue = (String)pane.getValue();
}
}while(svalue!=null && !svalue.equals("中止"));
System.exit(0);
}
}
指定幅に文字列を書ききれなかった時に、{" "," ","丁目","大字","字","市","番地"}を候補にして行を分割し、行毎に描画する。候補では分割しきれない時は文字ごとに分割します。ZipJusho.javaから呼び出されます。
package print01;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
public class AfureJusho {
String kp, nbf;
int jbgn, nextjbgn;
int kplen;
float fmwm, remm ;
float aidamm;
Graphics2D g;
FontMetrics fm;
float mm2pt = 72/25.4f;
float pt2mm = 25.4f/72;
String[] afure = {" "," ","丁目","大字","字","市","番地"};
public AfureJusho(Graphics2D g, String mojiretsu, float formatWidthMm) {
this.g = g;
kp = mojiretsu;
fmwm = formatWidthMm;
fm = g.getFontMetrics();
kplen = kp.length();
nextjbgn = 0;
//System.out.println("constr:'"+kp+"',"+fmwm); //test
nextLine();
}
public void nextLine(){
jbgn = nextjbgn;
nbf = kp.substring(jbgn,kplen);
remm = fmwm - fm.stringWidth(nbf)*pt2mm;
//System.out.println("nextLine:'"+nbf+"',"+kplen); //test
int afi = 0;
nextjbgn = -1;
while(0>remm && afure.length>afi) {
if (nbf.indexOf(afure[afi])>=0){
if (afure[afi].equals(" ") || afure[afi].equals(" ") ){
nextjbgn = nbf.indexOf(afure[afi])+jbgn;
nbf = kp.substring(jbgn,nextjbgn);
nextjbgn++;
}else{
nextjbgn = nbf.indexOf(afure[afi])+jbgn+afure[afi].length();
nbf = kp.substring(jbgn,nextjbgn);
}
remm = fmwm - fm.stringWidth(nbf)*pt2mm;
}
afi++;
}
int nbflen = nbf.length();
while(0>remm){
nbf = kp.substring(jbgn,jbgn+nbflen);
remm = fmwm - fm.stringWidth(nbf)*pt2mm;
nextjbgn = jbgn + nbflen;
int nbfcplen = nbf.codePointCount(0, nbflen);
nbfcplen--;
nbflen = nbf.offsetByCodePoints(0, nbfcplen);
}
}
public boolean hasNext(){
return nextjbgn>=0;
}
public void drawLeft(float hm, float vm) {
g.drawString(nbf,hm*mm2pt,vm*mm2pt);
}
public void drawRight(float hm, float vm) {
g.drawString(nbf,(hm+remm)*mm2pt,vm*mm2pt);
}
public void drawCenter(float hm, float vm) {
g.drawString(nbf,(hm+remm/2)*mm2pt,vm*mm2pt);
}
public void drawKintou(float hm, float vm) {
float hpp = 0;
int nbflen = nbf.length();
int nbfcplen = nbf.codePointCount(0,nbflen);
if (nbfcplen!=1){
aidamm = remm/(nbfcplen-1);
int i=0;
int nexti = 0;
int cpct = 0;
while (nbflen>i){
nexti = nbf.offsetByCodePoints(i,1);
//System.out.println("'"+nbf.substring(i,nexti)+"',"+hpp); //test
g.drawString(nbf.substring(i,nexti),(hm+aidamm*cpct)*mm2pt+hpp,vm*mm2pt);
hpp = fm.stringWidth(nbf.substring(0,nexti));
i=nexti;
cpct++;
}
}else{
drawCenter( hm, vm);
}
}
}