implements Printable したクラスのpaint()メソッドに文字と罫線の描画を行う部分を書き、main()から用紙を指定して印刷しています。説明のために極力単純化しています。
データは将来の拡張のためmain()で用意してコンストラクタで渡すようにしています。
public class Tsuuchi implements Printable { String[] kams; int[] tans, tens; public Tsuuchi(String[] kams, int[] tans, int[] tens){ //受け取ったデータを自分の変数に代入....⇨this.kams... } @Override public int print(Graphics g, PageFormat pf, int pageIndex) { if (pageIndex != 0) return NO_SUCH_PAGE; //描画の本体 (均等割付、罫線....) return PAGE_EXISTS; } public static void main(String[] args) { //データの準備 ....⇨kams,tans,tens //用紙の指定などのAttributeSetの用意 ....⇨reqset //Printableなインスタンスをセット pj.setPrintable(new Tsuuchi(kams,tans,tens)); //printable instance //ダイアログを出して印刷 if (pj.printDialog( reqset )) { try { pj.print( reqset ); } catch (PrinterException e) { System.err.println(e); } } } }
描画部分を独立したメソッドに移動してprint()から呼び出すようにします。extends JPanelを加えて、paintComponent()メソッド内からも描画のメソッドを呼び出すようにします。JPanelを表示すればそれがプレビューになります。詳しい説明はプログラム構成の後に書きます
プレビューのために追加したものは、一切省略していません。これだけでプレビューはできます。
import javax.swing.*; //追加します public class TsuuchiPrev extends JPanel implements Printable { //① String[] kams; int[] tans, tens; public TsuuchiPrev(String[] kams, int[] tans, int[] tens){ //受け取ったデータを自分の変数に代入....⇨this.kams... setBackground(Color.white); setPreferredSize(new Dimension(595,841)); //⑥ } @Override public void paintComponent(Graphics g){ //② super.paintComponent(g); drawPage(g); } @Override public int print(Graphics g, PageFormat pf, int pageIndex) { if (pageIndex != 0) return NO_SUCH_PAGE; drawPage(g); //③ return PAGE_EXISTS; } public void drawPage(Graphics g){ //④ //描画の本体 (均等割付、罫線....) } public static void main(String[] args) { //データの準備 ....⇨kams,tans,tens //用紙の指定などのAttributeSetの用意 ....⇨reqset //Printableなインスタンスをセット TsuuchiPrev prevPrintable = new TsuuchiPrev(kams,tans,tens); //⑤ String[] goOrNot = {"印刷","中止"}; int rev = JOptionPane.showOptionDialog( null, prevPrintable, "印刷プレビュー", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null,goOrNot,goOrNot[0] ); //rev:"印刷":0,"中止":1 if (rev!=0) System.exit(0); pj.setPrintable(prevPrintable); //printable instance //ダイアログを出して印刷 if (pj.printDialog( reqset )) { try { pj.print( reqset ); } catch (PrinterException e) { System.err.println(e); } } } }
クリックすると実物大になります。
とても簡単にプレビューができましたが、不満もあるでしょう
まず解像度です。それぞれの枠の中にデータが入ることさえわかればいいという要求の場合もあるかもしれませんが、自由に拡大したりスクロールしたりと細かな所まで確認したいかも知れません。
レンダリングヒントを入れることで多少改善されますが、もともと72dpiからくる595✕841が解像度となっているからです。
JOptionPane.showOptionDialog()を使っているので、ウィンドウの拡大ができません。ウィンドウを拡大すれば内容も拡大されるかどうかは、作り方によりますが、showOptionDialog()ではどちらにせよ無理です。
また、GUIでないプログラムで突然showOptionDialog()を使うことで、このDialogには親フレームがありません。他のウィンドウに隠れてしまった時に呼び出せなくなることがあります。使用例ならDialogでなくてFrameを使い、そこにJPanelを入れるのが順当ではないかといえばそのとおりですが、通知表作成時の状況から言えばメインのパネルから学期などを選択して、プレビューという流れなので、とりあえずダイアログだったわけです。
Dialogをマウスで拡大できるようにするにはAPIにあるように「JDialog インスタンスで setResizable を呼び出す」ようにします。具体的には、showOptionDialog()をやめてJOptionPaneのインスタンスを作り、さらにcreateDialog()でDialogを作って setResizable します。選択した値はJOptionPaneのインスタンスからgetValue()で取り出します。
TsuuchiPrev prevPrintable = new TsuuchiPrev(kams,tans,tens); //⑤ String[] goOrNot = {"印刷","中止"}; JOptionPane pane = new JOptionPane( prevPrintable, // scrollPane, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null,goOrNot,goOrNot[0] ); //JDialog dialog = pane.createDialog( null, "印刷プレビュー" ); JDialog dialog = pane.createDialog("印刷プレビュー" ); dialog.pack(); dialog.setResizable(true); dialog.setVisible(true); String svalue = (String)pane.getValue(); if (svalue==null || !svalue.equals("印刷")) System.exit(0); pj.setPrintable(prevPrintable); //printable instance
これだけでは枠だけ大きくなりますが、中身が拡大されません。
scale()で描画プログラムをそのままに拡大ができます。このメソッドはGraphic2Dのメソッドなので、Graphic2Dへのキャストを先にする必要があります。それに伴い、print()にも同じキャストを書いてdrawPage()の呼び出しをGraphic2Dのインスタンスを引数に変更します。(いままではdrawPage()内でキャストしていました)
拡大率はgetWidth()でpaintComponent()が呼び出された時点の横幅がわかりますから、これをいままでの595で割り算して算出します。両方intなので整数化されないよう595をdouble扱いにします。
@Override public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; double scale = getWidth()/595d; g2.scale(scale,scale); drawPage(g2); }
TsuuchiPrev prevPrintable = new TsuuchiPrev(kams,tans,tens); //⑤ JScrollPane scrollPane = new JScrollPane(prevPrintable); String[] goOrNot = {"印刷","中止"}; JOptionPane pane = new JOptionPane( scrollPane, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null,goOrNot,goOrNot[0] );
必要になるとスクロールバーが出ますが、ちょっと変です。一番下までスクロールしても全部見えません。
JScrollPaneのViewPortの大きさに合わせてJPanelの大きさ(getWidth()とgetHeight()の値)がそれぞれ変化します。最小がPreferredSizeの値になります。getWidth()だけに合わせて描画の拡大が起こるようにしましたから、横長のViewPortになるとJPanelもそれに合い、下が切れます。スクロールバーが出るのはPreferredSizeの値より小さくなった時ということのようです。
PreferredSizeを変更することが必要です。
変数を整理するとわかりやすくなりました。振動の問題はありますが、表示の遅れはありません。
public class TsuuchiPrev extends JPanel implements Printable { String[] kams; int[] tans, tens; double a4longside = 297d*72/25.4; // 841.88; double a4shortside = 210d*72/25.4; // 595.27; double pwidth = a4shortside; //用紙の横幅。用紙を変更する時はここ double pheight = a4longside; //用紙の縦幅 double wZh = pwidth/pheight; //横÷縦 Dimension prevsize; //previewSize preferredSizeで使用 double scale; //Graphics2D#.scale()に使用 public TsuuchiPrev(String[] kams, int[] tans, int[] tens){ this.kams = kams; this.tans = tans; this.tens = tens; setBackground(Color.white); prevsize = new Dimension(); //(int)pwidth,(int)pheight); prevsize.setSize(pwidth,pheight); //newではintしか認められないがsetはdoubleも許容される setPreferredSize(prevsize); //これは初期値 (new Dimension(595,841)におなじ) }
paintComponent()に来るたびにウィンドウの大きさからJPanelのpreferredSizeを指定し直す。
ウインドウの大きさは、正確に言うとJScrollPaneのJViewPortの大きさ。この窓からJPanelを覗いていると考える。
@Override public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; //thisがJPanel、parentはviewportになる int viewpw = getParent().getWidth(); int viewph = getParent().getHeight(); if((double)viewpw/viewph > wZh){ //用紙より横に長い時は横いっぱいに拡大する prevsize.setSize(viewpw,viewpw/wZh); scale = viewpw/pwidth; }else{ //用紙より縦に長い時は縦いっぱいに拡大する prevsize.setSize(viewph*wZh,viewph); scale = viewph/pheight; } //prevsize.setSize(scale*595,scale*841); setPreferredSize(prevsize); //System.out.println(scale); //test g2.scale(scale,scale); drawPage(g2); }
Viewportの横/縦がA4のそれ(wZh)より大きい時はviewpwに合わせて拡大・縮小する | Viewportの横/縦がA4のそれ(wZh)より小さい時はviewphに合わせて拡大・縮小する |
viewportの幅に合わせるのと高さに合わせるのを比べて大きくなる方にするという解釈のほうがわかりやすいかもしれない。
画像をクリックすると状況が再現されます
スクロールバーを出すとビューポートが小さくなってJPanelのサイズも小さくなるするとスクロールバーが不要になってビューポートが大きくなる。するとJPanelのサイズも大きくできるが、スクロールバーが必要になる... 縦横のスクロールバーの相互の影響でこのような振動が起きていると考えられる。もう少し緻密でないと正確ではないが...
用紙の縦横比(ここでは横÷縦を使う)の値をwZhという変数に入れてあります。今回はA4用紙なので210d/297dということになります。
ScrollPaneの窓部分をViewportと呼びます。この縦横比が用紙の縦横比(wZh)と比べてどうなっているかで条件分けします
大きい時は拡大(縮小でも同じ)して横を一致させます。すると縦には入りきらないので、必ず縦方向のスクロールバーが必要になります。そこで横幅はViewportの横幅からスクロールバーの幅を引いたものになり、縦の高さは横幅を縦横比で割ったものになります。
Viewportの縦横比の方が大きい時といっても、それほどでもない時には、スクロールバーの幅を引いた幅に合わせると縦が入りきってしまう場合も考えられます。この場合はスクロールバーが必要なくなりますから計算が狂います。そこで、条件1は十分に大きい場合としましたが、正確には縦スクロールバーの幅を引いても縦横比がwZhより大きい場合ということになります。
右にスクロールバーがある想定でWを合わせる
小さい時は拡大(縮小でも同じ)して縦を一致させます。すると横には入りきらないので、必ず横方向のスクロールバーが必要になります。そこで縦の高さはViewportの縦の高さからスクロールバーの高さを引いたものになり、横幅は縦の高さに縦横比をかけたものになります。
Viewportの縦横比の方が小さい時といっても、それほどでもない時には、スクロールバーの高さを引いた高さに合わせると横が入りきってしまう場合も考えられます。この場合はスクロールバーが必要なくなりますから計算が狂います。そこで、条件2は十分に小さい場合としましたが、正確には横スクロールバーの高さを引いても縦横比がwZhより小さい場合ということになります。
下にスクロールバーがある想定でhを合わせる
結論として、縦横比が大きい場合は縦を、小さい場合は横を合わせるように拡大(または縮小)します。
大きい場合は横を合わせていましたがスクロールバーが現れるとその分小さくなります。縦を合わせると横はスクロールバー程はない隙間が空きますが、全体としては横を合わせるより大きくなります。
縦横比が大きい場合は縦を合わせる
小さい場合は逆に縦を合わせていましたがスクロールバーが現れるとその分小さくなります。横を合わせると縦はスクロールバー程はない隙間が空きますが、全体としては縦を合わせるより大きくなります。
縦横比が小さい場合は横を合わせる
ちなみに、JViewportの報告するサイズはスクロールバーを除いた値です。
振動はなくなりました。
@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){ //条件1 prevsize.setSize(viewpw-vbarw, (viewpw-vbarw)/wZh); scale = (viewpw-vbarw)/pwidth; }else if( wZh > (double)viewpw / (viewph-hbarh) ){ //条件2 prevsize.setSize((viewph-hbarh)*wZh, viewph-hbarh); scale = (viewph-hbarh)/pheight; }else{ //条件3 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); }
説明の通り、条件1から条件3に分けて設定しています。
ただし、JViewportの報告するサイズはスクロールバーを除いた値です。考察ではスクロールバーの置かれるところも加えていましたので、それに合わせてスクロールバーがある場合にはその値を加えています。//注と書かれている部分です。
JScrollPaneにJpanelを継承したTsuuchiPrevクラスのインスタンス内で、getParent()はJViewportのことになります。さらにgetParent()を求めるとJScrollPaneになります。このようにして到達したScrollPaneからスクロールバーの状態や幅を取得しています。
開始の状態。すべて1/2にしてあります。クリックで大きくなります。
RenderingHintsについては説明していないが試せるようになっています。
swingのGUIということで、EDTからの呼び出し(invokeLaterを使う)という注意に従っていますが、この程度のプログラムでは必要性はないと思います。これについては後々書くかもしれません。
このプログラムの実行には次の3つのプログラムも必要です。これらはこれまでのページに全リストが掲載されていますが、今後も機能追加されるかも知れません。
AjustString.java AjustStringT.java Linemm.java
package print01; import java.awt.*; import java.awt.print.*; import java.awt.geom.Line2D; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.HashPrintJobAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.PrintJobAttributeSet; import javax.print.attribute.standard.MediaSize; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.MediaPrintableArea; import javax.print.attribute.standard.MediaTray; import javax.print.attribute.Attribute; import javax.swing.*; import static java.awt.RenderingHints.*; //SwingUtilities.invokeLaterを使う--2-- //paintComponent()の振動抑制(non ImageBuffer第一号 見やすく訂正) --3-- public class TsuuchiPrev extends JPanel implements Printable { public static final double a4longside = 297d*72/25.4; // 841.88; public static final double a4shortside = 210d*72/25.4; // 595.27; public static final double pwidth = a4shortside; public static final double pheight = a4longside; public static final double wZh = pwidth/pheight; String[] kams; int[] tans, tens; Dimension prevsize; double scale; public TsuuchiPrev(String[] kams, int[] tans, int[] tens){ this.kams = kams; this.tans = tans; this.tens = tens; setBackground(Color.white); prevsize = new Dimension(); //(int)pwidth,(int)pheight); prevsize.setSize(pwidth,pheight); setPreferredSize(prevsize); } @Override public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; int viewpw = getParent().getWidth(); int viewph = getParent().getHeight(); //int imgw = getWidth(); //int imgh = 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; } } //prevsize.setSize(scale*595,scale*841); setPreferredSize(prevsize); //System.out.println(scale); //test g2.scale(scale,scale); //g2.setRenderingHint(KEY_ANTIALIASING,VALUE_ANTIALIAS_ON); //g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_ON); 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){ //if (pageIndex != 0) return NO_SUCH_PAGE; //g2.setRenderingHint(KEY_ANTIALIASING,VALUE_ANTIALIAS_ON); //g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_GASP); float hbas = 20.0f; //左端の位置 float hwkm = 27.5f; //科目名の幅 float hwtn = 7f; //単位数の幅 float hptch = 45f/4; //学期などの幅 float vthtop = 41.01f; //ヘッダ行の上の位置 float vtdtop = 64.01f; //行データの上の位置 float vptch = 9.8f; //行データの各行の高さ float hwall = hwkm+hwtn+hptch*4; float mm2pt = 72/25.4f; float pt2mm = 25.4f/72; //Font font10 = new Font("Serif", Font.PLAIN, 10); Font font10 = new Font("IPA P明朝", Font.PLAIN, 10); BasicStroke boldstroke = new BasicStroke(1.0f); BasicStroke medmstroke = new BasicStroke(0.7f); BasicStroke thinstroke = new BasicStroke(0.0f); g2.setStroke(boldstroke); Linemm line = new Linemm(); line.setTB(vthtop, vtdtop+vptch*kams.length); line.setX(hbas); g2.draw(line); line.setX(hbas+hwall); g2.draw(line); line.setLR(hbas, hbas+hwall); line.setY(vthtop); g2.draw(line); line.setY(vtdtop+vptch*kams.length); g2.draw(line); g2.setStroke(medmstroke); line.setY(vtdtop); g2.draw(line); g2.setStroke(thinstroke); line.setLR(hbas, hbas+hwall); for (int k=1; kams.length>k; k++){ //1 not 0 line.setY(vtdtop+vptch*k); g2.draw(line); } line.setTB(vthtop, vtdtop+vptch*kams.length); line.setX(hbas+hwkm); g2.draw(line); for (int i=0; 4>i; i++){ line.setX(hbas+hwkm+hwtn+hptch*i); g2.draw(line); } /* Linemm line2 = new Linemm(); line2.setY(vtdtop+vptch*6 -0.001f); line2.setX(hbas, hbas+hwall-5); g2.draw(line2); */ g2.setFont(font10); float padbtm = (vptch-g2.getFontMetrics().getHeight()*pt2mm)/2; float vm,hm; AjustString kp; kp = new AjustString(g2, "科目", hwkm-10f); kp.drawKintou(hbas+5f,vthtop+(vtdtop-vthtop)/2+g2.getFontMetrics().getHeight()*pt2mm/2); AjustStringT kt; kt = new AjustStringT(g2, "単位数" ,vtdtop-vthtop-4f); kt.drawTtoB(hbas+hwkm+hwtn/2,vthtop+2f); kt = new AjustStringT(g2, "一学期" ,vtdtop-vthtop-4f); kt.drawTtoB(hbas+hwkm+hwtn+hptch/2,vthtop+2f); kt = new AjustStringT(g2, "二学期" ,vtdtop-vthtop-4f); kt.drawTtoB(hbas+hwkm+hwtn+hptch*1.5f,vthtop+2f); kt = new AjustStringT(g2, "三学期" ,vtdtop-vthtop-4f); kt.drawTtoB(hbas+hwkm+hwtn+hptch*2.5f,vthtop+2f); kt = new AjustStringT(g2, "学年" ,vtdtop-vthtop-4f); kt.drawTtoB(hbas+hwkm+hwtn+hptch*3.5f,vthtop+2f); for (int k=0; kams.length>k; k++){ vm = vtdtop+vptch*(k+1)-padbtm; //+1 kp = new AjustString(g2, kams[k] ,hwkm-2f); if(kp.hasNext()){ //長い科目名を2行に kp.drawLeft(hbas+1f,vm+padbtm*3/4-vptch/2); kp = new AjustString(g2, kams[k] ,hwkm-2f, kp.getNextPt()); kp.drawRight(hbas+1f,vm+padbtm/2); /* Fontを小さくする作戦 g2.setFont(new Font("Serif", Font.PLAIN, 6)); kp = new AjustString(g2, kams[k] ,hwkm-2f); kp.drawKintou(hbas+1f,vm); g2.setFont(font10); */ }else{ kp.drawKintou(hbas+1f,vm); } kp = new AjustString(g2, String.valueOf(tans[k]), hwtn);//単位数 kp.drawCenter(hbas+hwkm,vm); kp = new AjustString(g2, String.format("%3d",tens[k]), hptch);//評点1 hm = hbas+hwkm+hwtn; kp.drawCenter(hm,vm); /* if(gakki>=2){ kp = new AjustString(g2, tenStringOf(kamokutens.ten23), hptch);//評点2 kp.drawCenter(hm+hptch,vm); } if(gakki>=3){ kp = new AjustString(g2, tenStringOf(kamokutens.ten33), hptch);//評点3 kp.drawCenter(hm+hptch*2,vm); kp = new AjustString(g2, tenStringOf(kamokutens.ten5), hptch);//評点5 kp.drawCenter(hm+hptch*3,vm); } */ } //return PAGE_EXISTS; } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { String[] kams = { "国語総合","現代社会","数学Ⅰ","数学A","化学基礎", "生物基礎","体育","保健","音楽Ⅰ",//"コミュニケーⅠ", "コミュニケーション英語Ⅰ", "英語表現Ⅰ","家庭基礎","情報の科学" }; int[] tans = { 6,3,4,2,2, 2,2,1,1,2,4, 2,2,2 }; int[] tens = { 55,45,65,45,75, 45,55,55,60,45, 65,65,55 }; 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); float topmm = 8.8f; //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); TsuuchiPrev prevPrintable = new TsuuchiPrev(kams,tans,tens); //printable instance JScrollPane scrollPane = new JScrollPane(prevPrintable); // String[] goOrNot = {"印刷","中止"}; JOptionPane pane = new JOptionPane( scrollPane, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null,goOrNot,goOrNot[0] ); //JDialog dialog = pane.createDialog( null, "印刷プレビュー" ); JDialog dialog = pane.createDialog("印刷プレビュー" ); dialog.pack(); dialog.setResizable(true); dialog.setVisible(true); String svalue = (String)pane.getValue(); dialog.dispose(); //needs for ends /set HIDE_ON_CLOSE by default if (svalue==null || !svalue.equals("印刷")) System.exit(0); pj.setPrintable(prevPrintable); //printable instance if (pj.printDialog( reqset )) { boolean debug = true; if(debug){ Attribute[] attrs = reqset.toArray(); //test for(int n=0 ; attrs.length > n ; n++){ //test System.out.println( attrs[n].getName()+":"+ attrs[n].toString()+";; "); } } try { pj.print( reqset ); } catch (PrinterException e) { System.err.println(e); } } } }
突然mainにSwingUtilities.invokeLaterを使いましたが、これについてはswingのスレッドポリシーをご覧ください。
最後のプログラム末尾近くにdialog.dispose();を追加しました(2017-04-28)。印刷後に System.exit(0);を加えるのでもOKですが、showOptionDialog()と異なり、カスタマイズされたJDialogを使うと正常なオプション選択でもクローズボタンでもHIDE_ON_CLOSEなので、プログラムが終了しなくなります。dialog.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );を加えるのでは、正常なオプション選択をした時に終わらなくなります。詳しくは、 JDialogはHIDE_ON_CLOSEで残るに書きます。