JOptionPaneにscrollPaneを介してTsuuchiHRのインスタンスを置いています。TsuuchiHRはJPanelを継承しているのでpaintComponent()メソッド内でプレビューを描けば表示されます。今回は複数ページなのでページを切り替える機能が必要になりました。
現在はpaintComponent()メソッド内でページが0に固定されていますが、次へ、前へのボタンによりページの値を増減させてrepaint()で行けそうです。問題はボタンをどこに置くかです。JOptionPaneのオプション、つまり現在"印刷","中止"の2つの選択肢に加えることもできますが、これだと増減するたびにダイアログが一度消えてからページを変えて再び出現することになり、あまり使用感は良くないと予想されます。
次の策はscrollPaneのあるメッセージ部分にJPanelを置き、そこにscrollPaneとボタンを乗せたPanelを配置することです。ボタンが2箇所に分かれるので、見栄えは疑問ですが、何とかなりそうです。
我慢できなければJOptionPaneをやめて新たに独自のJDialogを作ることにします。
「現在ページ/総ページ数」を表示するstatlabelも加えることにした。
setStatLabel()はそのlabelをTsuuchiHRのインスタンスに伝えるためのメソッド。
TsuuchiHR prevPrintable = new TsuuchiHR(namemap,seisekimap,shukketsumap,tanis,gakki); //printable instance
JScrollPane scrollPane = new JScrollPane(prevPrintable);
JPanel sbPanel = new JPanel(); //ここから
sbPanel.setLayout(new BorderLayout());
sbPanel.add(scrollPane,BorderLayout.CENTER);
JPanel btnPanel = new JPanel();
sbPanel.add(btnPanel,BorderLayout.SOUTH);
JButton upbtn = new JButton("次");
JButton dnbtn = new JButton("前");
upbtn.addActionListener(prevPrintable);
dnbtn.addActionListener(prevPrintable);
JLabel statlabel = new JLabel(String.format("%3d/%-3d",1,seisekimap.size()));
prevPrintable.setStatLabel(statlabel);
btnPanel.add(dnbtn);
btnPanel.add(statlabel);
btnPanel.add(upbtn); //ここまで追加
String[] goOrNot = {"印刷","中止"};
JOptionPane pane = new JOptionPane(
sbPanel, //scrollPaneをこれに替える
JOptionPane.PLAIN_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null,goOrNot,goOrNot[0]
);
//JDialog dialog = pane.createDialog( null, "印刷プレビュー" );
JDialog dialog = pane.createDialog("印刷プレビュー" );
setStatLabel()はこれだけ。TsuuchiHR.java内のメソッド
public void setStatLabel(JLabel lbl){
this.statlabel = lbl;
}
TsuuchiHRのクラスにActionListenerをつけて、
public class TsuuchiHR extends JPanel implements Printable, ActionListener {
actionPerformed()を定義。ページの増減とページ数が範囲を超えた時の処理、画面の再描画の指示とJLabelの書き直し。
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("次")){
previewpage++;
if (previewpage>pmax) previewpage=1;
repaint();
statlabel.setText(String.format("%3d/%-3d",previewpage,pmax));
}
else if (command.equals("前")){
previewpage--;
if (0>=previewpage) previewpage = pmax;
repaint();
statlabel.setText(String.format("%3d/%-3d",previewpage,pmax));
}
}
pageIndexに合わせて0からだが、表面上は1からにする
フィールドに追加
int previewpage=1; JLabel statlabel;
paintComponent()からの呼び出し
drawPage(g2,previewpage-1);
プログラム名は、複数プレビューなしと同名です。
package print01のメンバーとして次のクラスも必要です。
AjustString.java 均等割付 AjustStringT.java 罫線を引く Linemm.java 罫線を引く SetHRData.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 java.awt.event.*;
import static java.awt.RenderingHints.*;
import java.util.LinkedHashMap;
import java.util.Set;
//SwingUtilities.invokeLaterを使う--2--
//paintComponent()の振動抑制(non ImageBuffer第一号 見やすく訂正) --3--
//TsuuchiPrev.java=3 +Shukketsu
//2017-5-2 multipage print. preview yet.
//2017-5-3 add preview.
public class TsuuchiHR extends JPanel implements Printable, ActionListener {
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, ks;
Dimension prevsize;
double scale;
int gakki = 0;
int pmax ;
int previewpage=1;
JLabel statlabel;
LinkedHashMap<Integer,String> namemap; //番号=>氏名
LinkedHashMap<Integer,LinkedHashMap<String,int[]>> seisekimap; //番号=>(科目名=>成績配列[学期])
LinkedHashMap<Integer,int[][]> shukketsumap; //番号=>出欠配列[項目][学期]
LinkedHashMap<String,Integer> tanis; //科目名=>単位数
public TsuuchiHR(
LinkedHashMap<Integer,String> namemap,
LinkedHashMap<Integer,LinkedHashMap<String,int[]>> seisekimap,
LinkedHashMap<Integer,int[][]> shukketsumap,
LinkedHashMap<String,Integer> tanis,
int gakki
){
this.namemap = namemap;
this.seisekimap = seisekimap;
this.shukketsumap = shukketsumap;
this.tanis = tanis;
this.gakki = gakki;
pmax = seisekimap.size();
statlabel = new JLabel();
setBackground(Color.white);
prevsize = new Dimension();
prevsize.setSize(pwidth,pheight);
setPreferredSize(prevsize);
}
public void setStatLabel(JLabel lbl){
this.statlabel = lbl;
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("次")){
previewpage++;
if (previewpage>pmax) previewpage=1;
repaint();
statlabel.setText(String.format("%3d/%-3d",previewpage,pmax));
}
else if (command.equals("前")){
previewpage--;
if (0>=previewpage) previewpage = pmax;
repaint();
statlabel.setText(String.format("%3d/%-3d",previewpage,pmax));
}
}
@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,previewpage-1);
}
@Override
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex >= pmax) return NO_SUCH_PAGE; //pageIndex is 0,1,2,...
Graphics2D g2 = (Graphics2D)g;
drawPage(g2,pageIndex);
return PAGE_EXISTS;
}
public void drawPage(Graphics2D g2, int page){
//2 Integer[] narray = namemap.keySet().toArray(new Integer[0]);
//2 int n = narray[page];
Object[] narray = namemap.keySet().toArray();
int n = (int)narray[page];
//x int[] narray = namemap.keySet().toArray(new int[0]);
//x int n = narray[page];
String name = namemap.get(n);
LinkedHashMap<String,int[]> kamokutensmap = seisekimap.get(n);
int kmax = kamokutensmap.size();
int[][] ks = shukketsumap.get(n);
//& use tanis for tani
//g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_GASP);
g2.setRenderingHint(KEY_ANTIALIASING,VALUE_ANTIALIAS_ON);
g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_ON);
//g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_DEFAULT);
float hbas = 22.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 mfont11 = new Font("Serif", Font.PLAIN, 11);
Font font10 = new Font("Serif", Font.PLAIN, 10);
Font font09 = new Font("Serif", Font.PLAIN, 9);
//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*kmax);
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*kmax);
g2.draw(line);
g2.setStroke(medmstroke);
line.setY(vtdtop);
g2.draw(line);
g2.setStroke(thinstroke);
line.setLR(hbas, hbas+hwall);
for (int k=1; kmax>k; k++){ //1 not 0
line.setY(vtdtop+vptch*k);
g2.draw(line);
}
line.setTB(vthtop, vtdtop+vptch*kmax);
line.setX(hbas+hwkm);
g2.draw(line);
for (int i=0; 4>i; i++){
line.setX(hbas+hwkm+hwtn+hptch*i);
g2.draw(line);
}
g2.setFont(font10);
float padbtm = (vptch-g2.getFontMetrics().getHeight()*pt2mm)/2;
float vm,hm;
AjustString kp;
kp = new AjustString(g2, "科目", hwkm-11f);
kp.drawKintou(hbas+5.5f,vthtop+(vtdtop-vthtop)/2+g2.getFontMetrics().getHeight()*pt2mm/2);
AjustStringT kt;
kt = new AjustStringT(g2, "単位数" ,vtdtop-vthtop-6f);
kt.drawTtoB(hbas+hwkm+hwtn/2,vthtop+3f);
kt = new AjustStringT(g2, "一学期" ,vtdtop-vthtop-6f);
kt.drawTtoB(hbas+hwkm+hwtn+hptch/2,vthtop+3f);
kt = new AjustStringT(g2, "二学期" ,vtdtop-vthtop-6f);
kt.drawTtoB(hbas+hwkm+hwtn+hptch*1.5f,vthtop+3f);
kt = new AjustStringT(g2, "三学期" ,vtdtop-vthtop-6f);
kt.drawTtoB(hbas+hwkm+hwtn+hptch*2.5f,vthtop+3f);
kt = new AjustStringT(g2, "学年" ,vtdtop-vthtop-6f);
kt.drawTtoB(hbas+hwkm+hwtn+hptch*3.5f,vthtop+3f);
int kamokuichi = 0;
//for (int k=0; kmax>k; k++){
for (String kamokumei: kamokutensmap.keySet()) {
kamokuichi++;
vm = vtdtop+vptch*kamokuichi-padbtm;
kp = new AjustString(g2, kamokumei ,hwkm-2f);
if(kp.hasNext()){ //長い科目名を2行に
kp.drawLeft(hbas+1f,vm+padbtm*3/4-vptch/2);
kp = new AjustString(g2, kamokumei ,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(tanis.get(kamokumei)), hwtn);//単位数 数値
kp.drawCenter(hbas+hwkm,vm);
g2.setFont(mfont11);
int gk = 0;
kp = new AjustString(g2, String.format("%3d",kamokutensmap.get(kamokumei)[gk]), hptch);//評点1 数値
hm = hbas+hwkm+hwtn;
kp.drawCenter(hm,vm);
if(gakki>=2){
gk = 1;
kp = new AjustString(g2, String.format("%3d",kamokutensmap.get(kamokumei)[gk]), hptch);//評点2 数値
kp.drawCenter(hm+hptch,vm);
}
if(gakki>=3){
gk = 2;
kp = new AjustString(g2, String.format("%3d",kamokutensmap.get(kamokumei)[gk]), hptch);//評点3 数値
kp.drawCenter(hm+hptch*2,vm);
kp = new AjustString(g2, String.format("%3d",kamokutensmap.get(kamokumei)[gk+1]), hptch);//評点5 数値
kp.drawCenter(hm+hptch*3,vm);
}
g2.setFont(font10);
}
//出欠
float hwssk = hwkm+hwtn+7f;
float hwhalf= hwssk+hptch*4;
float hbas2 = hbas+hwall+3.8f;
float vwbik = vptch*8f;
g2.setStroke(boldstroke);
line.setLR(hbas2,hbas2+hwhalf);
line.setY(vthtop);
g2.draw(line); //Rectangle TOP
line.setY(vtdtop);
g2.draw(line); //Rectangle th/td
line.setY(vtdtop+vptch*8);
g2.draw(line); //Rectangle th/td
line.setTB(vthtop,vtdtop+vptch*8);
line.setX(hbas2);
g2.draw(line); //Rectangle left
line.setX(hbas2+hwhalf);
g2.draw(line); //Rectangle right
g2.setStroke(thinstroke);
for(int gk=1;4>=gk;gk++){
line.setX(hbas2+hwhalf-hptch*gk);
g2.draw(line); //tate hwssk|hptch|hptch|...
}
line.setLR(hbas2,hbas2+hwhalf);
for(int i=1;8>i;i++){
line.setY(vtdtop+vptch*i);
g2.draw(line);
}
kp = new AjustString(g2, "項目",hwssk-16.4f);
kp.drawKintou(hbas2+8.2f,vtdtop-(vtdtop-vthtop)/2+g2.getFontMetrics().getHeight()*pt2mm/2f);
kt = new AjustStringT(g2, "一学期",vtdtop-vthtop-6f);
kt.drawTtoB(hbas2+hwssk+hptch/2f,vthtop+3f);
kt = new AjustStringT(g2, "二学期",vtdtop-vthtop-6f);
kt.drawTtoB(hbas2+hwssk+hptch+hptch/2f,vthtop+3f);
kt = new AjustStringT(g2, "三学期",vtdtop-vthtop-6f);
kt.drawTtoB(hbas2+hwssk+hptch*2+hptch/2f,vthtop+3f);
kt = new AjustStringT(g2, "学年",vtdtop-vthtop-6f);
kt.drawTtoB(hbas2+hwssk+hptch*3+hptch/2f,vthtop+3f);
vm = vtdtop-padbtm;
hm = hbas2;
kp = new AjustString(g2,"授業日数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch);
g2.setFont(font09);
kp = new AjustString(g2,"出校停止・忌引等の日数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*2);
g2.setFont(font10);
kp = new AjustString(g2,"出席すべき日数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*3);
kp = new AjustString(g2,"欠席日数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*4);
kp = new AjustString(g2,"出席日数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*5);
kp = new AjustString(g2,"遅刻",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*6);
kp = new AjustString(g2,"早退",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*7);
kp = new AjustString(g2,"欠課時数",hwssk-4f);
kp.drawKintou(hm+2f,vm+vptch*8);
g2.setFont(mfont11);
int[] kssum = new int[6];
for (int gk = 0; gakki>gk; gk++){
hm = hbas2+hwssk+hptch*gk;
int zd = ks[0][gk];
kp = new AjustString(g2,String.valueOf(zd),hptch); //授業日数
kp.drawCenter(hm,vm+vptch);
kp = new AjustString(g2,String.valueOf(ks[1][gk]),hptch); //1:忌引き
kp.drawCenter(hm,vm+vptch*2);
kp = new AjustString(g2,String.valueOf(zd-ks[1][gk]),hptch);
kp.drawCenter(hm,vm+vptch*3);
kp = new AjustString(g2,String.valueOf(ks[2][gk]),hptch); //2:欠席
kp.drawCenter(hm,vm+vptch*4);
kp = new AjustString(g2,String.valueOf(zd-ks[1][gk]-ks[2][gk]),hptch);
kp.drawCenter(hm,vm+vptch*5);
kp = new AjustString(g2,String.valueOf(ks[3][gk]),hptch); //3: 遅刻
kp.drawCenter(hm,vm+vptch*6);
kp = new AjustString(g2,String.valueOf(ks[4][gk]),hptch); //4:早退
kp.drawCenter(hm,vm+vptch*7);
kp = new AjustString(g2,String.valueOf(ks[5][gk]),hptch); //5:欠課時数
kp.drawCenter(hm,vm+vptch*8);
for(int i=0; kssum.length>i; i++) kssum[i]+=ks[i][gk];
}
if(gakki==3){
hm = hbas2+hwssk+hptch*3;
int zd = kssum[0];
kp = new AjustString(g2,String.valueOf(zd),hptch); //授業日数
kp.drawCenter(hm,vm+vptch);
kp = new AjustString(g2,String.valueOf(kssum[1]),hptch); //1:忌引き
kp.drawCenter(hm,vm+vptch*2);
kp = new AjustString(g2,String.valueOf(zd-kssum[1]),hptch);
kp.drawCenter(hm,vm+vptch*3);
kp = new AjustString(g2,String.valueOf(kssum[2]),hptch); //2:欠席
kp.drawCenter(hm,vm+vptch*4);
kp = new AjustString(g2,String.valueOf(zd-kssum[1]-kssum[2]),hptch);
kp.drawCenter(hm,vm+vptch*5);
kp = new AjustString(g2,String.valueOf(kssum[3]),hptch); //3:遅刻
kp.drawCenter(hm,vm+vptch*6);
kp = new AjustString(g2,String.valueOf(kssum[4]),hptch); //4:早退
kp.drawCenter(hm,vm+vptch*7);
kp = new AjustString(g2,String.valueOf(kssum[5]),hptch); //5:欠課時数
kp.drawCenter(hm,vm+vptch*8);
}
g2.setFont(font10);
//return PAGE_EXISTS;
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
int gakki = 1;
SetHRData hrdata = new SetHRData(2017,"1A",gakki); //printable instance
LinkedHashMap<Integer,String> namemap = hrdata.getNameMap();
LinkedHashMap<Integer,LinkedHashMap<String,int[]>>
seisekimap = hrdata.getSeisekiMap();
LinkedHashMap<Integer,int[][]> shukketsumap = hrdata.getShukketsuMap();
LinkedHashMap<String,Integer> tanis = hrdata.getTanis();
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);
TsuuchiHR prevPrintable = new TsuuchiHR(namemap,seisekimap,shukketsumap,tanis,gakki); //printable instance
JScrollPane scrollPane = new JScrollPane(prevPrintable);
JPanel sbPanel = new JPanel();
sbPanel.setLayout(new BorderLayout());
sbPanel.add(scrollPane,BorderLayout.CENTER);
JPanel btnPanel = new JPanel();
sbPanel.add(btnPanel,BorderLayout.SOUTH);
JButton upbtn = new JButton("次");
JButton dnbtn = new JButton("前");
upbtn.addActionListener(prevPrintable);
dnbtn.addActionListener(prevPrintable);
JLabel statlabel = new JLabel(String.format("%3d/%-3d",1,seisekimap.size()));
statlabel.setName("status");
prevPrintable.setStatLabel(statlabel);
btnPanel.add(dnbtn);
btnPanel.add(statlabel);
btnPanel.add(upbtn);
String[] goOrNot = {"印刷","中止"};
JOptionPane pane = new JOptionPane(
sbPanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null,goOrNot,goOrNot[0]
);
//JDialog dialog = pane.createDialog( null, "印刷プレビュー" );
JDialog dialog = pane.createDialog("印刷プレビュー" );
int dh = dialog.getPreferredSize().height;
int dw = dialog.getPreferredSize().width;
int scrh = Toolkit.getDefaultToolkit().getScreenSize().height;
if (dh>scrh) {
dialog.setPreferredSize(new Dimension(dw,scrh-40));
}
dialog.pack();
dialog.setResizable(true);
dialog.setVisible(true);
dialog.dispose(); //needs for ends /set HIDE_ON_CLOSE by default
String svalue = (String)pane.getValue();
if(! (svalue==null || !svalue.equals("印刷"))){// System.exit(0);
pj.setPrintable(prevPrintable); //printable instance
System.out.println(pj.getPrintService().getName()); //test
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);
}
}
}
//System.out.println("...");
//dialog.dispose();
}
}
ボタンが2段になってしまいますが、実用上問題ないでしょう。上下の狭いノートPCでどうなるかはちょっと心配です。
JDialogを拡張してCENTERにプレビュー、EASTに1つのラベルと4つのボタンを縦に並べるのが良いかもしれませんが、今回はここで留めておきます。

画面が小さい場合、下のタスクバーに[印刷][中止]ボタンが隠れてしまい操作ができなくなるという場合はプレビューが画面からはみ出しますをご覧ください。(上記プログラムリストには加えてあります(2017-05-05))
使うことはないかもしれないが、GUIのコンポーネントの親子関係を追う方法と、親子関係そのものの資料
TsuuchiHRのインスタンスから、となりのPanelにあるlabelを見つけるために、setStatLabel()を作るった。その前にgetParent()などを用いて探ることを考えた。この方法はコンポーネントの配置が終わって、ダイアログが完成してからでないと使えない。つまりコンストラクタ中ではうまく行かない。インスタンスができても、どこに配置されるかは決まらないので、actionPerformed()に書いた。
for(Component comp : this.getParent().getParent().getParent().getComponents()){
System.out.println(comp.getClass()+":"+comp.getName());
if(comp instanceof JPanel){
JPanel cc = (JPanel)comp;
//x不可 System.out.println("+"+cc.kari.getClass());
for(Component comp2 :cc.getComponents()){
System.out.println("-"+comp2.getClass()+":"+comp2.getName());
if(comp2 instanceof JLabel) statlabel = (JLabel)comp2;
}
}
}
statlabel.setName("status");
class javax.swing.JScrollPane:null class javax.swing.JPanel:null -class javax.swing.JButton:null -class javax.swing.JLabel:status -class javax.swing.JButton:null
ここが 1 。数字は.getParent()の数。.getParent()を1つずつ加えていって、
Container comp1 = this.getParent();
System.out.println("1 "+comp1.getClass()+":"+comp1.getName());
for(Component comp2 : comp1.getComponents()){
System.out.println(" _"+comp2.getClass()+":"+comp2.getName());
}
12で例外発生
Container comp1 = this.getParent().getParent().getParent().getParent().getParent().getParent().getParent().getParent().getParent().getParent().getParent().getParent();
System.out.println("12"+comp1.getClass()+":"+comp1.getName());
for(Component comp2 : comp1.getComponents()){
System.out.println(" _"+comp2.getClass()+":"+comp2.getName());
}
例外の直前から逆順で結果を再構成
11class javax.swing.JDialog:dialog0 _class javax.swing.JRootPane:null 10class javax.swing.JRootPane:null _class javax.swing.JPanel:null.glassPane _class javax.swing.JLayeredPane:null.layeredPane 9 class javax.swing.JLayeredPane:null.layeredPane _class javax.swing.JPanel:null.contentPane 8 class javax.swing.JPanel:null.contentPane _class javax.swing.JOptionPane:null 7 class javax.swing.JOptionPane:null _class javax.swing.JPanel:null _class javax.swing.JPanel:OptionPane.buttonArea 6 class javax.swing.JPanel:null _class javax.swing.JPanel:OptionPane.realBody 5 class javax.swing.JPanel:OptionPane.realBody _class javax.swing.JPanel:OptionPane.body
JDialogからOptionPaneまでtreeを書いてみる
その先、
4 class javax.swing.JPanel:OptionPane.body _class javax.swing.JPanel:null 3 class javax.swing.JPanel:null _class javax.swing.JScrollPane:null _class javax.swing.JPanel:null 2 class javax.swing.JScrollPane:null _class javax.swing.JViewport:null _class javax.swing.JScrollPane$ScrollBar:null _class javax.swing.JScrollPane$ScrollBar:null 1 class javax.swing.JViewport:null _class print01.TsuuchiHR:null 0 class print01.TsuuchiHR:null
OptionPaneにJPanelからはプログラムでaddしたものを追いかけることができる。JScrollPaneに入れたTsuuchiHRのインスタンスはJViewportに入れられていることがわかる。
「次」「前」のボタンは最後のJPanel:nullに入っていて、getParent()の繰り返しの中ではブランチとなるので、見えない。
例外の冒頭。JDialog.getParent()がNullPointerExceptionになるということ。
adachi@debian64:/media/S1T/basicaka/akajava/javadabiyone$ Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at print01.TsuuchiHR.actionPerformed(TsuuchiHR.java:82) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) at java.awt.Component.processMouseEvent(Component.java:6516)