一、默认打印机工具类
package vpos.zs.print;
import net.sf.json.JSONObject;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import javax.print.PrintServiceLookup;
import swing.zs.util.LogUtil;
/**
* 调用默认打印机,打印销售小票
*/
public class PrintUtil extends Thread {
private static PrintUtil instance;
private static LinkedBlockingQueue<Map<String, Object>> printQueue = new LinkedBlockingQueue<Map<String, Object>>();
private static PrinterJob job = PrinterJob.getPrinterJob();
private PrintUtil() {
start();
}
public void run() {
while (true) {
try {
if (printQueue.size() > 0) {
// print(printQueue.poll());
Map<String, Object> printMap = printQueue.poll();
if (null!=printMap.get("test")&&printMap.get("test").equals("test")){
sendPrintBufferTEST(printMap);
}else {
printSaleBill(printMap);
}
} else {
Thread.sleep(1000);
}
} catch (Exception e) {
}
}
}
public void printSaleBill(Map<String, Object> printMap) {
try {
// 用户可选用的打印服务数组
// PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
// DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
// PrintService printService[] = PrintServiceLookup
// .lookupPrintServices(flavor, pras);
//
// for (PrintService ps : printService) {
// System.out.println(ps.getName());
// }
// 默认的打印服务
// PrintService defaultService = PrintServiceLookup
// .lookupDefaultPrintService();
// System.out.println(defaultService.getName());
// 通俗理解就是书、文档
Book book = new Book();
// 设置成横打
PageFormat pf = new PageFormat();
pf.setOrientation(PageFormat.PORTRAIT);
// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
Paper p = new Paper();
p.setSize(400, 600);// 纸张大小
p.setImageableArea(0, 0, 360, 580);// A4(595 X 842)设置打印区域,其实0,0应该是72,72,因为A4纸的默认X,Y边距是72
pf.setPaper(p);
SaleBillPrintable mp = new SaleBillPrintable(printMap);
// 把 PageFormat 和 Printable 添加到书中,组成一个页面
book.append(mp, pf);
//调用系统给默认的打印服务
job.setPrintService(PrintServiceLookup.lookupDefaultPrintService());
job.setPageable(book);
job.print();
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendPrintBufferTEST(Map<String, Object> printMap) {
try {
// 通俗理解就是书、文档
Book book = new Book();
// 设置成横打
PageFormat pf = new PageFormat();
pf.setOrientation(PageFormat.PORTRAIT);
// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
Paper p = new Paper();
p.setSize(400, 600);// 纸张大小
p.setImageableArea(0, 0, 360, 580);// A4(595 X 842)设置打印区域,其实0,0应该是72,72,因为A4纸的默认X,Y边距是72
pf.setPaper(p);
PrintTestPrintable mp = new PrintTestPrintable(printMap);
// 把 PageFormat 和 Printable 添加到书中,组成一个页面
book.append(mp, pf);
//调用系统给默认的打印服务
job.setPrintService(PrintServiceLookup.lookupDefaultPrintService());
job.setPageable(book);
job.print();
} catch (Exception e) {
e.printStackTrace();
}
}
public void addPrintJob(Map<String, Object> printMap) {
try {
printQueue.put(printMap);
} catch (InterruptedException e) {
e.printStackTrace();
LogUtil.logger(e);
}
}
public static PrintUtil getInstance() {
if (instance == null || !instance.isAlive())
instance = new PrintUtil();
return instance;
}
// public static String getJsonValue(JSONObject json, Object key) {
// Object result = null;
// if (json != null) {
// result = json.get(key);
// }
// if (result == null) {
// return "";
// }
// return String.valueOf(result);
// }
public static void main(String[] args) {
JSONObject ticket=new JSONObject();
ticket.put("start_time", "2018-11-11 11:11:11");
ticket.put("ticket_price", 11);
ticket.put("cabin_price", 11);
ticket.put("fuel_price", 11);
ticket.put("port_price", 11);
PrintUtil.getInstance().addPrintJob(ticket);
}
}
二、打印内容类(自己做具体的排版)
package vpos.zs.print;
import net.sf.json.JSONObject;
import vpos.zs.entity.Currency;
import vpos.zs.entity.SYUser;
import vpos.zs.util.ConfigUtil;
import vpos.zs.util.DateUtil;
import vpos.zs.util.PrintStringUtil;
import vpos.zs.util.SystemConfig;
import java.awt.*;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
/*
* 打印销售小票
*/
public class SaleBillPrintable implements Printable {
private Map<String, Object> bill = null;
private List<String> textList = new ArrayList<String>();
/**
* 格式化金额,保留两位小数
*
* @param strValue
* @return
*/
public String round(String strValue) {
double f = Double.parseDouble(strValue);
BigDecimal b = new BigDecimal(f);
double f1 = b.setScale(1, RoundingMode.HALF_UP).doubleValue();
strValue = String.valueOf(f1);
return strValue;
}
/**
* 打印80MM纸张
*
* @param printMap
* @throws IOException
*/
public SaleBillPrintable(Map<String, Object> printMap) throws IOException {
this.bill = printMap;
String billingUnid = (String) printMap.get("billingunid");//订单编号(数据)
Integer number = (Integer) printMap.get("number");//件数(数据)
DecimalFormat df = new DecimalFormat(".00");
String price = df.format(Double.parseDouble((String) printMap.get("price")));//总欸(数据)
String receive = df.format(Double.parseDouble((String) printMap.get("recieve")));//实收(数据)
String zhaoling = df.format(Double.parseDouble((String) printMap.get("zhaoling")));//找零(数据)
String mode =(String) printMap.get("mode"); //支付方式(数据)
if(mode.equals("cash")){mode = "cash(现金)";}
if(mode.equals("member")){mode = "member(会员)";}
if(mode.equals("union")){mode = "union(银联)";}
if(mode.equals("wechat")){mode = "wechat(微信)";}
if(mode.equals("alipay")){mode = "alipay(支付宝)";}
price = round(price);
receive = round(receive);
zhaoling =round(zhaoling);
@SuppressWarnings("unchecked")
Vector<Vector<String>> allProductVector = (Vector<Vector<String>>) printMap.get("data");
Currency c = (Currency) printMap.get("currency");
String symbol = c.getCurrency_symbol();
if("₩".equals(symbol)){symbol="W";}//由于打印出来的会乱码,改成W
//========================表头部分=======================
if(printMap.get("title")!=null&&printMap.get("title").toString().equals("欢迎光临时尚精品免税店(退货)")){
//退货换标题
textList.add("text|"+"("+SystemConfig.getLocale("pos_print_tuihuo_title")+")"+ SYUser.getInstance().getStoreName()+"|45|15|12|1");
}else {
//标题
textList.add("text|" + SystemConfig.getLocale("pos_print_sale_title") + SYUser.getInstance().getStoreName() + "|45|15|12|1");
}
//收银员
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_cashier") + ":" + SYUser.getInstance().getReal_name()+"|20|40|9|1");
//编号
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_id") + ":" + SYUser.getInstance().getUserid()+"|140|40|9|1");
//订单编号
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_orderid") + ":" + billingUnid+"|20|52|9|1");
//============================================
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_line")+"|20|65|9|1");
//========================销售内容部分=======================
//品名
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_good")+"|20|78|9|1");
//单价*数量
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_unit")+"*"+SystemConfig.getLocale("pos_print_sale_number")+"|110|78|9|1");
//金额
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_price")+"|173|78|9|1");
/*
* 生成打印小票主要部分
*/
int y = 102;
for (int i = 0; i < allProductVector.size(); i++) {
Vector<String> singleProductVector = allProductVector.get(i);
String productName = (String) singleProductVector.get(2); //品名(值)
String code = (String) singleProductVector.get(1); //条码(值)
String singleNumber = (String) singleProductVector.get(6);//数量(值)
String singlePrice = (String) singleProductVector.get(3); //单价(值)
if(mode.equals("member(会员)")) {
singlePrice = (String) singleProductVector.get(5);
}
String totalPrice = (String) singleProductVector.get(8);//金额(值)
singlePrice =round(singlePrice);
totalPrice =round(totalPrice);
if(singleProductVector.get(10).equals("赠送")||singleProductVector.get(10).equals("<html><font color=\"red\"> 赠送 </font></html>")){
totalPrice="0";
productName = productName+"(赠送)";
}
//品名(值)
textList.add("text|"+productName+"|20|"+(y-12)+"|9|1");
//条码(值)
textList.add("text|"+code+"|20|"+y+"|9|1");
//单价*数量(值)
textList.add("text|"+singlePrice+"*"+singleNumber+"|120|"+y+"|9|1");
//金额(值)
textList.add("text|"+totalPrice+"|175|"+y+"|9|1");
y = y+ 24; //多一个物品纵坐标y+24
}
//========================统计部分=======================
//============================================
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_line")+"|20|"+(y-11)+"|9|1");
//件数
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_totalnumber")+":"+number+"|20|"+(y+2)+"|9|1");
//总额
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_total")+":"+symbol+price+"|120|"+(y+2)+"|9|1");
//实收
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_receive")+":"+symbol+ receive+"|20|"+(y+14)+"|9|1");
//找零
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_change")+":"+symbol+ zhaoling+"|120|"+(y+14)+"|9|1");
//支付方式
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_mode")+":"+mode+"|20|"+(y+26)+"|9|1");
//时间
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_date")+":"+DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")+"|20|"+(y+38)+"|9|1");
//========================尾部部分=======================
//--------------------------------------
textList.add("text|"+"-----------------------------------"+"|20|"+(y+51)+"|9|1");
//联系电话
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_tel") + ": " + SYUser.getInstance().getTeltphone()+"|50|"+(y+64)+"|9|1");
//感谢语
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_foot1") +"|50|"+(y+76)+"|9|1");
textList.add("text|"+SystemConfig.getLocale("pos_print_sale_foot2") +"|50|"+(y+88)+"|9|1");
textList.add("text|"+"-"+"|110|"+(y+110)+"|9|1");
}
/**
*
* @param g2
* @param text 参数格式(text|文本|横坐标|纵坐标|字体大小|是否加粗)
*/
public void printText(Graphics g2, String text) {
String[] str = text.split("\\|");
if (!"text".equals(str[0])) {
return;
}
int x = Integer.valueOf(str[2]);
int y = Integer.valueOf(str[3]);
int fontSize = Integer.valueOf(str[4]);
int bold = Integer.valueOf(str[5]);
Font font = getMyFont(bold, fontSize);
g2.setFont(font);// 设置字体
g2.drawString(str[1], x, y);
}
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
// 转换成Graphics2D
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
switch (pageIndex) {
case 0:
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
// 打印起点坐标
// double x = pf.getImageableX();
// double y = pf.getImageableY();
// Image src = ImageUtil.getTicketImage();
// g2.drawImage(src, (int) x, (int) y, (int) width, (int) height, null);
float[] dash1 = { 4.0f };
g2.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 4.0f, dash1, 0.0f));
// 设置打印颜色为黑色
g2.setColor(Color.black);
for (String text : textList) {
printText(g2, text);
}
return PAGE_EXISTS;
default:
return NO_SUCH_PAGE;
}
}
public static Font getMyFont(int style, float size) {
Font font = null;
font = new Font("宋体", style, (int) size);
return font;
}
}
三、具体调用
PrintUtil pt = PrintUtil.getInstance();
pt.addPrintJob(printMap);