java打印票据demo

package com.zns.print;

import com.zns.model.Product;
import com.zns.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.awt.*;
import java.awt.print.*;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Component
public class MyPrint implements Printable {
    @Autowired
    private ProductService productService;
    private static MyPrint myPrint;

    @PostConstruct
    //通过@PostConstruct实现初始化bean之前进行的操作
    public void init() {
        myPrint = this;
        myPrint.productService = this.productService;
    }

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //每个条项的长度
    private float filedW = 120;
    //list里面字段的默认长度
    private float commonListItemW = 55;
    //序号
    private int dataNo = 0;
    //标题
    private String title = "出 库 单";
    //列表字段名称
    private List<String> listFieldTitles = new ArrayList<>(Arrays.asList("序号", "编号", "名称", "规格", "单位", "单价", "数量", "小计", "备注"));
    //列表字段长度
    private List<Float> listFieldWidths = new ArrayList<>(Arrays.asList(commonListItemW, commonListItemW, commonListItemW, commonListItemW, commonListItemW, commonListItemW, commonListItemW, commonListItemW, commonListItemW));
    //列表字段key 对应对象的属性值
    private List<String> listFieldKeys = new ArrayList<>(Arrays.asList("no", "code", "name", "spec", "unit", "unitPrice", "num", "total", "remark"));
    private List<Product> dataList;
    //需要打印的页数
    private int totalPageCount;

    public List<Product> getDataList() {
        return dataList;
    }

    public void setDataList(List<Product> dataList) {
        this.dataList = dataList;
    }

    public int getTotalPageCount() {
        return totalPageCount;
    }

    public void setTotalPageCount(int totalPageCount) {
        this.totalPageCount = totalPageCount;
    }

    /**
     * 打印方法
     * graphics - 用来绘制页面的上下文,即打印的图形
     * pageFormat - 将绘制页面的大小和方向,即设置打印格式,如页面大小一点为计量单位(以1/72 英寸为单位,1英寸为25.4毫米。A4纸大致为595 × 842点)
     * pageIndex - 要绘制的页面从 0 开始的索引 ,即页号
     */
    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        System.out.println("pageIndex为:" + pageIndex);
        //获取数据
        this.dataList = myPrint.productService.getDataList(pageIndex + 1);

        Graphics2D g2 = (Graphics2D) graphics;
        g2.setColor(Color.black);
        if (pageIndex > totalPageCount - 1) {
            return NO_SUCH_PAGE;
        } else {
            System.out.println("开始打印第:" + (pageIndex + 1) + "页");
            g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());// 转换坐标,确定打印边界

            //打印起点坐标
            double x = pageFormat.getImageableX();  //返回与此 PageFormat相关的 Paper对象的可成像区域左上方点的 x坐标。
            double y = pageFormat.getImageableY();  //返回与此 PageFormat相关的 Paper对象的可成像区域左上方点的 y坐标。

            //Font.PLAIN: 普通样式常量  Font.ITALIC 斜体样式常量 Font.BOLD 粗体样式常量。
            Font font = new Font("宋体", Font.BOLD, 18);
            g2.setFont(font);//设置标题打印字体
            g2.setStroke(new BasicStroke(1.0f));//线条宽度
            float height = font.getSize2D();//获取字体的高度

            //设置标题
            g2.drawString(title, (float) x + 180, (float) y + height);

            float line = 2 * height; //下一行开始打印的高度
            g2.setFont(new Font("宋体", Font.PLAIN, 10));
            height = font.getSize2D();// 字体高度

            line += 5;
            g2.drawString("出货日期: 2018-01-01", (float) x, (float) y + line);
            g2.drawString("交货进间: 2018-01-01", (float) x + filedW, (float) y + line);
            g2.drawString("出货单号: 20180101123", (float) x + 2 * filedW, (float) y + line);

            line += height;
            g2.drawString("取货方式: 货到付款", (float) x, (float) y + line);
            g2.drawString("电话号码: 18818000000", (float) x + filedW, (float) y + line);
            g2.drawString("页    次: 第 1 页,共 2 页", (float) x + 2 * filedW, (float) y + line);

            line += height;
            g2.drawString("收 货 人: 张三", (float) x, (float) y + line);
            g2.drawString("移动电话: 18818000000", (float) x + filedW, (float) y + line);
            g2.drawString("订购客户: 华强北九方店", (float) x + 2 * filedW, (float) y + line);

            line += height;
            g2.drawString("收货地址: 深圳市福田区会展中心", (float) x, (float) y + line);
            g2.drawString("出货仓库: 总仓", (float) x + 2 * filedW, (float) y + line);

            //表格线微调值
            float lineFineTuning = 5;
            //设置列表项标题
            line += height;
            //画上横线
            g2.drawLine((int) (x - lineFineTuning), (int) (y + line - height + lineFineTuning), (int) (x + getlistFieldWidthTotal()), (int) (y + line - height + lineFineTuning));
            //画左竖线
            g2.drawLine((int) (x - lineFineTuning), (int) (y + line - height + lineFineTuning), (int) (x - lineFineTuning), (int) (y + line + lineFineTuning));
            for (int i = 0; i < listFieldTitles.size(); i++) {
                float offsetNum = 0;
                for (int j = 0; j < i; j++) {
                    offsetNum += listFieldWidths.get(j);
                }
                g2.drawString(listFieldTitles.get(i).toString(), (float) x + offsetNum, (float) y + line);
                //画竖线
                int temX = (int) (x + getlistFieldWidthTotal(i) - lineFineTuning);
                if (i == listFieldTitles.size() - 1) {
                    temX = temX + (int) lineFineTuning;
                }
                g2.drawLine(temX, (int) (y + line - height + lineFineTuning), temX, (int) (y + line + height));
            }
            //画下横线
            g2.drawLine((int) (x - lineFineTuning), (int) (y + line + lineFineTuning), (int) (x + getlistFieldWidthTotal()), (int) (y + line + lineFineTuning));

            //设置列表项数据
            line += height;
            if (dataList != null && dataList.size() > 0) {
                for (int i = 0; i < dataList.size(); i++) {
                    dataNo++;
                    for (int k = 0; k < listFieldKeys.size(); k++) {
                        float offsetNum = 0;
                        for (int j = 0; j < k; j++) {
                            offsetNum += listFieldWidths.get(j);
                        }
                        String filedValue = "";
                        //如果是序号列
                        if (k == 0) {
                            filedValue = String.valueOf(dataNo);
                        } else {
                            filedValue = getValueByKey(dataList.get(i), listFieldKeys.get(k)).toString();
                        }
                        g2.drawString(filedValue, (float) x + offsetNum, (float) y + line);
                        //画竖线
                        int temX = (int) (x + getlistFieldWidthTotal(k) - lineFineTuning);
                        if (k == listFieldTitles.size() - 1) {
                            temX = temX + (int) lineFineTuning;
                        }
                        g2.drawLine(temX, (int) (y + line - height + lineFineTuning), temX, (int) (y + line + lineFineTuning));
                        //画下横线
                        g2.drawLine((int) (x - lineFineTuning), (int) (y + line + lineFineTuning), (int) (x + getlistFieldWidthTotal()), (int) (y + line + lineFineTuning));
                    }
                    //画左竖线
                    g2.drawLine((int) (x - lineFineTuning), (int) (y + line - height + lineFineTuning), (int) (x - lineFineTuning), (int) (y + line + lineFineTuning));
                    line += height;
                }
            }

            //在点 (x1, y1) 和 (x2, y2) 之间画一条线
            //line += height;
            //g2.drawLine((int) x, (int) (y + line), (int) x + 500, (int) (y + line));

            //虚线
            //line += height;
            //g2.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10.0f, new float[] { 2, 2 }, 0));
            //g2.drawLine((int) x, (int) (y + line), (int) x + 500, (int) (y + line));

            line += height;
            g2.drawString("备注: 这里是备注...", (float) x, (float) y + line);

            line += height;
            g2.drawString("服务电话: 18818000000", (float) x, (float) y + line);
            g2.drawString("订单编号: 20180101123", (float) x + filedW, (float) y + line);
            g2.drawString("制表日期:" + sdf.format(new Date()), (float) x + 2 * filedW, (float) y + line);

            line += height;
            g2.drawString("订购: 华强北九方店", (float) x, (float) y + line);
            g2.drawString("白联:仓库  红联:客户  蓝、黄联:财务", (float) x + filedW, (float) y + line);

            return PAGE_EXISTS;
        }
    }

    /**
     * 获取对象属性值
     *
     * @param obj
     * @param key
     * @return
     */
    public static Object getValueByKey(Object obj, String key) {
        // 得到类对象
        Class userCla = (Class) obj.getClass();
        /* 得到类中的所有属性集合 */
        Field[] fs = userCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); // 设置些属性是可以访问的
            try {
                if (f.getName().endsWith(key)) {
                    return f.get(obj);
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        // 没有查到时返回空字符串
        return "";
    }

    //获取列表字段总宽度
    private float getlistFieldWidthTotal() {
        float widthTotal = 0;
        for (int i = 0; i < listFieldWidths.size(); i++) {
            widthTotal += listFieldWidths.get(i);
        }
        return widthTotal;
    }

    //获取截止到某个字段索引的字段总宽度 index从0开始
    private float getlistFieldWidthTotal(int index) {
        float widthTotal = 0;
        for (int i = 0; i <= index; i++) {
            widthTotal += listFieldWidths.get(i);
        }
        return widthTotal;
    }

    public void doPrint(Printable printable) {
        try {
            MyPrint myPrint = new MyPrint();
            //Book 类提供文档的表示形式,该文档的页面可以使用不同的页面格式和页面 painter
            Book book = new Book(); //要打印的文档
            //PageFormat类描述要打印的页面大小和方向
            PageFormat pf = new PageFormat();  //初始化一个页面打印对象
            pf.setOrientation(PageFormat.PORTRAIT); //设置页面打印方向,从上往下,从左往右
            //设置打印纸页面信息。通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
            Paper paper = new Paper();
            // 纸张大小
            //paper.setSize(683, 793.7);
            paper.setSize(683, 500);
            // A4(595 X 842)设置打印区域 A4纸的默认X,Y边距是72
            //paper.setImageableArea(20, 20, 683, 793.7);
            paper.setImageableArea(20, 20, 683, 500);
            pf.setPaper(paper);
            book.append(printable, pf, this.totalPageCount);
            PrinterJob job = PrinterJob.getPrinterJob();   //获取打印服务对象
            job.setPageable(book);  //设置打印类
            job.print();
        } catch (PrinterException e) {
            e.printStackTrace();
        }
    }
}

 

 

控制器调用

@Autowired
private ProductService productService;

@RequestMapping("/print")
@ResponseBody
public String print() {
    MyPrint myPrint = new MyPrint();
    //设置打印页面数量
    myPrint.setTotalPageCount(2);
    myPrint.doPrint(myPrint);
    System.out.println("打印成功。。。");
    return "打印...";
}

 

转载于:https://www.cnblogs.com/zengnansheng/p/10404722.html

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java是一种面向对象编程语言,拥有强大的打印和网络编程功能。打印票据和使用Socket进行网络通信是Java编程中常见且重要的功能之一。 在Java打印票据,通常可以使用Java打印库中的JasperReports或iText等第三方库。这些库可以帮助开发人员快速生成、设计和打印复杂而庞大的票据,同时提供丰富的定制功能。开发人员可以通过这些库创建报表模板,并将数据源与模板连接,以生成所需的打印输出格式。 使用Java Socket进行网络通信则需要实现客户端和服务器之间的连接。开发人员可以使用Java Socket API中的socket、ServerSocket和DatagramSocket等类来实现这些连接。Socket通常用于建立TCP连接,而DatagramSocket用于建立UDP连接。 在使用Java Socket进行网络通信时,需要考虑到通信协议、消息格式、端口号等方面的细节,以确保数据的安全传输。开发人员还可以在Socket之上使用SSL/TLS协议来加密通信内容,进一步保护网络安全。 总的来说,Java打印票据和使用Socket进行网络通信方面具有强大的能力,开发人员可以利用这些功能来构建高质量、安全可靠的应用程序。 ### 回答2: Java打印票据Socket是一种将Java技术与网络通信技术相结合的应用方式。通过这种方式,可以在网络上实现打印票据的功能,具有方便、高效、安全等多种优势。 首先,Java打印票据Socket利用Java的网络编程技术,从服务器获取打印票据的信息,然后将其传输到打印机进行打印,这样可以避免了在本地进行复杂的设置和操作,从而提高了效率。 其次,Java打印票据Socket的特点是具有安全性和稳定性,它可以通过设置协议、安全认证、数据加密等方式来保护数据的安全性,同时可以通过错误处理、重连机制、超时控制等方式保证网络通信的稳定性。 最后,Java打印票据Socket是一种灵活的应用方式,可以适应各种应用环境。无论是在小型企业、零售店铺还是大型商场、展览会场,都可以通过Java打印票据Socket实现打印票据的功能。 总之,Java打印票据Socket是一种优秀的应用方式,可以提高打印效率、保证打印安全、稳定性,并适应各种应用环境的要求。 ### 回答3: Java打印票据可以通过Socket实现。首先,需要在客户端程序中创建Socket连接,连接到打印机所在的IP地址和端口号。接着,将要打印的文本内容通过Socket传输到打印机端,然后在打印机端进行解析并打印出来。 在打印机端,需要编写一个Socket服务器程序来监听客户端的连接请求,接收客户端传输的文本内容,并将文本写入到打印机的缓存中。当缓存区中的文本达到打印机的缓存大小时,打印机就会打印出文本内容。 需要注意的是,在打印票据时,需要设置打印机的一些参数,如字体大小、字体样式、对齐方式等,以保证打印结果符合要求。 在实现中,可以使用Java自带的Socket类或者第三方库如Netty来处理Socket通信和打印机驱动的编写。此外,还需要了解一些Socket编程和打印机驱动的知识,以确保程序能够正确地实现打印功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值