Aumentar tamnho da área imprimível MediaPrintableArea

Olá, pessoal!

Estou com um problema: estou imprimindo num formulário contínuo tipo FOLIO (8.5"x13") e funciona corretamente. Porém o que não consigo fazer funcionar corretamente é o tamanho da página e área imprimível. Se “seto” o tamanho da página como FOLIO, não consigo usar toda a página para imprimir(não consigo imprimir no finalzinho da página, não chega a zero ou perto disso) pq mesmo “setando” a área imprimível do tamanho da página, a área imprimível não passa de um limite. Se eu aumento o tamanho da página, aí sim consigo aumentar a área imprimível e fazer imprimir na região que gostaria mas aí a segunda página vai imprimir errado porque a primeira página estourou o tamanho dela (com certeza não é o modo correto).

Eu gostaria de saber senão dá pra criar um tipo de página personalizado onde poderia “setar” o tamanho da área imprimível que eu quisesse sem ter de aumentar o tamanho da página (8.5"x13").

O código que estou utilizando para imprimir é este:

[code]PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();

aset.add(OrientationRequested.PORTRAIT);

MediaSizeName msn = MediaSize.Other.FOLIO.getMediaSizeName(); // tamnho: 8.5"x13" ou 220mmx33mm

aset.add(new MediaPrintableArea(0, 0, 220, 330,MediaPrintableArea.MM)); //Seta tamanho total da página

aset.add(msn);

PrinterJob pjob = PrinterJob.getPrinterJob();

PrintService[] ps = PrinterJob.lookupPrintServices();

for(int i=0; i<ps.length; i++){
if(ps[i].equals(“Win32 Printer : Epson FX-1170”)){

	pjob.setPrintService(ps[i]); //indice da epson FX-1170
				
}

}

pjob.setJobName(“Nota Fiscal”);

pjob.setCopies(1);

pjob.setPrintable(new PrintContext());

pjob.print(aset); //Imprime[/code]

Agradeço desde já!

Pestana

Olá

Esta é uma pergunta interessante porque toca no raro assunto impressão com Java que é uma área onde a Sun só faz merda. Desde as versões iniciais do Java o modo de imprimir já mudou várias vezes e ainda continua ruim, confuso e mal documentado.

Suspeito que seu problema seja que as margens não estão zeradas e estão roubando espaço da impressão.

Para mexer na área a imprimir há desde o j2sdk1.3 as classes Paper e PageFormat que permitem definir as margens e o tamanho da área a ser impressa no papel.

Abaixo mostro um exemplo um pouco diferente do seu em que eu zero as margens com paper.setImageableArea(0.0, 0.0, width, height);. Só sei definir isto usando um Book :

   // Converte mm em pontos considerando 72 pontos por polegada
   public static double fatorConverMMPt = 2.834646D; 
   . . . . . . . .
    PrinterJob printerJob = PrinterJob.getPrinterJob();
    Book book = new Book();
    PageFormat pageFormat = new PageFormat();
    //pageFormat = printJob.pageDialog(pageFormat);
    Paper paper = new Paper();
    // Papel A4
    // 8,5 pol.
    double width  = 215.9 * fatorConverMMPt;
    // 13 pol.
    double height = 330.2 * fatorConverMMPt;
    paper.setSize(width, height);
    paper.setImageableArea(0.0, 0.0, width, height);
    pageFormat.setPaper(paper);
. . . . . . . . . . . 
. . . . . . . . . . .
     // A Classe interna abaixo implementa Printable e ImageObserver e imprime com drawString
     book.append(new ClasseInternaQueRealmenteImprime(parm1, parm1, parmN), pageFormat);
. . . . . . . . . . . 
. . . . . . . . . . .
    // Liga o book com printJob
    printerJob.setPageable(book);
    PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
    
    /* Poderia fazer assim:
     * PrintService[] services = printerJob.lookupPrintServices()
     * e não usar flavor
     */
    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
    PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, pras);
    
    PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
    PrintService service = ServiceUI.printDialog(null, 200, 200, services, defaultService, flavor, pras);     
   // Mostra o diálogo de impressão
    // Prossegue se o usuário clicar em imprimir ou então cancela
    if (printerJob.printDialog(pras)) {
      try {
        printerJob.print(pras);
      } catch (Exception printException) {
        printException.printStackTrace();
      }
    }


  // Member class que acessa todos os campos a imprimir
  private class ClasseInternaQueRealmenteImprime implements Printable, ImageObserver {
 
    // toggle é uma gambiarra para evitar que passe 2 vezes pelo método de impressão
    // ver também o fórum Sun:
    // http://forum.java.sun.com/thread.jspa?forumID=57&threadID=500687
    private boolean toggle = true;
  
    // Caso imprima imagem precisa implementar ImageObserver para poder usar drawImage
    // Todo Component implementa ImageObserver. Examinei o código fonte de Component e julquei (???) que
    // se imageUpdate que é quem implementa ImageObserver  
    // apenas retornar true em imageUpdate tudo deve funcionar. 
    public boolean imageUpdate(Image img, int infoflags,
	       int x, int y, int w, int h) {

      return true;
    }
    
    public ClasseInternaQueRealmenteImprime(parm1, parm1, parmN) {
 . . . . . . .     
    }
    
    public int print(Graphics g, PageFormat pf, int pageIndex) {
      if (pageIndex < numPags) {
         
        Graphics2D g2d = (Graphics2D) g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());
        Font font = new Font("Arial Narrow", Font.PLAIN, 8);
        g2d.setFont(font);
        
        // Imprimir         
        // Chamar o método que realmente imprime com drawString e drawImage
        return (PAGE_EXISTS);
        
      } else {
        
        return (NO_SUCH_PAGE);
      }
    }
  }  

}

Veja JavaWorld Printing in Java 1-5, Java Print Service API User Guide (Alpha Draft 0.1) e tudo o mais que vc conseguir achar sobre impressão em Java (que é muito pouco).

[]s
Luca

Luca,

Muito obrigado!

Conseguí zerar as margens e verifiquei que o tamanho imprimível agora é o mesmo que o tamanho da página.

Só uma coisa: depois que a primeira página é impressa, a impressora desce mais 1 polegada e a próxima página começa daí…Estranho pq conferí o tamanho. Tanto que se coloco 12 polegadas como tamanho do papel, nem chega a imprimir tudo.

A única coisa diferente do se código é que já mando pra impressora sem diálogo com o usuário:

ao invés de:

if (printerJob.printDialog(pras)) { try { printerJob.print(pras); } catch (Exception printException) { printException.printStackTrace(); } }

faço:

A seguir, como ficou meu código:

Book book = new Book();
PageFormat pageFormat = new PageFormat();
		    
Paper paper = new Paper();
// Papel FOLIO
// 8,5 pol.
double width  = 215.9 * fatorConverMMPt;
// 13 pol.
double height = 330.2 * fatorConverMMPt;
paper.setSize(width, height);
paper.setImageableArea(0.0, 0.0, width, height);
pageFormat.setPaper(paper);
		    
book.append(new PrintContext(), pageFormat);

PrinterJob pjob = PrinterJob.getPrinterJob();

pjob.setJobName("Nota Fiscal");
pjob.setCopies(1);

pjob.setPageable(book);
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
		    
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, pras);

PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
		    
pjob.print(pras);

Por que será que pula mais uma polegada?

Se alguém souber como fazer a impressora voltar, também ajudaria(sei que não é o correto mas ajuda).

Obrigado novamente!

Pestana

Olá

Talvez a impressora não esteja entendendo direito o seu tamanho de papel FOLIO 8.5" x 13". É possível fazer testes fora do Java? Quando você abre um documento em um programa qualquer e vai em Configurar Página aparece este tamanho para esta impressora?

[]s
Luca

Não aparece…e agora?

[]´s

Pestana

Olá

O fato da impressora não mostrar o tamanho pode não ser problema. Há classes e métodos na API de impressão que permitem que vc veja as margens e o tamanho da área a ser impressa. Exemplo de conferência das margens:

    double topMargin;
    double leftMargin;
    topMargin = (pageFormat.getHeight() - pageFormat.getImageableHeight()) / 2.0D;
    leftMargin = (pageFormat.getWidth() - pageFormat.getImageableWidth()) / 2.0D;
// E então vc imprime topMargin e leftMargin com seu logger favorito

Verifique também com um log as coordenadas (em pontos) onde vc está mandando imprimir. Pode ser que alguma linha (em branco) esteja sendo impressa uma polegada depois do fim da página.

[]s
Luca

Caros amigos. Estou com problema em zerar a margem da impressão. Segui o código de vcs. Porém não deu certo.

	[/code]
               double fatorConverMMPt = 2.834646D; 
	    PrinterJob printerJob = PrinterJob.getPrinterJob();  
	    Book book = new Book(); 
	    PageFormat pageFormat = new PageFormat(); 
	    Paper paper = new Paper(); 
	    double width  = getLayoutEtiquetaVO().getLarguraFolhaImpressao() * fatorConverMMPt;
	    double height = getLayoutEtiquetaVO().getAlturaFolhaImpressao() * fatorConverMMPt;
	    paper.setSize(width, height);
	    paper.setImageableArea(0.0, 0.0, width, height);
	    pageFormat.setPaper(paper);  
	    book.append(new MyPrintable(imagemFolha), pageFormat);
	    printerJob.setPageable(book);
	    PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
               printerJob.printDialog(pras);

[code]
o que estou fazendo de errrado?

Descobri que para vc poder setar margens pequenas, necessita saber qual impressora vc está trabalhando, pois o driver da impressora já tem um valor minimo para margens, não deixando imprimir margens menores que a padrão do driver.

E ae, sofri um pouco para imprimir pdf no java, segue o cógido…

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
import com.sun.pdfview.PDFRenderer;

/**
 * Converts the PDF content into printable format
 */
public class PrintPdf {

    private PrinterJob pjob = null;

    public static void main(String[] args) throws IOException, PrinterException {
// Create a PDFFile from a File reference
        FileInputStream fis = new FileInputStream("/root/PDF/teste.pdf");
        PrintPdf printPDFFile = new PrintPdf(fis, "Test Print PDF");
        printPDFFile.print();
    }

    /**
     * Constructs the print job based on the input stream
     * 
     * @param inputStream
     * @param jobName
     * @throws IOException
     * @throws PrinterException
     */
    public PrintPdf(InputStream inputStream, String jobName) throws IOException, PrinterException {

        byte[] pdfContent = new byte[inputStream.available()];
        inputStream.read(pdfContent, 0, inputStream.available());
        initialize(pdfContent, jobName);

    }

    /**
     * Constructs the print job based on the byte array content
     * 
     * @param content
     * @param jobName
     * @throws IOException
     * @throws PrinterException
     */

    public PrintPdf(byte[] content, String jobName) throws IOException, PrinterException {
        initialize(content, jobName);
    }

    /**
     * Initializes the job
     * 
     * @param pdfContent
     * @param jobName
     * @throws IOException
     * @throws PrinterException
     */
    private void initialize(byte[] pdfContent, String jobName) throws IOException, PrinterException {
        ByteBuffer bb = ByteBuffer.wrap(pdfContent);
// Create PDF Print Page
        PDFFile pdfFile = new PDFFile(bb);
        PDFPrintPage pages = new PDFPrintPage(pdfFile);

// Create Print Job
        pjob = PrinterJob.getPrinterJob();
        PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
//pjob.setJobName(jobName);
        Book book = new Book();
        book.append(pages, pf, pdfFile.getNumPages());
        pjob.setPageable(book);

// to remove margins
        Paper paper = new Paper();
        paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight());
        pf.setPaper(paper);
    }

    public void print() throws PrinterException {
// Send print job to default printer
        pjob.print();
    }
}

/**
 * Class that actually converts the PDF file into Printable format
 */
class PDFPrintPage implements Printable {

    private PDFFile file;

    PDFPrintPage(PDFFile file) {
        this.file = file;
    }

    public int print(Graphics g, PageFormat format, int index) throws PrinterException {
        int pagenum = index + 1;
        if ((pagenum >= 1) && (pagenum <= file.getNumPages())) {
            Graphics2D g2 = (Graphics2D) g;
            PDFPage page = file.getPage(pagenum);

// fit the PDFPage into the printing area
            Rectangle imageArea = new Rectangle((int) format.getImageableX(), (int) format.getImageableY(),
                    (int) format.getImageableWidth(), (int) format.getImageableHeight());
            g2.translate(0, 0);
            PDFRenderer pgs = new PDFRenderer(page, g2, imageArea, null, null);
            try {
                page.waitForFinish();
                pgs.run();
            } catch (InterruptedException ie) {
// nothing to do
            }
            return PAGE_EXISTS;
        } else {
            return NO_SUCH_PAGE;
        }
    }
}