打印机型号:GT800,只要支持zpl,下面的方式都可以通用。
打印的具体样式如下所示:有引用其他文章的打印方式,但是不通用,而且中文这块,打印出来是反的,并且我需要一次性打印两张一样的,参考的链接百度都是那篇文章,如下:这是原博主的,百度很多都是抄这个一模一样,我在zpl语言那边有改进,具体看下面代码,有详细解析
先贴上整个类的代码,其中有一个ts24.lib文件我放在网盘,那玩意老费劲不好找,
网盘地址:链接:https://pan.baidu.com/s/1hsPz0F1uBBgg0hlRQDbIfw
提取码:o00d
package com.lims.common.core.utils.print;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.standard.PrinterName;//import sun.awt.AppContext;
/*** 采用点阵字库ts24.lib* @author Labrador**/
public class ZplPrinter {private String printerURI = null; //打印机完整路径private PrintService printService = null; //打印机服务private byte[] dotFont;private String darkness = "~SD10"; //Set Darkness设置色带颜色的深度 0-30private String width = "^PW1000"; //Print Width打印宽度0-1500private String length = "^LL800"; //Label Length标签长度0-x(暂无作用)private String begin = "^XA" + darkness + width; //标签格式以^XA开始private String end = "^XZ"; //标签格式以^XZ结束private String content = ""; //打印内容private String message = ""; //打印的结果信息/*** 构造方法* @param printerURI 打印机路径*/public ZplPrinter(String printerURI){this.printerURI = printerURI;//加载字体File file = new File("C:\\Users\\gonghf\\Desktop\\ts24.lib");if(file.exists()){FileInputStream fis;try {fis = new FileInputStream(file);dotFont = new byte[fis.available()];fis.read(dotFont);fis.close();} catch (IOException e) {e.printStackTrace();}}else{System.out.println("C://ts24.lib文件不存在");}//初始化打印机//AppContext.getAppContext().put(PrintServiceLookup.class.getDeclaredClasses()[0], null);//刷新打印机列表PrintService[] services = PrintServiceLookup.lookupPrintServices(null,null);if (services != null && services.length > 0) {for (PrintService service : services) {if (printerURI.equals(service.getName())) {printService = service;break;}}}if (printService == null) {System.out.println("没有找到打印机:["+printerURI+"]");//循环出所有的打印机if (services != null && services.length > 0) {System.out.println("可用的打印机列表:");for (PrintService service : services) {System.out.println("["+service.getName()+"]");}}}else{System.out.println("找到打印机:["+printerURI+"]");System.out.println("打印机名称:["+printService.getAttribute(PrinterName.class).getValue()+"]");}}/*** 设置条形码* @param barcode 条码字符* @param zpl 条码样式模板*/public void setBarcode(String barcode,String zpl) {content += zpl.replace("${data}", barcode);}/*** 中文字符、英文字符(包含数字)混合* @param str 中文、英文* @param x x坐标* @param y y坐标* @param eh 英文字体高度height* @param ew 英文字体宽度width* @param es 英文字体间距spacing* @param mx 中文x轴字体图形放大倍率。范围1-10,默认1* @param my 中文y轴字体图形放大倍率。范围1-10,默认1* @param ms 中文字体间距。24是个比较合适的值。*/public void setText(String str, int x, int y, int eh, int ew, int es, int mx, float my, int ms) {byte[] ch = str2bytes(str);for (int off = 0; off < ch.length;) {if (((int) ch[off] & 0x00ff) >= 0xA0) {//中文字符try {int qcode = ch[off] & 0xff;int wcode = ch[off + 1] & 0xff;
// content += String.format("^FO%d,%d^XG0000%01X%01X,%d,%d^FS\n", x, y, qcode, wcode, mx, my);content += String.format("^FO%d,%d^XG0000%01X%01X,%d,%f^FS\n", x, y, qcode, wcode, mx, my);
// System.out.println("content===="+content);begin += String.format("~DG0000%02X%02X,00072,003,\n", qcode, wcode);qcode = (qcode + 128 - 32) & 0x00ff;wcode = (wcode + 128 - 32) & 0x00ff;int offset = ((int) qcode - 16) * 94 * 72 + ((int) wcode - 1) * 72;for (int j = 0; j < 72; j += 3) {qcode = (int) dotFont[j + offset] & 0x00ff;wcode = (int) dotFont[j + offset + 1] & 0x00ff;int qcode1 = (int) dotFont[j + offset + 2] & 0x00ff;begin += String.format("%02X%02X%02X\n", qcode, wcode, qcode1);}x = x + ms * mx;off = off + 2;} catch (Exception e) {e.printStackTrace();//替换成X号setChar("X", x, y, eh, ew);x = x + es;//注意间距更改为英文字符间距off = off + 2;}} else if (((int) ch[off] & 0x00FF) < 0xA0) {//英文字符setChar(String.format("%c", ch[off]), x, y, eh, ew);x = x + es;off++;}}}/*** 英文字符串(包含数字)* @param str 英文字符串* @param x x坐标* @param y y坐标* @param h 高度 H* @param w 宽度*/public void setChar(String str, double x, double y, int h, int w) {content += "^FO" + x + "," + y + "^AQN," + h + "," + w + "^FD" + str + "^FS";}/*** 英文字符(包含数字)顺时针旋转180度* @param str 英文字符串* @param x x坐标* @param y y坐标* @param h 高度* @param w 宽度*/public void setCharR(String str, int x, int y, int h, int w) {content += "^FO" + x + "," + y + "^A0I," + h + "," + w + "^FD" + str + "^FS";}/*** 获取完整的ZPL* @return*/public String getZpl() {return begin + content + end;}/*** 重置ZPL指令,当需要打印多张纸的时候需要调用。*/public void resetZpl() {begin = "^XA" + darkness + width;end = "^XZ";content = "";}/*** 打印* @param zpl 完整的ZPL*/public boolean print(String zpl){if(printService==null){message = "打印出错:没有找到打印机["+printerURI+"]";System.out.println("打印出错:没有找到打印机["+printerURI+"]");return false;}DocPrintJob job = printService.createPrintJob();byte[] by = zpl.getBytes();DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;Doc doc = new SimpleDoc(by, flavor, null);try {job.print(doc, null);message = "已打印";System.out.println("已打印");return true;} catch (PrintException e) {message = "打印出错:"+e.getMessage();System.out.println("打印出错:"+e.getMessage());e.printStackTrace();return false;}}public String getMessage(){return message;}/*** 字符串转byte[]* @param s* @return*/private byte[] str2bytes(String s) {if (null == s || "".equals(s)) {return null;}byte[] abytes = null;try {abytes = s.getBytes("gb2312");} catch (UnsupportedEncodingException ex) {ex.printStackTrace();}return abytes;}//^B3N,Y,Y code39条形码public boolean printBarcode(ZplPrinter p){//1.打印单个条码String bar0 = "D21066000101";//条码内容String str = "厦门湖里永康门诊部";String bar0Zpl = "^FO190,90^BY1.4,3,80^BCN,60,N,N,N^FD${data}^FS";//条码样式模板p.setBarcode(bar0, bar0Zpl);p.setCharR(bar0,200,60,25,25);content += "^CI26^SEE:GB18030.DAT^CWJ,E:MSUNG24^CI28^FO160,20^A1I,10,10^FD"+str+"^FS";
// p.setText("厦门湖里永康门诊部", 160, 120, 10, 10, 30, 1, 0, 24);content += "^FO500,90^BY1.4,3,80^BCN,60,N,N,N^FD"+bar0+"^FS^FO510,60^A0I,25,25^FD"+bar0+"^FS^FT680,20^A1I,10,10^FD"+str+"^FS";String zpl = p.getZpl();System.out.println(zpl);boolean result = p.print(zpl);//打印return result;}public static void main(String[] args) {ZplPrinter p = new ZplPrinter("ZDesigner GT800 (EPL)");p.printBarcode(p);}
}
代码解析:
首先要找到打印机:原博主是通过远程分享的方式\pch啥玩意的,我是直接根据打印机的名字来,具体的可以看下面这个方法的service.getName,自己debug找一下自己的打印机名字就知道了
PrintService[] services = PrintServiceLookup.lookupPrintServices(null,null);if (services != null && services.length > 0) {for (PrintService service : services) {if (printerURI.equals(service.getName())) {printService = service;break;}}}
第二步就是那个lib文件,自己下了自己放
第三步就看如下这个方法里面的东西了,精髓都在这了:
//^B3N,Y,Y code39条形码public boolean printBarcode(ZplPrinter p){//1.打印单个条码String bar0 = "D21066000101";//条码内容String str = "厦门湖里永康门诊部";String bar0Zpl = "^FO190,90^BY1.4,3,80^BCN,60,N,N,N^FD${data}^FS";//条码样式模板p.setBarcode(bar0, bar0Zpl);p.setCharR(bar0,200,60,25,25);content += "^CI26^SEE:GB18030.DAT^CWJ,E:MSUNG24^CI28^FO160,20^A1I,10,10^FD"+str+"^FS";
// p.setText("厦门湖里永康门诊部", 160, 120, 10, 10, 30, 1, 0, 24);content += "^FO500,90^BY1.4,3,80^BCN,60,N,N,N^FD"+bar0+"^FS^FO510,60^A0I,25,25^FD"+bar0+"^FS^FT680,20^A1I,10,10^FD"+str+"^FS";String zpl = p.getZpl();System.out.println(zpl);boolean result = p.print(zpl);//打印return result;}
bar0Zpl 这个就是打印的模板,这个获取的方法,
第一,如果你的打印机比较高级,可以去下载ZebraDesigner 3 这个官网软件试试,会生成prn文件,我试过了我是用不了,不然就直接文本打开就可以看里面的zpl语言,这边这个链接可以看看你的打印机支持啥玩意:在文章的下面自己翻一下
第二:ZebraDesigner 3 for Developers 这个也是官方软件,这边可以去绑定变量然后去用,参考链接:工具的使用说明
第三:CODESOFT 2015这个软件要是有下过想研究的小伙伴感觉可以放弃了,这边中文什么的会乱码,有网上说找Unicode编码可以的,但是我没成功,有兴趣自己研究
第四:解答这个zpl:FO这个就是开始的意思,复制就好,后面两个190,90,是对应的xy坐标,自己去调整,BY这个是调整条形码的高度,宽度,然后中间那个空白的大小,那三个数字参数是这样的,第一个增幅是0.1,后面是1;BCN这个是D210000那个的字体调整,跟大小没啥关系,大小是下面方法调的
下面这个方法就是条形码替换,也可以直接写死,只是显得low一点
public void setBarcode(String barcode,String zpl) {content += zpl.replace("${data}", barcode);}
再然后就是p.setCharR这个方法了,这个是我中间那一串数字的打印,里面有一个^AOI这个I是字体的方向,还有R,O好像,反正I是旋转180度,最下面我会附上这个zpl语言的文档,可以自己细看这个东西。
重点来了,中文字:我参考的是这篇博主的东西:但是这个里面的中文会乱码
所以我在中文这边里面加上了^CI28,这个就是转UTF-8的意思,这个博主里面有说到:具体可打开细看
^A1I,10,10 这个东西是调整中文的大小,我试过了,最小就是我图片那种的大小,负数也一样,只能往更大了调整,虽然我需要更小的字体,但是一直没法解决,如果有小伙伴研究出来了,可以滴滴我一下,不胜感激。中间那个数字字体可以xy坐标随便调整大小。
然后固定的^FS就是结尾的意思了
另一个重点同行打印两一个条码:^FD这个符号加上然后自己调整x坐标就可以了
这边附上几个觉得还不错zpl的语言文档:这个对字体的方向描述比较清晰
这个是整个zpl的文档,道客巴巴的比较规范
这个是其他博主写的,大同小异,得自己去看
基本上就是这些东西了,花了我三天时间,人都傻了,希望写了这么多,能对研究打印机的人有些帮助吧,要是有描述不太明白的地方或者有什么其他好的建议,可以给我留言或者直接邮箱我1095254145@qq.com
共勉!!