如何知道打印机的打印方法何时完成打印文件?

时间:2015-01-20 20:03:47

标签: java printing

我正在开发一个打印文件的JAVA程序。 我需要知道打印机何时完成打印文件,我发现这个简单的代码很有意思:

import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterStateReason;
import javax.print.attribute.standard.PrinterStateReasons;
import javax.print.attribute.standard.Severity;
import javax.print.event.*;
import java.awt.*;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.util.Set;

/**
 * PrintTest
 */
public class PrintTest implements PrintServiceAttributeListener,PrintJobListener,Doc, Printable, PrintJobAttributeListener {

  private static final transient String TEXT = "12345";

  public static void main(String[] args) {
    PrintTest test = new PrintTest();
    test.checkPrinters();
  }

  public void checkPrinters() {
    Thread newThread = new Thread(new Runnable() {
      public void run() {
    PrintService ps = PrinterJob.getPrinterJob().getPrintService();

    DocFlavor[] myFlavors = ps.getSupportedDocFlavors();
    ps.addPrintServiceAttributeListener(PrintTest.this);
    DocPrintJob docJob = ps.createPrintJob();
      docJob.addPrintJobAttributeListener(PrintTest.this, null);
    docJob.addPrintJobListener(PrintTest.this);
    try {
      docJob.print(PrintTest.this,null);
    }
    catch (PrintException e) {
      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }
    } });

    newThread.start();
    /**
    PrintServiceAttributeSet attSet = ps.getAttributes();
    PrinterStateReasons psr = ps.getAttribute(PrinterStateReasons.class);

    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }          */
  }

  public void attributeUpdate(PrintServiceAttributeEvent psae) {
    System.out.println(psae.getAttributes());
  }

  public void printDataTransferCompleted(PrintJobEvent pje) {
    System.out.println("Transfer completed");
  }

  public void printJobCompleted(PrintJobEvent pje) {
    System.out.println("Completed");
  }

  public void printJobFailed(PrintJobEvent pje) {
    System.out.println("Failed");
    PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }
  }

  public void printJobCanceled(PrintJobEvent pje) {
    System.out.println("Canceled");
  }

  public void printJobNoMoreEvents(PrintJobEvent pje) {
    System.out.println("No more events");
  }

  public void printJobRequiresAttention(PrintJobEvent pje) {
    System.out.println("Job requires attention");
    PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }
  }

  public DocFlavor getDocFlavor() {
    return DocFlavor.SERVICE_FORMATTED.PRINTABLE;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public Object getPrintData() throws IOException {
    return this;
  }

  public DocAttributeSet getAttributes() {
    return null;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public Reader getReaderForText() throws IOException {
    return null; //To change body of implemented methods use File | Settings | File Templates.
  }

  public InputStream getStreamForBytes() throws IOException {
    return null;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
    return pageIndex == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public void attributeUpdate(PrintJobAttributeEvent pjae) {
    System.out.println("Look out");
  }
}

所以,我感兴趣的方法是:

public void printJobCompleted(PrintJobEvent pje) {
    System.out.println("Completed");
  }

但它对我不起作用。问题是打印机不支持这种类型的代码。有人能告诉我一个支持这段代码的打印机型号吗?

3 个答案:

答案 0 :(得分:0)

查看示例代码here

您似乎需要实施PrintJobAdapter。相关位是:

package com.your.package;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;

public class DetermineThatPrintJobHasFinished {

    public static void main(String[] args) throws Exception {
       //...    see example in link

      // Locate the default print service for this environment.    
      PrintService service = PrintServiceLookup.lookupDefaultPrintService();

      // Create and return a PrintJob capable of handling data from    
      // any of the supported document flavors.    
      DocPrintJob printJob = service.createPrintJob();

      // register a listener to get notified when the job is complete    
      JobCompleteMonitor monitor = new JobCompleteMonitor();    
      printJob.addPrintJobListener(monitor);

      // Construct a SimpleDoc with the specified print data, doc flavor and doc attribute set.    
      Doc doc = new SimpleDoc(is, flavor, null);

      // Print a document with the specified job attributes.    
      printJob.print(doc, null);    
      monitor.waitForJobCompletion();

      is.close();
    }

    private static class JobCompleteMonitor extends PrintJobAdapter {   
        private boolean completed = false;

        @Override
        public void printJobCanceled(PrintJobEvent pje) {
            signalCompletion();
        }

        @Override
        public void printJobCompleted(PrintJobEvent pje) {
            signalCompletion();
        }

        @Override
        public void printJobFailed(PrintJobEvent pje) {
            signalCompletion();
        }

        @Override
        public void printJobNoMoreEvents(PrintJobEvent pje) {
            signalCompletion();
        }

        private void signalCompletion() {
           synchronized (JobCompleteMonitor.this) { 
               completed = true;    
               JobCompleteMonitor.this.notify();    
           }
        }

        public synchronized void waitForJobCompletion() {    
            try {
                while (!completed) {
                    wait();
                }
            } catch (InterruptedException e) {
            }
        }
    }
}

答案 1 :(得分:0)

效率不是最好的,但是您可以等到属性:'queued-job-count'等于零:

public final static void waitEndJobs(final PrintService printService) throws InterruptedException {

    int queue = 1;
    while (queue != 0) {
        final AttributeSet attributes = printService.getAttributes();
        final Attribute a = Arrays.stream(attributes.toArray())//
                .filter(o -> o.getName().equalsIgnoreCase("queued-job-count"))//
                .findFirst()//
                .orElse(null);
        queue = Integer.parseInt(attributes.get(a.getClass()).toString());
        Thread.sleep(5000);
    }
}

答案 2 :(得分:0)

就我而言,Rx或Project Reactor可以很好地帮助使用此旧的Java打印机api。我最近也遇到了这个问题,目前我已经完成了下一版本。也许会对某人有帮助

首先,如果您使用的是pdfbox,那么

from django.db import models

# Create your models here.
class Subscriber(models.Model):
    email = models.EmailField(max_length=75,)
    def __str__(self):
        return self.email

第二次,如果仅首选默认打印机API,则将打印方法替换为:

@Slf4j
@Service
@RequiredArgsConstructor
public class PrinterDeviceServiceImpl implements PrinterDeviceService {

    @Override
    public StreamEx<PrintService> getAvailablePrinters() {
        return of(PrintServiceLookup.lookupPrintServices(null, null));
    }

    @Override
    public boolean isPrinterExists(String printerName) {
        return getAvailablePrinters()
                .anyMatch(p -> p.getName().equals(printerName));
    }

    @Override
    public PrintService getPrinter(String printerName) {
        return getAvailablePrinters()
                .findFirst(p -> p.getName().equals(printerName))
                .orElse(null);
    }

    @Override
    public Mono<PrintTaskStatus> print(String printerName, InputStream source) {
        try {
            PrintService printer = getPrinter(printerName);
            if (printer == null) {
                return Mono.error(new RuntimeException("printer is null"));
            }

            PDDocument document = Unchecked.supplier(() -> PDDocument.load(source));

            PrinterJob job = PrinterJob.getPrinterJob();

            job.setPageable(new PDFPageable(document, Orientation.PORTRAIT));
            job.setPrintService(printer);

            Paper paper = new Paper();
            paper.setSize(500, 500); //TODO: lets get it from configs or task request
            paper.setImageableArea(0.0, 0.0, paper.getWidth(), paper.getHeight()); // no margins

            // custom page format
            PageFormat pageFormat = new PageFormat();
            pageFormat.setPaper(paper);

            Book book = new Book();

            book.append(new PDFPrintable(document), pageFormat, document.getNumberOfPages());
            job.setPageable(book);

            HashPrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
            attr.add(OrientationRequested.PORTRAIT);
            attr.add(PrintQuality.HIGH);
            job.print(attr);

            return Mono.create(sink -> {
                /*If exec thread is UI or from http pool, then maybe better idea is to attach it to another independent one or run print in another one!*/
                while (!isPrintCompleted(printer)) {
                    log.debug("I'm waiting to printer processed queue");
                    Unchecked.runnable(() -> Thread.sleep(1000));
                }
                /*you can wait some fixed or dynamic time based on how big your document etc and finish with error state if it needed*/
                log.debug("printer queue have processed :)");
                sink.success(PrintTaskStatus.Completed);
            });
        } catch (Throwable ex) {
            ExceptionHelpers.logError(ex, log);
            return Mono.just(PrintTaskStatus.Failed);
        }
    }

    private boolean isPrintCompleted(PrintService printer) {
        return Arrays.stream(printer.getAttributes().toArray())
                .filter(att -> att instanceof QueuedJobCount)
                .map(QueuedJobCount.class::cast)
                .findFirst()
                .map(queuedJobCount -> queuedJobCount.getValue() == 0)
                .orElse(false);
    }
}

祝你好运:)