以下是关于 Java 如何调用打印机 的完整技术指南,涵盖原理、实现步骤、代码示例及常见问题解决方案:
核心机制
Java 通过 javax.print
包提供标准化打印接口,其底层依赖操作系统原生打印服务(CUPS/Windows Print Spooler),主要流程包含以下关键环节:
- 发现打印机 → 2. 获取打印服务对象 → 3. 创建打印作业 → 4. 构建打印数据流 → 5. 提交打印任务
核心组件 | 作用说明 |
---|---|
PrintServiceLookup |
枚举系统中所有可用打印机 |
PrintService |
表示单个打印机的服务接口 |
DocFlavor |
定义打印数据的格式(如TEXT/HTML/IMAGE) |
PrintJob |
管理具体打印任务的生命周期 |
AttributeSet |
控制纸张大小、边距、份数等打印参数 |
分步实现详解
✅ 第一步:获取打印机列表
import javax.print.; import javax.print.attribute.standard.; import java.util.; public class PrinterUtil { // 获取所有已安装的打印机名称列表 public static List<String> listAllPrinters() { List<String> printerNames = new ArrayList<>(); PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService service : services) { printerNames.add(service.getName()); } return printerNames; } }
⚠️ 注意:若返回空数组,需确认系统已安装物理/虚拟打印机且未禁用后台打印服务。
✅ 第二步:选择目标打印机并创建打印作业
// 根据名称精确匹配打印机(区分大小写) private static PrintService findPrinter(String name) throws PrinterException { PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService service : services) { if (service.getName().equalsIgnoreCase(name)) { return service; } } throw new PrinterException("未找到打印机: " + name); } // 创建打印作业对象 PrintJob job = service.createPrintJob();
✅ 第三步:配置打印属性(关键!)
// 设置纸张为A4横向 HashPrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet(); attrs.add(MediaSizeName.ISO_A4); // 纸张尺寸 attrs.add(OrientationRequested.LANDSCAPE); // 横向布局 attrs.add(new Copies(2)); // 打印两份 attrs.add(Chromaticity.COLOR); // 彩色打印
👉 常用属性对照表:
| 需求 | 对应属性类及常量 |
|——————–|——————————————|
| 单面/双面 | Sides.ONE_SIDED / Sides.DUPLEX |
| 纵向/横向 | Portrait / Landscape |
| 纸张厚度 | MediaTray.THICK |
| 缩放至适合页面 | ScalingFactor.SCALE_TO_FIT |
| 页边距调整 | MarginType. (需配合自定义边距值) |
✅ 第四步:构建打印数据流(重点!)
根据 DocFlavor
类型选择不同的数据构造方式:
数据类型 | 典型用途 | 实现方式 |
---|---|---|
STRING |
纯文本打印 | new SimpleDoc(textContent, flavor, null) |
URL |
网页/图片打印 | new SimpleDoc(new URL("http://example.com"), flavor, null) |
BufferedImage |
图像打印 | new SimpleDoc(image, flavor, null) |
InputStream |
PDF/PS文件打印 | new SimpleDoc(inputStream, flavor, null) |
PRINTABLE |
自定义组件打印 | 继承JComponent 重写paint() 方法 |
示例:打印富文本内容
// 支持HTML格式的打印(需安装支持PCL6/PostScript的打印机) DocFlavor flavor = DocFlavor.BYTE_ARRAY.TEXT; // 部分打印机需改用PDF风味 byte[] bytes = docContent.getBytes(StandardCharsets.UTF_8); Doc doc = new SimpleDoc(bytes, flavor, null);
✅ 第五步:提交打印任务
try { job.print(doc, attrs); // 异步打印(立即返回) // job.print(doc, attrs, true); // 同步阻塞直到完成 } catch (PrintException e) { System.err.println("打印失败: " + e.getMessage()); } finally { job.cancel(); // 可选:取消未完成的打印队列 }
完整代码示例:打印测试页
import javax.print.; import javax.print.attribute.; import javax.print.attribute.standard.; import java.awt.; import java.awt.print.; import java.io.; public class PrintDemo { public static void main(String[] args) { try { // 1. 获取默认打印机 PrintService defaultPrinter = PrintServiceLookup.lookupDefaultPrintService(); if (defaultPrinter == null) { throw new IllegalStateException("未检测到默认打印机"); } // 2. 创建自定义打印内容(可替换为任意Component) JPanel panel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("Hello Java Print!", 50, 50); g.fillRect(100, 100, 200, 100); } }; // 3. 包装成Printable对象 Printable printable = new Printable() { @Override public int print(Graphics g, PageFormat pageFormat, int pageIndex) { if (pageIndex > 0) return NO_SUCH_PAGE; // 仅第一页有效 g.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); panel.print(g); return PAGE_EXISTS; } }; // 4. 创建打印作业并设置属性 PrintJob job = defaultPrinter.createPrintJob(); HashPrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet(); attrs.add(MediaSizeName.ISO_A4); attrs.add(OrientationRequested.PORTRAIT); attrs.add(new Copies(1)); // 5. 执行打印 job.print(new SimpleDoc(printable, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null), attrs); System.out.println("打印任务已提交"); } catch (Exception e) { e.printStackTrace(); } } }
高级技巧与注意事项
🔧 动态页眉页脚实现
public class WatermarkPrint implements Printable { private String watermarkText; public WatermarkPrint(String text) { this.watermarkText = text; } @Override public int print(Graphics g, PageFormat pf, int page) { if (page != 0) return NO_SUCH_PAGE; // 绘制半透明水印 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); g.setComposite(ac); g.setColor(Color.BLUE); g.drawString(watermarkText, pf.getWidth()/2, pf.getHeight()/2); return PAGE_EXISTS; } }
⚠️ 常见问题排查清单
现象 | 可能原因及解决方案 |
---|---|
打印机无响应 | 检查USB连接线/网络状态;重启打印服务;尝试更换USB端口 |
文字显示方框乱码 | 确保使用UTF-8 编码;尝试切换DocFlavor 为URL 类型 |
图片缺失 | 确认图像格式受打印机支持(推荐PNG/JPEG);检查内存不足导致截断 |
多页文档只打印第一页 | 在print() 方法中正确处理分页逻辑;设置Bookmark 标记分割章节 |
彩色输出变为黑白 | 检查打印机墨盒状态;在属性集中添加Chromaticity.COLOR |
相关问答FAQs
Q1: 如何解决“No suitable printer found”异常?
A: 此错误通常由以下原因导致:① 指定的DocFlavor
不被目标打印机支持;② 打印机未正确安装,解决方案:① 通过listAllPrinters()
查看实际支持的打印机列表;② 尝试修改DocFlavor
为通用类型(如DocFlavor.BYTE_ARRAY.AUTOSENSE
);③ 确保打印机处于在线状态。
Q2: 如何实现静音模式打印(不弹出对话框)?
A: 默认情况下Java会调用操作系统的标准打印对话框,如需静默打印,需满足两个条件:① 打印机已设为默认打印机;② 在代码中显式指定所有打印参数(如纸张大小、份数等),避免触发系统弹窗,示例:
// 强制使用默认打印机且不弹窗 PrintService service = PrintServiceLookup.lookupDefaultPrintService(); if (service instanceof StreamPrintService) { StreamPrintService sps = (StreamPrintService) service; OutputStream os = sps.getPrintOutputStream(attrs); // 直接获取输出流 // 向os写入数据后记得flush()和close() } else { throw new UnsupportedOperationException("该打印机不支持静默
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/94608.html