title: Java PrintJob to DocPrintJob Not Working?
body: <p>I have a class that extends from Printable, it prints fine using the standard PrintJob, but i would like to move to DocPrintJob so i can listen to the status of the print (successful print etc).</p>
  
  <p>My current code looks like this to create a print job and print</p>
  
  <pre><code>// define printer
  AttributeSet attributes = new HashAttributeSet();
  attributes.add(new Copies(1));
  
  // get printerJob
  PrinterJob printJob = PrinterJob.getPrinterJob();
  PageFormat pageFormat = printJob.defaultPage();
  
  // sizing (standard is 72dpi, so multiple inches by this)
  Double height = 8d * 72d;
  Double width = 3d * 72d;
  Double margin = 0.1d * 72d;
  
  // set page size
  Paper paper = pageFormat.getPaper();
  
  paper.setSize(width, height);
  paper.setImageableArea(margin, margin, width - (margin * 2), height - (margin * 2));
  
  // set orientation and paper
  pageFormat.setOrientation(PageFormat.PORTRAIT);
  pageFormat.setPaper(paper);
  
  // create a book for printing
  Book book = new Book();
  book.append(new EventPrint(args.getEvent()), pageFormat);
  
  // set book to what we are printing
  printJob.setPageable(book);
  
  // set print request attributes
  PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
  aset.add(OrientationRequested.PORTRAIT);
  
  // now print
  try {
      printJob.print();
  } catch (PrinterException e) {
      e.printStackTrace();
  }   
  </code></pre>
  
  <p>Now to convert this to a DocPrintJob, i followed <a href="https://blog.idrsolutions.com/2010/02/java-printing-of-custom-swing-components/" rel="nofollow">this</a> link which told me how to convert from PrintJob to DocPrintJob.  So now my code became this</p>
  
  <pre><code>PrintService[] services = PrinterJob.lookupPrintServices(); //list of printers
  PrintService printService = services[0];
  DocFlavor[] flavours = printService.getSupportedDocFlavors();
  
  // may need to determine which printer to use
  DocPrintJob printJob = printService.createPrintJob();
  
  // get out printable
  EventPrint eventPrint = new EventPrint(args.getEvent());
  
  // convert printable to doc
  Doc doc = new SimpleDoc(eventPrint, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null);
  
  // add eventlistener to printJob
  printJob.addPrintJobListener(new PrintJobListener() {
  
      @Override
      public void printDataTransferCompleted(PrintJobEvent pje) {
          Console.Log("Print data sent successfully");
      }
  
      @Override
      public void printJobCompleted(PrintJobEvent pje) {
          Console.Log("Print successful");
      }
  
      @Override
      public void printJobFailed(PrintJobEvent pje) {
          Console.Log("Print failed");
      }
  
      @Override
      public void printJobCanceled(PrintJobEvent pje) {
          Console.Log("Print cancelled");                     
      }
  
      @Override
      public void printJobNoMoreEvents(PrintJobEvent pje) {
          Console.Log("No more printJob events");
      }
  
      @Override
      public void printJobRequiresAttention(PrintJobEvent pje) {
          Console.Log("printJob requires attention");                     
      }
  
  });
  
  PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
  aset.add(new Copies(1));
  
  try {
      printJob.print(doc, aset);
  } catch (Exception e) {
  
  }
  </code></pre>
  
  <p>Now for some reason, my print just keeps executing (400+ times until i close application).  I am not sure if it is because maybe i have not set the paper size, like i did when i was using PrintJob? Would that cause it?  If so, how can i set the paperSize of the DocPrintJob as it doesnt have the methods the normal printJob has?</p>
  
  <p>Anyone else faces this problem before?</p>
  
  <p>EDIT: Here is my eventPrint class and the class it inherits from</p>
  
  <p>PRINTABLEBASE.JAVA</p>
  
  <pre><code>public class PrintableBase {
  
      public Graphics2D g2d;
      public float x, y, imageHeight, imageWidth, maxY;
      public enum Alignment { LEFT, RIGHT, CENTER };
  
      public void printSetup(Graphics graphics, PageFormat pageFormat) {
          // user (0,0) is typically outside the imageable area, so we must translate
          // by the X and Y values in the pageFormat to avoid clipping
          g2d = (Graphics2D) graphics;
          g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
  
          // get starter X and Y
          x = 0;//(float)pageFormat.getImageableX();
  
          // do not offset vertical as pushes ticket down too much
          y = 0;//(float)pageFormat.getImageableY();
  
          // get height and width of the printable image
          imageWidth = (float)pageFormat.getImageableWidth();
          imageHeight = (float)pageFormat.getImageableHeight();
  
          // maximum that we can go vertically
          maxY = y;
  
          Console.Log("imageWidth:" + imageWidth);
          Console.Log("imageHeight: " + imageHeight);
          Console.Log("X: " + x);
          Console.Log("Y: " + y);
      }
  
      public void setFont(Font font) {
          g2d.setFont(font);
      }
  
      public float addSeparatorLine(float y, float imageWidth) {
          String fontName = g2d.getFont().getName();
          int fontStyle = g2d.getFont().getStyle();
          int fontSize = g2d.getFont().getSize();
  
          g2d.setFont(new Font("Arial", Font.PLAIN, 10));
  
          y = drawFirstLine(g2d, "---------------------------------------------------------------------------------------", imageWidth, 0, y, Alignment.LEFT);
  
          // revery font
          g2d.setFont(new Font(fontName, fontStyle, fontSize));
  
          return y + 5;
      }
  
      public BufferedImage scaleImage(BufferedImage sbi, int dWidth, int dHeight) {
          BufferedImage dbi = null;
          if(sbi != null) {
              // calculate ratio between standard size and scaled
              double wRatio = (double)dWidth / (double)sbi.getWidth();
              double hRatio = (double)dHeight / (double)sbi.getHeight();
  
              // use wRatio by default
              double sWidth = (double)sbi.getWidth() * wRatio;
              double sHeight = (double)sbi.getHeight() * wRatio;
  
              // if hRation is small, use that, as image will be reduced by more
              if (hRatio &lt; wRatio) {
                  sWidth = (double)sbi.getWidth() * hRatio;
                  sHeight = (double)sbi.getHeight() * hRatio;             
              }
  
              double sRatio = (wRatio &lt; hRatio) ? wRatio : hRatio;
  
              // now create graphic, of new size
              dbi = new BufferedImage((int)sWidth, (int)sHeight, BufferedImage.TYPE_INT_ARGB);
              Graphics2D g = dbi.createGraphics();
  
              AffineTransform at = AffineTransform.getScaleInstance(sRatio, sRatio);
              g.drawRenderedImage(sbi, at);
          }
          return dbi;
      }
  
      // This function will only add the first line of text and will not wrap
      // useful for adding the ticket title.  
      // Returns the height of the text
      public float drawFirstLine(Graphics2D g2, String text, float width, float x, float y, Alignment alignment) {
          AttributedString attstring = new AttributedString(text);
          attstring.addAttribute(TextAttribute.FONT, g2.getFont());
          AttributedCharacterIterator paragraph = attstring.getIterator();
          int paragraphStart = paragraph.getBeginIndex();
          int paragraphEnd = paragraph.getEndIndex();
          FontRenderContext frc = g2.getFontRenderContext();
          LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
  
          // Set break width to width of Component.
          float breakWidth = width;
          float drawPosY = y;
          // Set position to the index of the first character in the paragraph.
          lineMeasurer.setPosition(paragraphStart);
  
          // Get lines until the entire paragraph has been displayed.
          if (lineMeasurer.getPosition() &lt; paragraphEnd) {
              // Retrieve next layout. A cleverer program would also cache
              // these layouts until the component is re-sized.
              TextLayout layout = lineMeasurer.nextLayout(breakWidth);
              // Compute pen x position. 
              float drawPosX;
  
              switch (alignment){         
                  case RIGHT:
                      drawPosX = (float) x + breakWidth - layout.getAdvance();
                      break;
                  case CENTER:
                      drawPosX = (float) x + (breakWidth - layout.getAdvance())/2;
                      break;
                  default: 
                      drawPosX = (float) x;
              }
              // Move y-coordinate by the ascent of the layout.
              drawPosY += layout.getAscent();
  
              // Draw the TextLayout at (drawPosX, drawPosY).
              layout.draw(g2, drawPosX, drawPosY);
  
              // Move y-coordinate in preparation for next layout.
              drawPosY += layout.getDescent() + layout.getLeading();
          }
          return drawPosY;
      }
  
      /**
       * Draw paragraph.
       *
       * @param g2 Drawing graphic.
       * @param text String to draw.
       * @param width Paragraph's desired width.
       * @param x Start paragraph's X-Position.
       * @param y Start paragraph's Y-Position.
       * @param dir Paragraph's alignment.
       * @return Next line Y-position to write to.
       */
      protected float drawParagraph (String text, float width, float x, float y, Alignment alignment){
          AttributedString attstring = new AttributedString(text);
          attstring.addAttribute(TextAttribute.FONT, g2d.getFont());
          AttributedCharacterIterator paragraph = attstring.getIterator();
          int paragraphStart = paragraph.getBeginIndex();
          int paragraphEnd = paragraph.getEndIndex();
          FontRenderContext frc = g2d.getFontRenderContext();
          LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
  
          // Set break width to width of Component.
          float breakWidth = width;
          float drawPosY = y;
          // Set position to the index of the first character in the paragraph.
          lineMeasurer.setPosition(paragraphStart);
  
          // Get lines until the entire paragraph has been displayed.
          while (lineMeasurer.getPosition() &lt; paragraphEnd) {
              // Retrieve next layout. A cleverer program would also cache
              // these layouts until the component is re-sized.
              TextLayout layout = lineMeasurer.nextLayout(breakWidth);
              // Compute pen x position. 
              float drawPosX;
              switch (alignment){         
                  case RIGHT:
                      drawPosX = (float) x + breakWidth - layout.getAdvance();
                      break;
                  case CENTER:
                      drawPosX = (float) x + (breakWidth - layout.getAdvance())/2;
                      break;
                  default: 
                      drawPosX = (float) x;
              }
              // Move y-coordinate by the ascent of the layout.
              drawPosY += layout.getAscent();
  
              // Draw the TextLayout at (drawPosX, drawPosY).
              layout.draw(g2d, drawPosX, drawPosY);
  
              // Move y-coordinate in preparation for next layout.
              drawPosY += layout.getDescent() + layout.getLeading();
          }
          return drawPosY;
      }
  
  }
  </code></pre>
  
  <p>EVENTPRINT.JAVA</p>
  
  <pre><code>public class EventPrint extends PrintableBase implements Printable {
  
      private Event event;
  
      public EventPrint(Event event) {
          this.event = event; 
      }
  
      @Override
      public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
              throws PrinterException {
  
          // setup
          super.printSetup(graphics, pageFormat);
  
          // title
          super.setFont(new Font("Tahoma", Font.BOLD, 16));
          y = super.drawParagraph(event.getTitle(), imageWidth, x, y, Alignment.LEFT);
  
      RETURN PAGE_EXISTS;                 
  }
  </code></pre>