Java中如何获取printDataTransferCompleted等打印状态?现有代码无返回值求解决
解决Java打印PDF无法获取完整打印状态的问题
你的代码存在两个核心问题,导致无法捕获printDataTransferCompleted、printJobCompleted等状态:
- 实际执行打印的是
PrinterJob,但监听器绑定到了后续创建的DocPrintJob上——这是两个完全独立的打印任务,监听器根本无法捕获前者的状态。 job.print()是阻塞方法,会等到打印完成(或失败、取消)才会执行后续代码,此时再添加监听器已经完全错过所有事件。
正确实现方式(推荐用DocPrintJob)
DocPrintJob支持通过PrintJobListener监听完整的打印生命周期事件,关键是先绑定监听器,再提交打印任务。
第一步:实现完整的PrintJobListener
import javax.print.event.PrintJobEvent; import javax.print.event.PrintJobListener; public class PrintJobListenerSample implements PrintJobListener { @Override public void printDataTransferCompleted(PrintJobEvent pje) { System.out.println("打印数据传输完成"); } @Override public void printJobCompleted(PrintJobEvent pje) { System.out.println("打印任务完成"); // 可在此处关闭PDF文档等资源 } @Override public void printJobFailed(PrintJobEvent pje) { System.out.println("打印任务失败"); // 处理失败逻辑,关闭资源 } @Override public void printJobCanceled(PrintJobEvent pje) { System.out.println("打印任务被取消"); } @Override public void printJobNoMoreEvents(PrintJobEvent pje) { System.out.println("无更多打印状态事件"); } @Override public void printJobRequiresAttention(PrintJobEvent pje) { System.out.println("打印任务需要人工干预(如缺纸、卡纸)"); } }
第二步:修改打印逻辑,绑定监听器后再提交任务
import org.apache.pdfbox.pdmodel.PDDocument; import javax.print.*; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; public class PdfPrinter { public static void main(String[] args) { try { // 加载PDF文档 File pdfFile = new File("D:\\Rose\\Work\\17.pdf"); PDDocument document = PDDocument.load(pdfFile); // 查找目标打印机 PrintService targetPrinter = findPrintService("Champ RP Series"); if (targetPrinter == null) { System.out.println("未找到指定打印机"); document.close(); return; } // 构建打印用的Doc对象 DocFlavor pdfFlavor = DocFlavor.INPUT_STREAM.PDF; Doc printDoc = new SimpleDoc(new FileInputStream(pdfFile), pdfFlavor, null); // 创建打印任务并绑定监听器 DocPrintJob printJob = targetPrinter.createPrintJob(); printJob.addPrintJobListener(new PrintJobListenerSample() { // 在这里重写方法,直接处理当前任务的资源关闭 @Override public void printJobCompleted(PrintJobEvent pje) { super.printJobCompleted(pje); try { document.close(); } catch (Exception e) { e.printStackTrace(); } } @Override public void printJobFailed(PrintJobEvent pje) { super.printJobFailed(pje); try { document.close(); } catch (Exception e) { e.printStackTrace(); } } }); // 设置打印属性(可选:打印份数、纸张大小等) PrintRequestAttributeSet printAttrs = new HashPrintRequestAttributeSet(); // printAttrs.add(new Copies(2)); // 示例:打印2份 // 提交打印任务(非阻塞,后台执行) printJob.print(printDoc, printAttrs); } catch (FileNotFoundException | PrintException e) { e.printStackTrace(); } } // 根据名称查找打印机服务 private static PrintService findPrintService(String printerName) { PrintService[] allPrinters = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService printer : allPrinters) { if (printer.getName().equals(printerName)) { return printer; } } return null; } }
关键注意事项
- 监听器必须在打印前绑定:如果先调用
print()再添加监听器,会错过所有初始化、数据传输类事件。 - 不要提前关闭资源:PDF文档、输入流必须保持打开直到打印完成/失败,否则会导致打印中断或失败,建议在监听器的完成/失败事件中关闭。
DocPrintJob.print()是非阻塞的:调用后会立即返回,打印过程在后台线程执行,状态事件通过监听器异步通知。
内容的提问来源于stack exchange,提问作者user16514999
相关产品推荐
相关产品推荐

