PDF PrinterJob получить статус работы

У меня есть проблема для печати PDF с использованием Java. Я знаю, что 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. Итак, как я могу прослушивать статус задания из моего PrinterJob, как это происходит в DocPrintJob?

1 ответ

Решение
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);

Для тех, кто сталкивается с этой проблемой здесь, в 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();
Другие вопросы по тегам