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