为了开发android无线点餐系统,需要用到打印小票任务,根据网上查找资料所得,学习了两种方法,一种为通过tomcat服务连接服务器所连接的打印机打印,一种为直接连接网络打印机打印
一、通过tomcat服务连接服务器所连接的打印机打印
手机或平板是一种移动设备,不可能直接打印机,所以要把打印的数据发给tomcat,通过服务器电脑打印
先定义一个javabean实体类,用来保存数据
public class FoodChoose implements Serializable{
int id;
String tablename;
String foodname;
int foodnum;//数量
int foodunitprice;//单价
public FoodChoose() {
super();
}
public FoodChoose(String tablename, String foodname, int foodnum,
int foodunitprice) {
super();
this.tablename = tablename;
this.foodname = foodname;
this.foodnum = foodnum;
this.foodunitprice = foodunitprice;
}
public FoodChoose(int id, String tablename, String foodname, int foodnum,
int foodunitprice) {
super();
this.id = id;
this.tablename = tablename;
this.foodname = foodname;
this.foodnum = foodnum;
this.foodunitprice = foodunitprice;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTablename() {
return tablename;
}
public void setTablename(String tablename) {
this.tablename = tablename;
}
public String getFoodname() {
return foodname;
}
public void setFoodname(String foodname) {
this.foodname = foodname;
}
public int getFoodnum() {
return foodnum;
}
public void setFoodnum(int foodnum) {
this.foodnum = foodnum;
}
public int getFoodunitprice() {
return foodunitprice;
}
public void setFoodunitprice(int foodunitprice) {
this.foodunitprice = foodunitprice;
}
@Override
public String toString() {
return "FoodChoose [id=" + id + ", tablename=" + tablename
+ ", foodname=" + foodname + ", foodnum=" + foodnum
+ ", foodunitprice=" + foodunitprice + "]";
}
再定义一个打印类Prient implements Printable,在这个类里实现打印格式调整,以及数据获取
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.util.List;
import vo.FoodChoose;
public class Prient implements Printable {
String tablename,places,total,receiveprice,change;
List lists;
int heightIndex;
public Prient(String tablename,String places,String total,String receiveprice,String change,List lists) {
System.out.println("Prient构造方法");
this.tablename = tablename;
this.places = places;
this.total = total;
this.receiveprice = receiveprice;
this.change = change;
this.lists = lists;
}
@Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
System.out.println("----print----");
heightIndex = -20;
if (page > 0) {
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(new Font("Default", Font.PLAIN, 14));
g2d.drawString("天龙餐饮(消费清单)", 50, 12);
g2d.setFont(new Font("Default", Font.PLAIN, 16));
g2d.drawString("台号:"+places+"-"+tablename, 52, 30);
g2d.setFont(new Font("Default", Font.PLAIN, 10));
g2d.drawString("流水号:123456"+" "+Content.getNowTime(), 30, 45);
g2d.setFont(new Font("Default", Font.PLAIN, 12));
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 55);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 58);
g2d.drawString("项目" + " "+"数量" + " "+"单价" + " "+"小计", 30, 70);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 80);
System.out.println("xxxxxxxxxxxxxxxxxxxxx");
for (FoodChoose f : lists) {
heightIndex = heightIndex+20;
System.out.println("lists大小="+lists.size());
System.out.println("aa打印菜名="+f.getFoodname());
double price = f.getFoodnum() * f.getFoodunitprice();//小计
if(f.getFoodname().length()==2){
g2d.drawString(f.getFoodname() + Content.two1+f.getFoodnum() + Content.two2+f.getFoodunitprice() + Content.two3+ price+"元", 30, 90+heightIndex);
}else if(f.getFoodname().length()==3){
g2d.drawString(f.getFoodname() + Content.three1+f.getFoodnum() + Content.three2+f.getFoodunitprice() + Content.three3+ price+"元", 30, 90+heightIndex);
}else if(f.getFoodname().length()==4){
g2d.drawString(f.getFoodname() + Content.four1+f.getFoodnum() + Content.four2+f.getFoodunitprice() + Content.four3+ price+"元", 30, 90+heightIndex);
}else if(f.getFoodname().length()==5){
g2d.drawString(f.getFoodname() + Content.five1+f.getFoodnum() + Content.five2+f.getFoodunitprice() + Content.five3+ price+"元", 30, 90+heightIndex);
}
}
// g2d.drawString("荷包蛋" + " "+"2" + " "+"1" + " "+"2元", 30, 90);
// g2d.drawString("鱼片粥" + " "+"2" + " "+"6" + " "+"12元", 30,110);
// g2d.drawString("白粥" + " "+"1" + " "+"2" + " "+"2元", 30, 130);
// g2d.drawString("黑椒牛肉" + " "+"1" + " "+"25" + " "+"25元", 30, 150);
// g2d.drawString("河鱼河虾煲" + " "+"1" + " "+"20" + " "+"20元", 30, 170);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 90+heightIndex+10);
g2d.drawString(" "+"总计: "+total, 30, 90+heightIndex+20);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 90+heightIndex+30);
g2d.drawString(" "+"收款: "+receiveprice, 30, 90+heightIndex+40);
g2d.drawString(" "+"找零: "+change, 30, 90+heightIndex+60);
g2d.drawString("服务员:" + "001"+" " + "收银员:" + "002", 30, 90+heightIndex+80);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 90+heightIndex+90);
g2d.drawString("- - - - - - - - - - - - - - - - - - - - - -", 30, 90+heightIndex+93);
g2d.drawString("欢迎光临,谢谢惠顾", 60, 90+heightIndex+113);
g2d.drawString("服务电话:13888888888", 50, 90+heightIndex+133);
System.out.println("mmmmmmmmmmmmmmmmmmmmmmmm");
return PAGE_EXISTS;
}
}
public static void print(String tablename,String places,String total,String receiveprice,String change,List lists){
System.out.println("Content.print");
// int height = 1000 + 3 * 15 + 20;
int height = 1000;
// 通俗理解就是书、文档
Book book = new Book();
// 打印格式
PageFormat pf = new PageFormat();
pf.setOrientation(PageFormat.PORTRAIT);
// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
Paper p = new Paper();
p.setSize(230, height);
p.setImageableArea(5, -20, 230, height + 20);
pf.setPaper(p);
// 把 PageFormat 和 Printable 添加到书中,组成一个页面
book.append(new Prient(tablename,places,total,receiveprice,change,lists), pf);
// 获取打印服务对象
PrinterJob job = PrinterJob.getPrinterJob();
job.setPageable(book);
try {
job.print();
System.out.println("开始打印");
} catch (PrinterException e) {
System.out.println("================打印出现异常");
}
}
第二种方法,直接连接网络打印机(需要该打印机支持网线连接),还要求手机或平板所连接的网必须和打印机处于同一个网络字段
String PRINTER_IP = "192.168.2.223";//网络打印要ip地址,端口用9100即可
先要设定一个打印工具类pos
public class Pos {
//定义编码方式
private static String encoding = null;
private Socket sock = null;
// 通过socket流进行读写
private OutputStream socketOut = null;
private OutputStreamWriter writer = null;
/**
* 初始化Pos实例
*
* @param ip 打印机IP
* @param port 打印机端口号
* @param encoding 编码
* @throws IOException
*/
public Pos(String ip, int port, String encoding) throws IOException {
sock = new Socket(ip, port);
socketOut = new DataOutputStream(sock.getOutputStream());
this.encoding = encoding;
writer = new OutputStreamWriter(socketOut, encoding);
}
/**
* 关闭IO流和Socket
*
* @throws IOException
*/
public void closeIOAndSocket() throws IOException {
writer.close();
socketOut.close();
sock.close();
}
/**
* 打印二维码
*
* @param qrData 二维码的内容
* @throws IOException
*/
public void qrCode(String qrData) throws IOException {
int moduleSize = 8;
int length = qrData.getBytes(encoding).length;
//打印二维码矩阵
writer.write(0x1D);// init
writer.write("(k");// adjust height of barcode
writer.write(length + 3); // pl
writer.write(0); // ph
writer.write(49); // cn
writer.write(80); // fn
writer.write(48); //
writer.write(qrData);
writer.write(0x1D);
writer.write("(k");
writer.write(3);
writer.write(0);
writer.write(49);
writer.write(69);
writer.write(48);
writer.write(0x1D);
writer.write("(k");
writer.write(3);
writer.write(0);
writer.write(49);
writer.write(67);
writer.write(moduleSize);
writer.write(0x1D);
writer.write("(k");
writer.write(3); // pl
writer.write(0); // ph
writer.write(49); // cn
writer.write(81); // fn
writer.write(48); // m
writer.flush();
}
/**
* 进纸并全部切割
*
* @return
* @throws IOException
*/
public void feedAndCut() throws IOException {
writer.write(0x1D);
writer.write(86);
writer.write(65);
// writer.write(0);
//切纸前走纸多少
writer.write(100);
writer.flush();
//另外一种切纸的方式
// byte[] bytes = {29, 86, 0};
// socketOut.write(bytes);
}
/**
* 打印换行
*
* @return length 需要打印的空行数
* @throws IOException
*/
public void printLine(int lineNum) throws IOException {
for (int i = 0; i < lineNum; i++) {
writer.write("\n");
}
writer.flush();
}
/**
* 打印换行(只换一行)
*
* @throws IOException
*/
public void printLine() throws IOException {
writer.write("\n");
writer.flush();
}
/**
* 打印空白(一个Tab的位置,约4个汉字)
*
* @param length 需要打印空白的长度,
* @throws IOException
*/
public void printTabSpace(int length) throws IOException {
for (int i = 0; i < length; i++) {
writer.write("\t");
}
writer.flush();
}
/**
* 打印空白(一个汉字的位置)
*
* @param length 需要打印空白的长度,
* @throws IOException
*/
public void printWordSpace(int length) throws IOException {
for (int i = 0; i < length; i++) {
writer.write(" ");
}
writer.flush();
}
/**
* 打印位置调整
*
* @param position 打印位置 0:居左(默认) 1:居中 2:居右
* @throws IOException
*/
public void printLocation(int position) throws IOException {
writer.write(0x1B);
writer.write(97);
writer.write(position);
writer.flush();
}
/**
* 绝对打印位置
*
* @throws IOException
*/
public void printLocation(int light, int weight) throws IOException {
writer.write(0x1B);
writer.write(0x24);
writer.write(light);
writer.write(weight);
writer.flush();
}
/**
* 打印文字
*
* @param text
* @throws IOException
*/
public void printText(String text) throws IOException {
String s = text;
byte[] content = s.getBytes("gbk");
socketOut.write(content);
socketOut.flush();
}
/**
* 新起一行,打印文字
*
* @param text
* @throws IOException
*/
public void printTextNewLine(String text) throws IOException {
//换行
writer.write("\n");
writer.flush();
String s = text;
byte[] content = s.getBytes("gbk");
socketOut.write(content);
socketOut.flush();
}
/**
* 初始化打印机
*
* @throws IOException
*/
public void initPos() throws IOException {
writer.write(0x1B);
writer.write(0x40);
writer.flush();
}
/**
* 加粗
*
* @param flag false为不加粗
* @return
* @throws IOException
*/
public void bold(boolean flag) throws IOException {
if (flag) {
//常规粗细
writer.write(0x1B);
writer.write(69);
writer.write(0xF);
writer.flush();
} else {
//加粗
writer.write(0x1B);
writer.write(69);
writer.write(0);
writer.flush();
}
}
下面就可以调用打印工具类pos实现网络打印
/**
* 直接连接网络打印机打印,不需要tomcat,暂时不用
*/
public void testPrint() {
System.out.println("测试打印");
// 开启一个子线程
new Thread() {
public void run() {
try {
pos = new Pos(Content.PRINTER_IP, 9100, "GBK"); // 第一个参数是打印机网口IP
// 初始化打印机
pos.initPos();
// 初始化订单数据
initData();
pos.bold(true);
pos.printTabSpace(2);//两个tab距离,一个tab=4个汉字
pos.printWordSpace(1);//一个汉字距离
pos.printText("**测试店铺");
pos.printLocation(0);//打印位置调整
pos.printTextNewLine("----------------------------------------");
pos.bold(false);
pos.printTextNewLine("订 单 号:1005199");
pos.printTextNewLine("用 户 名:15712937281");
pos.printTextNewLine("桌 号:3号桌");
pos.printTextNewLine("订单状态:订单已确认");
pos.printTextNewLine("订单日期:2016/2/19 12:34:53");
pos.printTextNewLine("付 款 人:线下支付(服务员:宝哥)");
pos.printTextNewLine("服 务 员:1001");
pos.printTextNewLine("订单备注:不要辣,少盐");
pos.printLine(2);
pos.printText("项目");
pos.printLocation(20, 1);
pos.printText("单价");
pos.printLocation(99, 1);
pos.printWordSpace(1);
pos.printText("数量");
pos.printWordSpace(3);
pos.printText("小计");
pos.printLocation(0);//打印位置调整
pos.printTextNewLine("----------------------------------------");
for (FoodChoose foods : foodChoose) {
pos.printTextNewLine(foods.getFoodname());
pos.printLocation(20, 1);
pos.printText(foods.getFoodunitprice()+"");
pos.printLocation(99, 1);
pos.printWordSpace(1);
pos.printText(foods.getFoodnum()+"");
pos.printWordSpace(3);
}
pos.printTextNewLine("----------------------------------------------");
//pos.printLocation(1);
//pos.printLine(2);
// 打印二维码
//pos.qrCode("http://blog.csdn.net/haovip123");
// 切纸
//pos.feedAndCut();
pos.closeIOAndSocket();
pos = null;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
private void initData() {
foodChoose = new ArrayList();
for (int i = 0; i < 4; i++) {
FoodChoose fb = new FoodChoose();
fb.setFoodname("测试菜品" + i);
fb.setFoodunitprice(90);
fb.setFoodnum(2);
foodChoose.add(fb);
}
}