Java 打印功能带预览,纸张大小设置

效果图

package print;

import java.awt.*;
import java.awt.print.*;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.standard.PrinterName;
import javax.swing.*;

import utils.PrinterSet;

//打印预览父类
public class PrintPreview extends JFrame {
    private static final long serialVersionUID = 1L;

    Printable printable;
    PageFormat pageFormat;
    PrintPreviewCanvas printPreviewCanvas;
    String printerName;
    
    public PrintPreview() {
        JButton print=new JButton("打印");
        this.add(print,BorderLayout.SOUTH);
        this.setLocationRelativeTo(null);//居中
        //打印
        print.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent ev) {
                print();
            }
        });
    }

    public void setPrintable(Printable printable) {
        this.printable = printable;
    }
    //打印
    protected void print() {
        PrinterJob job=PrinterJob.getPrinterJob();
        //job.setPrintable(printable);

        Book book = new Book();
        book.append(printable, pageFormat);
        job.setPageable(book);
          
        HashAttributeSet hs = new HashAttributeSet();
        hs.add(new PrinterName(printerName,null));//通过打印机名称选择打印机
        PrintService[] pss = PrintServiceLookup.lookupPrintServices(null, hs);
        if(pss.length==0)
        {
            JOptionPane.showMessageDialog(null, "请检查打印机设置\n");
            return ;
        }
           // System.out.println("打印机:"+printerName);
        try {
             // if (!job.printDialog())return;//取消   此方法会将页边距变为0 原因未知 
            job.setPrintService(pss[0]);
            job.print();
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "打印失败\n"+e.toString());
        }
    }
    private void setPreviewWindow(int x,int y) {
        
        add(new JPanel(),BorderLayout.EAST);//边框
        add(new JPanel(),BorderLayout.WEST);
        add(new JPanel(),BorderLayout.NORTH);
        setSize(x+40,y+40);
    }
    //纸张大小设置
    protected void setPaper(int x,int y,int orientation) {
        Paper paper=new Paper();
        pageFormat=new PageFormat();
        paper.setSize(x,y);//设置一页纸的大小
        paper.setImageableArea(0,0,x,y) ;//设置打印区域的大小
        pageFormat.setPaper(paper);
        pageFormat.setOrientation(orientation);
        
        if(orientation==PageFormat.LANDSCAPE) setPreviewWindow(y,x);
        else setPreviewWindow(x,y);

        //printPreviewCanvas.setPreferredSize(new Dimension(y,x));
        add(printPreviewCanvas);//预览内容
    }
    protected void setPaper(int x,int y) {
        setPaper(x,y,PageFormat.PORTRAIT);
    }

    //以下是子类中使用于绘制表格
    //居中
    static void drawCellOnCenter(Graphics2D g2,String text,int x, int y,int width,int height){
        FontMetrics fm = g2.getFontMetrics();//用于获取字符串宽高
        g2.drawString(text,x + (width - fm.stringWidth(text)) / 2,
                y+ fm.getAscent() + (height - fm.getHeight()) / 2);
    }
    //左对齐
    static void drawCellOnLeft(Graphics2D g2,String text,int x, int y,int width,int height){
        FontMetrics fm = g2.getFontMetrics();//用于获取字符串宽高
        g2.drawString(text,x +fm.getHeight()/3,
                y+ fm.getAscent() + (height - fm.getHeight()) / 4);
    }
    //是否超出列宽
    static boolean isLineFlow(Graphics2D g2,String text,int width){
         FontMetrics fm =g2.getFontMetrics();//用于获取字符串宽高
         if(fm.stringWidth(text)>width-fm.getHeight()) return true;
         return false;
    }
    //带自动换行
    static int drawCellOnCenterRows(Graphics2D g2,String text,int x, int y,int width,int height){
         FontMetrics fm =g2.getFontMetrics();//用于获取字符串宽高
         int stringWidth;
         String s;
         int rowCount=0;
         for(int i=1;i<=text.length();i++){
             s=text.substring(0,i);//i不包括
             stringWidth=fm.stringWidth(s);
             if(stringWidth>width-fm.getHeight()){//换行
                 s=text.substring(0,i-1);
                 drawCellOnCenter(g2,s,x,y,width,height);
                 rowCount++;
                 text=text.substring(i-1,text.length());//取剩下的
                 y+=height;
                 i=1;
             }
             else{
                 if(i==text.length()) {
                     drawCellOnCenter(g2,s,x,y,width,height);
                     rowCount++;
                     break;
                 }
             }
                 
         }
         return rowCount;
     }  
    

}

//----------------------------
//PrintPreview内部类  用于绘制打印内容,在setPaper中调用
class PrintPreviewCanvas extends Canvas {
    private static final long serialVersionUID = 1L;
    Printable printable;

    public PrintPreviewCanvas(Printable printable) {
        this.printable=printable;
        this.setBackground(Color.white);
    }

    public void paint(Graphics g){

        try {
            printable.print(g, null, 0);
        } catch (PrinterException e) {
            e.printStackTrace();
        }
    }
}


//----------------------------
//PrintPreview子类  实现Printable重写print绘制打印内容

package print;

import java.awt.*;
import java.awt.print.*;
import java.text.SimpleDateFormat;
import java.util.Date;

import table.PackageDetailTable;
import utils.PrinterSet;

public class ProductPrintPreview extends PrintPreview implements Printable{
    private static final long serialVersionUID = 1L;
    PackageDetailTable table=new PackageDetailTable();
    
    //packageDetailTable数据内容,visible=false时不显示预览窗口
    public ProductPrintPreview(PackageDetailTable packageDetailTable, boolean visible) {
        
        setPrintable(this);        
        printPreviewCanvas=new PrintPreviewCanvas(this);
        if(getPaperSize().equals("A4")){
            setPaper(595,842,PageFormat.LANDSCAPE);
        }else{
            setPaper(480,620,PageFormat.LANDSCAPE);
        }
        this.setLocationRelativeTo(null);//居中
         
        this.table=packageDetailTable;
        super.printerName=PrinterSet.getBigPrinter();
        
        if(visible) setVisible(true);
        else print();
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

        /*        int up=Integer.parseInt(PrinterSet.getPrinter1Up());
        int left=Integer.parseInt(PrinterSet.getPrinter1Left());*/
        int startX;
        int startY;    
        if(getPaperSize().equals("A4")){
            startX=120;
            startY=120;
        }else{
            startX=36;
            startY=55;    
        }
        int tableTop=startY+50;     
        int productRow=Integer.parseInt(table.getName());//要打印的产品在表中的行
            
        Graphics2D g2 = (Graphics2D) graphics;
        g2.setStroke(new BasicStroke(0.8f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));//设置画笔粗细的    
        
        Font font=new Font("黑体",Font.PLAIN,18);
        g2.setFont(font);
        g2.drawString("配 件 清 单 ",startX+240,startY+18); 
        
        font=new Font("宋体",Font.BOLD,8);
        g2.setFont(font);
        
        String order=table.getValueAt(0, 1).toString().substring(5);
        g2.drawString("单号:"+order,startX+10,tableTop-10);


        int tableLeft=startX;
        int cw1=30;//类别
        int cw2=160;//型号
        int cw3=210;//规格
        int cw4=25;//单位
        int cw5=25;//数量    
        int cw6=120;//附注        
        
        int tableWidth=cw1+cw2+cw3+cw4+cw5+cw6;    
        int headeHeightt=28;  
        int lineHeight=14;  
        int bodyLineCount=13;  
        int tableHeight=headeHeightt+lineHeight*(bodyLineCount+2); 

        //表头
        int x=tableLeft;
        drawCellOnCenter(g2,"类别",x,tableTop,cw1,headeHeightt);
        drawCellOnCenter(g2,"产品型号",x+=cw1,tableTop,cw2,headeHeightt);
        drawCellOnCenter(g2,"产品规格",x+=cw2,tableTop,cw3,headeHeightt);
        drawCellOnCenter(g2,"单位",x+=cw3,tableTop,cw4,headeHeightt);
        drawCellOnCenter(g2,"数量",x+=cw4,tableTop,cw5,headeHeightt);
        drawCellOnCenter(g2,"附注",x+=cw5,tableTop,cw6,headeHeightt);
        
        int y=tableTop;
        g2.drawLine(tableLeft,y,tableLeft+tableWidth,y);//横线0 
        g2.drawLine(tableLeft,y+=headeHeightt,tableLeft+tableWidth,y);//横线1         

        tableTop+=headeHeightt;
        x=tableLeft;
        int rows=2,row1,row2;
        String text1=table.getValueAt(productRow, 3).toString();//型号
        String text2=table.getValueAt(productRow, 4).toString();
        int productHight=lineHeight*rows;
        if(!isLineFlow(g2,text1,cw2)&&!isLineFlow(g2,text2,cw3)) {
            drawCellOnCenter(g2,text1,x+=cw1,tableTop,cw2,headeHeightt);
            drawCellOnCenter(g2,text2,x+=cw2,tableTop,cw3,headeHeightt);
            productHight=lineHeight*rows;
        }
        else{
            row1=drawCellOnCenterRows(g2,text1,x+=cw1,tableTop,cw2,lineHeight);
            row2=drawCellOnCenterRows(g2,text2,x+=cw2,tableTop,cw3,lineHeight);
            rows=row1>row2?row1:row2;
            productHight=lineHeight*rows;
        }
        
        drawCellOnCenter(g2,"主机",tableLeft,tableTop,cw1,productHight);  
        drawCellOnCenter(g2,"台",x+=cw3,tableTop,cw4,productHight);
        drawCellOnCenter(g2,"1",x+=cw4,tableTop,cw5,productHight);

        g2.drawLine(tableLeft,y+=productHight,tableLeft+tableWidth,y);//横线end

        //表框架
        tableTop-=headeHeightt;
        x=tableLeft;
        tableHeight+=productHight;
        g2.drawLine(x,tableTop,x,tableTop+tableHeight);//竖0
        g2.drawLine(x+=cw1,tableTop,x,tableTop+tableHeight);//竖1
        g2.drawLine(x+=cw2,tableTop,x,tableTop+tableHeight);//竖2
        g2.drawLine(x+=cw3,tableTop,x,tableTop+tableHeight);//竖2
        g2.drawLine(x+=cw4,tableTop,x,tableTop+tableHeight);//竖2
        g2.drawLine(x+=cw5,tableTop,x,tableTop+tableHeight);//竖2   
        g2.drawLine(x+=cw6,tableTop,x,tableTop+tableHeight);//竖3 
           Date date=new Date();
           String time;
           SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");//设置日期格式        
           time=df.format(date);
        g2.drawString("装配员:"+time,startX+50,tableTop+tableHeight+lineHeight); 
        g2.drawString("装配日期:"+time,startX+450,tableTop+tableHeight+lineHeight); 
        tableTop+=headeHeightt;   
        
        //表身
        tableTop+=productHight;
        for(int i=0;i<bodyLineCount;i++){
            g2.drawLine(tableLeft+cw1,tableTop+lineHeight*i,tableLeft+tableWidth,tableTop+lineHeight*i); 
        }
        tableHeight=lineHeight*bodyLineCount;    
        g2.drawLine(tableLeft,tableTop+tableHeight,tableLeft+tableWidth,tableTop+tableHeight);//横线end       
        
        x=tableLeft;
        drawCellOnCenter(g2,"配件",x,tableTop,cw1,tableHeight);    
        
        String list[][]={{"C1","1/2NPT引压过渡焊接头","套",""},
                {"C2","M20X1.5丁字接头","套","配:M10X25螺栓2个,油封1个"},
                {"C3","1/2NPT锥管阴螺纹接头","套","配:M10X35螺栓2个,油封1个"},
                {"B1","管装弯支架","套","配:M10X16螺栓4个,U型卡1个"},
                {"B2","盘装弯支架","套","配:M10X16螺栓4个"},    
                {"B3","管装平支架","套","配:M10X16螺栓4个,U型卡1个"},
                {"下套","","件",""},    
                {"垫片","","片",""},    
                {"盲法兰","","片",""},
                {"安装法兰","","片",""},
                {"紧固件","","套",""},
        };
        for(int i=0;i<11;i++){
            x=tableLeft;
            drawCellOnCenter(g2,list[i][0],x+=cw1,tableTop+lineHeight*i,cw2,lineHeight);
            drawCellOnCenter(g2,list[i][1],x+=cw2,tableTop+lineHeight*i,cw3,lineHeight);
            drawCellOnCenter(g2,list[i][2],x+=cw3,tableTop+lineHeight*i,cw4,lineHeight);
            drawCellOnLeft(g2,list[i][3],x+=(cw4+cw5),tableTop+lineHeight*i,cw6,lineHeight);       
        }
        //随机文件
        
        tableTop+=tableHeight;
        tableHeight=lineHeight*2;        
        g2.drawLine(tableLeft+cw1,tableTop+lineHeight,tableLeft+tableWidth,tableTop+lineHeight);   
        g2.drawLine(tableLeft,tableTop+tableHeight,tableLeft+tableWidth,tableTop+tableHeight);//横线end
        
        String plist[][]={{"随机","使用说明书","本","1"},
                {"文件","合格证/检测报告","张","1"},
        };
        for(int i=0;i<2;i++){
            x=tableLeft;
            drawCellOnCenter(g2,plist[i][0],x,tableTop+lineHeight*i,cw1,lineHeight);
            drawCellOnCenter(g2,plist[i][1],x+=cw1,tableTop+lineHeight*i,cw2,lineHeight);
            drawCellOnCenter(g2,plist[i][2],x+=(cw2+cw3),tableTop+lineHeight*i,cw4,lineHeight);
            drawCellOnCenter(g2,plist[i][3],x+=(cw4),tableTop+lineHeight*i,cw5,lineHeight);       
        }

        return Printable.PAGE_EXISTS;

    }    }