PDF PrinterJob获取工作状态

时间:2014-11-14 05:11:44

标签: java pdf printing pdfrenderer

使用java打印PDF时遇到问题。我知道Java本身并不支持打印PDF,因为java没有PDF渲染器。所以为了解决这个问题,我使用的是PDFRenderer库,下面是一个用它打印的例子:

 File f = new File("myfile.pdf");
 FileInputStream fis = new FileInputStream(f);
 FileChannel fc = fis.getChannel();
 ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
 fc.size());
 PDFFile pdfFile = new PDFFile(bb); 
 PDFPrintPage pages = new PDFPrintPage(pdfFile);
 PrinterJob pjob = PrinterJob.getPrinterJob();
 PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
 pjob.setJobName(f.getName());
 pjob.setPrintService(mPrintService);
 Book book = new Book();
 book.append(pages, pf, pdfFile.getNumPages());
 pjob.setPageable(book);
 pjob.print();

它运行正常,但我需要一些方法来获取我的打印机作业的状态。我需要知道我的打印机工作何时完成,我可以启动另一个。 Java API与DocPrintJob和PrintJobListener有很好的解决方案,但我需要使用PrinterJob进行PDF打印。那么我怎么能像在DocPrintJob中那样从我的PrinterJob中听取工作状态呢?

2 个答案:

答案 0 :(得分:2)

javafx.print
Enum PrinterJob.JobStatus

java.lang.Object
java.lang.Enum<PrinterJob.JobStatus>
javafx.print.PrinterJob.JobStatus


public static PrinterJob.JobStatus[] values()
Returns an array containing the constants of this enum type, in the order they are declared. This method may be used to iterate over the constants as follows:
for (PrinterJob.JobStatus c : PrinterJob.JobStatus.values())
    System.out.println(c);

答案 1 :(得分:0)

对于在2020年在这里处理此问题的任何人,我发现了一种非常漂亮的方式来打印PDF文件,同时能够在不使用JavaFX的情况下监视打印作业-因为人们似乎不太愿意将JavaFX用于打印PDF文件,而且我也不喜欢对象节点打印,因为我认为很难将打印出来的图像看起来像普通文档一样……JavaFX似乎喜欢-基本上-屏幕截图的想法表单的一部分,然后将该快照渲染为图形,然后必须对其缩放以适合打印机,最终看起来有点怪异……而采用格式精美的HTML并通过PDF库进行打印真的很干净,而且速度很快。所以这是我发现的东西:

首先,我使用了这个免费的库,将我的HTML字符串渲染为PDF文件。这是该库的Maven源代码:

<dependency>
    <groupId>org.icepdf.os</groupId>
    <artifactId>icepdf-core</artifactId>
    <version>6.2.2</version>
</dependency>

这是我渲染PDF的代码:

        String docPath = "/Users/michael/Documents/JavaFile.pdf";
        String html = "<html>Any HTML Code you want, including embedded CSS for a really clean look</html>
        OutputStream outputStream = new FileOutputStream(docPath);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        renderer.layout();
        renderer.createPDF(outputStream);
        outputStream.close();

这是我打印PDF的类……虽然有点冗长,但是非常简单,它使用了很好的本机Java API(我使用的是1.8):

import javafx.application.Platform;
import javafx.scene.control.Label;
import java.io.*;
import javax.print.*;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;

public class PrintHandler {

    private void delay(int msec) {
        try {
            Thread.sleep(msec);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public PrintHandler (FileInputStream fis, Label statusLabel) {
        this.statusLabel = statusLabel;
        this.fis = fis;
    }
    private FileInputStream fis;
    private Label statusLabel;
    private String state;

    public void startPrintJob () {
        try {
            Platform.runLater(()->statusLabel.setText("PRINTING"));
            delay(5000);
            InputStream is = new BufferedInputStream(this.fis);
            DocFlavor flavor = DocFlavor.INPUT_STREAM.PDF;
            PrintService service = PrintServiceLookup.lookupDefaultPrintService();
            DocPrintJob printJob = service.createPrintJob();
            JobMonitor monitor = new JobMonitor();
            printJob.addPrintJobListener(monitor);
            Doc doc = new SimpleDoc(is, flavor, null);
            printJob.print(doc, null);
            monitor.waitForJobCompletion();
            is.close();
        } catch (PrintException | IOException e) {
            e.printStackTrace();
        }
    }

    private class JobMonitor extends PrintJobAdapter {
        private boolean notify = false;
        final int DATA_TRANSFERRED      = 10;
        final int JOB_COMPLETE          = 11;
        final int JOB_FAILED            = 12;
        final int JOB_CANCELED          = 13;
        final int JOB_NO_MORE_EVENTS    = 14;
        final int JOB_NEEDS_ATTENTION   = 15;

        private int status;
        @Override
        public void printDataTransferCompleted(PrintJobEvent pje) {
            status = DATA_TRANSFERRED;
            markAction();
        }
        @Override
        public void printJobCompleted(PrintJobEvent pje) {
            status = JOB_COMPLETE;
            markAction();
        }
        @Override
        public void printJobFailed(PrintJobEvent pje) {
            status = JOB_FAILED;
            markAction();
        }
        @Override
        public void printJobCanceled(PrintJobEvent pje) {
            status = JOB_CANCELED;
            markAction();
        }
        @Override
        public void printJobNoMoreEvents(PrintJobEvent pje) {
            status = JOB_NO_MORE_EVENTS;
            markAction();
        }
        @Override
        public void printJobRequiresAttention(PrintJobEvent pje) {
            status = JOB_NEEDS_ATTENTION;
            markAction();
        }
        private void markAction() {
            synchronized (JobMonitor.this) {
                notify = true;
                JobMonitor.this.notify();
            }
        }
        public synchronized void waitForJobCompletion() {
            Runnable runner = ()->{
                boolean keepRunning = true;
                while (keepRunning) {
                    try {
                        while (!notify) {
                            wait();
                        }
                        switch(this.status){
                            case DATA_TRANSFERRED:
                                state = "DATA_TRANSFERRED";
                                break;
                            case JOB_COMPLETE:
                                state = "JOB_FINISHED";
                                keepRunning = false;
                                break;
                            case JOB_FAILED:
                                state = "JOB_FAILED";
                                keepRunning = false;
                                break;
                            case JOB_CANCELED:
                                state = "JOB_CANCELED";
                                keepRunning = false;
                                break;
                            case JOB_NO_MORE_EVENTS:
                                state = "JOB_COMPLETE";
                                keepRunning = false;
                                break;
                            case JOB_NEEDS_ATTENTION:
                                state = "JOB_NEEDS_ATTENTION";
                                break;

                        }
                        Platform.runLater(()->statusLabel.setText(state));
                        delay(5000);
                        notify = false;
                    }
                    catch (InterruptedException e) {}
                }
                delay(5000);
                Platform.runLater(()->statusLabel.setText(""));
            };
            Thread monitor = new Thread(runner);
            monitor.start();
        }
    }
}

这是我调用类以打印和监视作业的方式:

FileInputStream fis = new FileInputStream(docPath);
Label jobStatus = new Label(); //Already in my AnchorPane but included here for clarity
new PrintHandler(fis,jobStatus).startPrintJob();