You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何获取printDataTransferCompleted等打印状态?现有代码无返回值求解决

解决Java打印PDF无法获取完整打印状态的问题

你的代码存在两个核心问题,导致无法捕获printDataTransferCompleted、printJobCompleted等状态:

  1. 实际执行打印的是PrinterJob,但监听器绑定到了后续创建的DocPrintJob上——这是两个完全独立的打印任务,监听器根本无法捕获前者的状态。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:45:19