6

我在使用 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 监听作业状态呢?

4

2 回答 2

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);
于 2014-11-20T14:50:13.870 回答
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();
于 2020-01-05T11:42:13.363 回答