Imprimindo com Java

Java 2D Print API e Java Printing Service
Uma visão geral das duas APIs de impressão do Java HERVAL FREIRE Em Java, o acesso aos recursos de impressão pode ser feito não por uma, mas por duas APIs complementares: a Java 2D Printing API ("Print API") e o Java Print Service (JPS). A Print API, teve sua primeira versão no JDK 1.1 e permite a manipulação e a impressão de textos e objetos gráficos. A JPS, que foi introduzida mais recentemente, no J2SE 1.4, traz facilidades para interação com filas de impressão inspirada no padrão Internet Printing Protocol (IPP). Inicialmente alvo de críticas por parte de muitos desenvolvedores devido às suas constantes mudanças desde a primeira versão, as APIs de impressão de Java hoje têm um bom grau de maturidade. A facilidade de utilizar a JPS para realizar tarefas como localizar e selecionar a impressora adequada ou imprimir arquivos fechados complementa a flexibilidade da Print API na formatação e organização de conteúdos gráficos para impressão. Este artigo apresenta uma visão geral dos vários recursos das duas APIs de impressão de Java, bem como ilustrar os seus modos de utilização mais comuns.
Dada a flexibilidade de utilização, é comum encontrar-se frameworks que abstraem particularidades da API para atividades específicas (como a impressão de relatórios, do popular JasperReports ou a geração de PDF do iText, por exemplo). Este artigo não cobre a utilização de tais frameworks.

Print API
A Print API utiliza o mecanismo de desenho do Java 2D. Através de um objeto do tipo Graphics (ou sua subclasse, Graphics2D. A Graphics2D costuma ser mais utilizada na manipulação de objetos geométricos e transformação de coordenadas. No restante deste artigo, faremos referência apenas à Graphics2D), a aplicação renderiza o conteúdo a ser impresso, da mesma forma que é feito para exibir o conteúdo em um componente visual na tela. Dessa forma, qualquer informação que possa ser criada para visualização na tela pode também ser impressa. Para realizar a impressão com a Print API, devemos cumprir quatro etapas: 1. Criar uma job (tarefa) de impressão, representada por um objeto PrinterJob. 2. Definir o conteúdo a ser impresso através dos métodos setPrintable() ou setPageable() do PrinterJob. 3. Opcionalmente, exibir um diálogo de configuração de impressão. 4. Iniciar o processo chamando print() do PrinterJob. Para que um objeto possa ser impresso, a sua classe deve implementar a interface Printable ou Pageable. Printable define um método de renderização print(), semelhante ao método paint() de componentes gráficos. A chamada a print() é feita pelo PrinterJob (como um callback), à medida que o sistema operacional solicita a impressão de páginas. A Tabela 1 resume os elementos da API.
Páginas simples com Printable

Conteúdos simples, como documentos de uma única página ou conjuntos de páginas sem variações de layout (tamanho de papel, orientação etc.) podem ser implementados utilizando a interface Printable. Quando requisitado para imprimir um objeto Printable, o sistema de impressão faz chamadas sucessivas ao método print() do objeto, informando ao objeto o índice da página a ser impressa (que começa em zero). Assim, um objeto Printable pode imprimir um número arbitrário de páginas.

Nada obriga a impressão a iniciar da primeira página e páginas não precisam ser impressas em seqüência. O objeto Printable tem que ser capaz de lidar com “saltos” na numeração de páginas, e também com páginas que sejam impressas várias vezes seguidas, sem passar para uma página seguinte.

A Listagem 1 demonstra a impressão de um objeto Printable simples, que renderiza uma página somente. Note que o método print() retorna uma constante Printable.NO_SUCH_PAGE para informar ao PrinterJob que não existem mais páginas subseqüentes, permitindo que sistema encerre a tarefa de impressão. A Print API também permite exibir um diálogo de configuração para o usuário, como a seguir:
// Obtém um printerJob PrinterJob job = PrinterJob.getPrinterJob(); // Exibe tela de configuração de pagina ao usuario PageFormat pf = job.pageDialog(job.defaultPage());

As preferências selecionadas são armazenadas em um objeto PageFormat, que pode então ser associado aos objetos Printable ou Pageable a serem impressos.
Documentos longos com Printable

Objetos Printable não dispõem de métodos para determinar o número de páginas a ser impresso. Caso se deseje indicar previamente a quantidade de páginas, por exemplo para impressão eficiente em ordem reversa, é necessário usar objetos do tipo Pageable. Pageable é voltada à gerência de documentos mais complexos, com uma quantidade prédefinida de páginas. Ela não define métodos de renderização de páginas. Cada página pode manter configurações próprias, em objetos PageFormat. Em linhas gerais, um objeto Pageable pode ser visto como um conjunto de objetos Printable de tamanho definido, um para cada página. A Print API inclui uma implementação concreta da interface Pageable, a classe Book, que atende aos requisitos da maior parte das aplicações que precisam imprimir documentos de várias páginas. A Listagem 2 demonstra a impressão de um documento de três páginas usando a classe Book. Antes do lançamento da JPS, o PrinterJob só era capaz de utilizar a impressora padrão do sistema, sendo necessário mostrar um diálogo do sistema operacional, para que o usuário escolhesse a impressora. Com a introdução do JPS, a seleção de impressoras via programação se torna possível graças a PrinterServiceLookup.

Manipulando imagens e textos
A impressão de imagens utilizando a Print API é simples: depois de se carregar a imagem, basta chamar o método drawImage() da classe Graphics2D para posicioná-la na página. A Listagem 3 demonstra todos os passos da impressão de uma imagem JPEG. A impressão e organização de textos é uma tarefa um pouco mais complexa. A classe LineBreakMeasurer permite manipular texto formatado e quebrar seu conteúdo em diversas linhas de largura definida. A quebra de sílabas é feita de acordo com as regras de internacionalização do locale em uso. Objetos TextLayout são utilizados para armazenar cada parágrafo (incluindo sua formatação), e para gerenciar a impressão de cada linha de texto no objeto Graphics2D.Cada objeto TextLayout armazena atributos de fonte, que podem ser utilizados para calcular o posicionamento do parágrafo e o espaçamento entre as linhas. A Figura 2, retirada do artigo “Printing in Java” (veja links) ilustra os atributos de fonte cobertos pela API. São eles: § Advance – distância entre o início de um bloco de texto e o final do último caractere. § Ascent – distância entre o ponto superior direito do texto e a sua baseline. § Baseline – linha de base do texto: uma posição relativa que depende da fonte em uso. § Descent – distância entre o baseline e o ponto inferior da linha de texto.

§ Leading – distância sugerida entre duas linhas utilizando-se uma determinada fonte, para que o texto seja legível. Todos esses atributos são acessíveis através de métodos getAtributo(), como getAdvance(), getBaseline(), etc. Além dos atributos de posicionamento, a formatação de outras características de um texto (como fonte, utilização de negrito ou itálico, etc) pode ser feita através do método addAttribute() da classe AttributedString.
// define a fonte de um AttributedString como Arial 12 AttributedString str = new AttributedString(“linha formatada”); str.addAttribute(TextAttribute.FONT, new Font("Arial", Font.ITALIC, 12));

É possível ainda formatar cada caractere de um AttributedString individualmente:
// define a fonte dos 3 primeiros caractered de um AttributedString como Arial 12 AttributedString str = new AttributedString(“linha mais ou menos formatada”); str.addAttribute(TextAttribute.FONT, new Font("Arial", Font.ITALIC, 12), 0, 3);

A Listagem 4 demonstra a utilização dos recursos para a impressão de texto formatado em múltiplas linhas. Uma vez criado um LineBreakMeasurer para o texto, solicita-se a impressão de cada parágrafo (chamando-se o método nextLayout()) até que não exista mais conteúdo a ser impresso. Cada parágrafo é instanciado como um objeto TextLayout. Observe que as classes LineBreakMeasurer e TextLayout não gerenciam a paginação de texto automaticamente. Fica por conta do desenvolvedor efetuar esta paginação da forma que convier à sua aplicação, verificando o espaço restante na página. Alguns frameworks mais “alto nível” que utilizam a Print API executam esta lógica de paginação de forma transparente (como é o caso do JasperReports e do iText, por exemplo).

Apresentando o Java Print Service
Apesar do modelo utilizado pela Print API ser bastante útil para impressão de conteúdos gráficos gerados pela aplicação, a Print API não fornece mecanismos para impressão de conteúdos streamed (como documentos PDF ou PostScript armazenados em arquivos, por exemplo). Com o JPS é usando um modelo de gerenciamento de conteúdo para impressão, que separa o mecanismo de impressão da API Java 2D (diferente da Print API, que depende diretamente da Java 2D para funcionar). Esta separação de conceitos da JPS foi sugerida para permitir que, em futuras implementações, a JPS possa ser utilizada em ambientes que não dispõem da API gráfica Java 2D – como em dispositivos J2ME, por exemplo. O mecanismo de impressão é gerenciado por um objeto DocPrintJob. Os objetos que representam documentos para impressão são representados pela interface Doc. Um Doc funciona como um tipo de “conversor de dados”, implementando métodos que são chamados pelo DocPrintJob para gerar a saída para a impressora. Tipos de documentos são identificados através de objetos DocFlavor, que representam um determinado tipo MIME de conteúdo – por exemplo, application/pdf, application/postscript e text/plain. A JPS inclui uma implementação da interface Doc, chamada SimpleDoc, capaz de manipular os tipos MIME mais conhecidos sem necessidade de implementações adicionais. O SimpleDoc simplesmente carrega o documento e o envia para impressão, deixando o tratamento do conteúdo a cargo do sistema operacional. Por exemplo, um sistema Windows é capaz de imprimir diretamente um documento Word, se o MS Office estiver instalado, enquanto um sistema Linux será capaz de imprimir diretamente documentos PostScript devido à integração do Ghostscript com os serviços de impressão do Linux. A definição de atributos de impressão, documentos e impressoras é feitas através de objetos AttributeSet. Há atributos específicos para formatação de documentos (DocAttributeSet), um job de impressão (PrintJobAttributeSet), requisições de impressão (i.e., um print job e todos os Docs associados a ele - PrintRequestAttributeSet) e impressora (PrintServiceAttributeSet).

Para cada tipo de AttributeSet, a JPS define muitos atributos de configuração. O pacote javax.print.attribute.standard inclui mais de 70 atributos, que permitem controlar desde a quantidade de cópias do documento até o nome que o processo deve receber na fila de impressão do sistema operacional. A utilização dos attribute sets é simples:
// Configura o conjunto de parametros para a impressora PrintRequestAttributeSet printerAttributes = new HashPrintRequestAttributeSet(); // Adiciona uma propriedade de impressão: imprimir 2 cópias printerAttributes.add(new Copies(2)); // Imprime o documento, utilizando o attribute set printJob.print(textDocument, printerAttributes);

A Tabela 2 resume alguns dos atributos disponíveis.

Descobrindo serviços de impressão
A localização de impressoras na JPS pode ser feita via programação. Além de escolher uma entre todas as impressoras disponíveis, é possível fazer uma filtragem de dispositivos segundo uma série de critérios – por exemplo, impressoras com suporte a cores somente:
// localiza apenas as impressoras com suporte a cores AttributeSet attributes = new HashAttributeSet(); attributes.add(Chromaticity.COLOR); PrintService[] pdfPrinters = PrintServiceLookup.lookupPrintServices(pdfFlavor, attributes);

O lookup (localização de impressoras) é feito através da classe PrintServiceLookup. A classe utiliza objetos DocFlavor para selecionar impressoras com suporte a tipos de documento específicos; também pode utilizar um conjunto de atributos, representado por um objeto PrintServiceAttributeSet. Os três métodos de localização são descritos na Tabela 3. Note que o serviço de localização da JPS pode ser usado também pela Print API sem dificuldades. A Listagem 7 mostra um exemplo de impressão utilizando a Print API, que localiza a impressora a ser utilizada através dos métodos de lookup da JPS.

Imprimindo conteúdo com a JPS
O processo de impressão com a JPS é tão simples quanto com a Print API. Uma vez definida a impressora, cria-se um objeto Doc e agenda-se a impressão através de um DocPrintJob. Veja um exemplo na Listagem 6. É usado um parâmetro para definir se o conteúdo será impresso usando os atributos definidos via programação ou se deverá ser exibida uma tela de configurações de impressão. No primeiro caso, o documento será enviado diretamente para a fila de impressão, sem confirmação por parte do usuário. Havendo a necessidade de se exibir um diálogo de configuração, pode-se fazê-lo através da classe ServiceUI (Figura 3), também do pacote javax.print. Ela permite ao usuário configurar a impressão, selecionar outra impressora e modificar o número de cópias, entre outras configurações. A Listagem 6 demonstra a utilização da ServiceUI.

Conclusões
As APIs de impressão do Java evoluíram juntamente com a linguagem, ganhando recursos e maturidade a cada release do JDK. Tratam-se de duas APIs bastante flexíveis e poderosas, que garantem ao desenvolvedor Java um alto grau de controle sobre a impressão de documentos dos mais variados tipos e formatos. Links
java.sun.com/products/java-media/2D/forDevelopers/sdk12print.html Tutorial sobre o Java 2D Printing API java.sun.com/j2se/1.4.2/docs/guide/jps Java Print Service User Guide javaworld.com/javaworld/jw-10-2000/jw-1020-print.html Printing in Java

jcp.org/en/jsr/detail?id=6 JSR-6 (Java Print Service) w3schools.com/media/media_mimeref.asp Sobre tipos MIME Herval Freire (hervalfreire@gmail.com) é Sun Certified Java Programmer (SCJP), Web Components Developer (SCWCD), Micro Application Developer (SCMAD) e Sun Certified Architect (1) (SCEA). Atua como consultor em projetos Java EE e Java ME.

Tabela 1. Classes e interfaces da Print API (pacote java.awt.print) [interfaces em iálico] Define as características físicas de uma página: largura, altura e área útil de Paper impressão (imageable area). PageForma Define a orientação (landscape, portrait ou landscape reverso). Um PageFormat também pode ser associado a um objeto Paper para a t definição de outras características de tamanho de página. Responsável pelo gerenciamento de impressões (incluindo exibição de diálogo PrinterJob de impressão e de configuração de página). Book Implementa de forma simples a interface Pageable. Define um conjunto de páginas, em que cada página pode ter configurações Pageable diferenciadas e ser renderizada por um objeto Printable diferente. Printable Define o método de renderização de páginas, chamado pelo PrinterJob durante a impressão de um documento. PrinterGrap Permite à aplicação localizar o contexto gráfico do PrinterJob atualmente em execução. hics Tabela 2. Seleção de atributos da JPS (pacote javax.print.attribute.standard)
Chromaticit y SheetCollat e PrintQualit y MediaSize Copies JobPriority
Atributo utilizado para definir a utilização de cores na impressão (ou impressão em preto e branco). Usado também para localizar impressoras coloridas ou monocromáticas Modelo de separação de páginas em caso de múltiplas cópias (ou seja, o agrupamento de páginas) Qualidade de impressão Dimensões do papel (ou outra mídia) Número de cópias de um Doc Definições de prioridade da impressão na fila de impressão do sistema operacional

Tabela 3. Métodos da classe PrintserviceLookup
PrintService lookupDefaultPrintService() PrintService[] lookupPrintServices( DocFlavor flavor, AttributeSet attributes) MultiDocPrintService[] lookupMultiDocPrintServices( DocFlavor[] flavors, AttributeSet attributes)
Retorna a impressora definida como padrão pelo sistema operacional Retorna uma lista de todas as impressoras que suportam um determinado tipo de documento (DocFlavor) e/ou modelo de impressão (AttributeSet) Retorna uma lista de impressoras com suporte aos diversos DocFlavors e ao AttributeSet especificados

Figura 2. atributos espaciais de um TextLayout

Figura 3. diálogo de impressão exibido pela JPS (classe ServiceUI)

Listagem 1. Imprimindo um objeto Printable
import java.awt.*; import java.awt.print.*; public class PrintableExample { public PrintableExample() { // Obtem um job de impressao PrinterJob job = PrinterJob.getPrinterJob(); // Define o objeto a ser impresso job.setPrintable(new Desenho()); // exibe o dialogo de impressao. if (job.printDialog()) { try { // imprime o objeto printable job.print(); } catch (PrinterException e) { e.printStackTrace(); } }

}

}

public static void main(String[] args) { new PrintableExample(); }

// definição de uma classe 'printable' class Desenho implements Printable { // Método de renderização de paginas public int print(Graphics graphics, PageFormat format, int pageIndex) throws PrinterException { // (caso o pageIndex seja maior que zero, retorna NO_SUCH_PAGE) if (pageIndex > 0) { return Printable.NO_SUCH_PAGE; } Graphics2D g2d = (Graphics2D) graphics; // desenha um retangulo na pagina int x = 85; int y = 87; g2d.draw(new Rectangle2D.Double(x, y, 400, 300)); // Indica que foi possível renderizar a página return Printable.PAGE_EXISTS;

}

}

Listagem 2. Imprimindo um objeto Pageable (Book)
import import import import java.awt.Graphics; java.awt.Graphics2D; java.awt.geom.Rectangle2D; java.awt.print.*;

public class PageableExample { public PageableExample() { // Obtem um job de impressao PrinterJob job = PrinterJob.getPrinterJob(); // Define o objeto a ser impresso job.setPageable(new Livro()); // exibe o dialogo de impressao. if (job.printDialog()) { try { // imprime o objeto printable job.print(); } catch (PrinterException e) { e.printStackTrace(); } }

}

}

public static void main(String[] args) { new PageableExample(); }

// definição de uma classe 'pageable' (um Book com 3 páginas) class Livro extends Book { public Livro() { PageFormat formatoCapa = new PageFormat(); formatoCapa.setOrientation(PageFormat.PORTRAIT); PageFormat formatoPagina = new PageFormat(); formatoPagina.setOrientation(PageFormat.LANDSCAPE); // define o tamanho da pagina em 8,5x11 polegadas (Letter) // note que os valores tem que ser passados em pontos, // onde 1pt = 1/72 polegada formatoPagina.getPaper().setSize(612, 792); // Adiciona uma capa ao livro utilizando a formatação de capa append(new Capa(), formatoCapa); // Adiciona duas paginas ao livro utilizando a formatacao de pagina interna append(new Pagina(), formatoPagina); append(new Pagina(), formatoPagina); } System.out.println("Livro criado. Total de paginas: " + getNumberOfPages());

}

// Renderiza a capa: um retangulo ao redor da area util da pagina class Capa implements Printable {

public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex > 1) { return Printable.NO_SUCH_PAGE; } g.drawRect((int) pageFormat.getImageableX()+1, (int) pageFormat.getImageableY()+1, (int) pageFormat.getImageableWidth()-2, (int) pageFormat.getImageableHeight()-2); } } // Renderiza uma pagina do livro: apenas um texto impresso no meio da pagina class Pagina implements Printable { public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { // Imprime somente os indices 0 e 1 if (pageIndex > 2) { return Printable.NO_SUCH_PAGE; } g.drawString("JavaMagazine", (int) pageFormat.getImageableWidth()/3, (int) pageFormat.getImageableHeight()/2); } return Printable.PAGE_EXISTS; return Printable.PAGE_EXISTS;

}

Listagem 3: imprimindo imagens
import java.awt.*; import java.awt.print.*; public class ImagePrintExample implements Printable { String imagem = "severina.jpg"; public ImagePrintExample() { // Obtem um job de impressao PrinterJob job = PrinterJob.getPrinterJob(); // Define o objeto a ser impresso job.setPrintable(this); // exibe o dialogo de impressao. if (job.printDialog()) { try { // imprime o objeto printable job.print(); } catch (PrinterException e) { e.printStackTrace(); } }

}

public int print(Graphics g, PageFormat format, int page) throws PrinterException { if (page != 0) { return NO_SUCH_PAGE; } Graphics2D gr = (Graphics2D) g; // posiciona o objeto graphics no começo da area util da pagina gr.translate(format.getImageableX(), format.getImageableY()); // carrega a imagem do arquivo jpg Image image = Toolkit.getDefaultToolkit().getImage(imagem); MediaTracker mediaTracker = new MediaTracker(new Container()); mediaTracker.addImage(image, 0); try { mediaTracker.waitForID(0); } catch (InterruptedException e) { e.printStackTrace(); } // imprime a imagem na posicao relativa 10, 10 gr.drawImage(image, 10, 10, null); return PAGE_EXISTS;

} public static void main(String[] args) { new ImagePrintExample(); }

}

Listagem 4. Impressão de texto formatado em múltiplas linhas
import import import import import import import java.awt.*; java.awt.font.*; java.awt.print.*; java.io.*; java.text.AttributedString; java.util.ArrayList; java.util.Iterator;

public class AdvancedTextExample implements Printable { // array de paragrafos do texto ArrayList texto; public AdvancedTextExample() throws IOException { // Obtem um job de impressao PrinterJob job = PrinterJob.getPrinterJob(); // carrega o texto a ser impresso BufferedReader re = new BufferedReader(new FileReader("texto.txt")); texto = new ArrayList(); String line = re.readLine(); while (line != null) { texto.add(line); line = re.readLine(); } re.close(); // Define o objeto a ser impresso job.setPrintable(this); // exibe o dialogo de impressao. if (job.printDialog()) { try { // imprime o objeto printable job.print(); } catch (PrinterException e) { e.printStackTrace(); } }

}

public int print(Graphics g, PageFormat format, int page) throws PrinterException { if (page != 0) { return NO_SUCH_PAGE; } Graphics2D gr = (Graphics2D) g; // determina o ponto de inicio do texto (inicio da area util + 10 pontos) float posX = (float) format.getImageableX()+10; float posY = (float) format.getImageableY()+10; // determina a largura do texto como 350 pontos (dpi) float larguraTexto = 350; // para cada paragrafo, imprime o paragrafo formatado Iterator it = texto.iterator(); while (it.hasNext()) { String line = (String) it.next(); // caso haja uma linha em branco, substituir por um espaço // para permitir formatação if (line.length() == 0) { line = " "; } // texto formatado a ser impresso AttributedString str = new AttributedString(line);

// define a fonte do texto como arial 12 itálico str.addAttribute(TextAttribute.FONT, new Font("Arial", Font.ITALIC, 12)); // instancia um line breaker para o texto formatado LineBreakMeasurer quebrador = new LineBreakMeasurer(str.getIterator(), gr.getFontRenderContext()); // cria um TextLayout para armazenar cada linha 'quebrada' TextLayout linha = quebrador.nextLayout(larguraTexto); while (linha != null) { // posiciona o texto posY += linha.getAscent(); linha.draw(gr, posX, posY); // soma espaço para a próxima linha posY += linha.getDescent() + linha.getLeading(); linha = quebrador.nextLayout(larguraTexto); } } // fim dos paragrafos return PAGE_EXISTS;

}

}

public static void main(String[] args) { try { new AdvancedTextExample(); } catch (IOException e) { System.out.println("Erro imprimindo: " + e.getMessage()); } }

Listagem 5. Exemplos de utilização do serviço de lookup
import javax.print.*; import javax.print.attribute.*; public class LookupExample { public LookupExample() { // Localiza a impressora padrão PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); System.out.println("Impressora padrão: " + printService.getName()); // Localiza todas as impressoras disponíveis no sistema (inclusive impressoras em rede) PrintService[] printers = PrintServiceLookup.lookupPrintServices(null, null); for (int i = 0; i < printers.length; i++) { System.out.println(printers[i].getName()); } // Localiza todas as impressoras com suporte a impressão de PDFs e com suporte a cores DocFlavor pdfFlavor = DocFlavor.BYTE_ARRAY.PDF; AttributeSet attributes = new HashAttributeSet(); attributes.add(Chromaticity.COLOR); PrintService[] pdfPrinters = PrintServiceLookup.lookupPrintServices(pdfFlavor, attributes); for (int i = 0; i < pdfPrinters.length; i++) { System.out.println(pdfPrinters[i].getName()); }

}

} public static void main(String[] args) { new LookupExample(); }

Listagem 6. Imprimindo duas cópias de um arquivo texto
import import import import java.io.FileInputStream; java.io.FileNotFoundException; javax.print.*; javax.print.attribute.*;

public class JpsPrintExample { public JpsPrintExample(boolean showDialog) { try { // Localiza todas as impressoras com suporte a arquivos txt PrintService[] printerServices = PrintServiceLookup.lookupPrintServices( DocFlavor.INPUT_STREAM.AUTOSENSE, null);

System.out.println("Impressoras com suporte: " + printerServices.length); // Localiza a impressora padrão PrintService printer = PrintServiceLookup.lookupDefaultPrintService(); System.out.println("Impressora: " + printer.getName()); System.out.println("Imprimindo arquivo txt"); // Definição de atributos do conteúdo a ser impresso: DocFlavor docFlavor = DocFlavor.INPUT_STREAM.AUTOSENSE; // Atributos de impressão do documento HashDocAttributeSet attributes = new HashDocAttributeSet(); // InputStream apontando para o conteúdo a ser impresso FileInputStream fi = new FileInputStream("teste.txt"); // Cria um Doc para impressão a partir do arquivo exemplo.txt Doc textDocument = new SimpleDoc(fi, docFlavor, attributes); // Configura o conjunto de parametros para a impressora PrintRequestAttributeSet printerAttributes = new HashPrintRequestAttributeSet(); if (showDialog) { // exibe um dialogo de configuracoes de impressao PrintService service = ServiceUI.printDialog(null, 320, 240, printerServices, printer, docFlavor, printerAttributes); if (service != null) { DocPrintJob printJob = service.createPrintJob(); printJob.print(textDocument, printerAttributes); }

} else { // Cria um job de impressão DocPrintJob printJob = printer.createPrintJob();

// Adiciona uma propriedade de impressão: imprimir 2 cópias printerAttributes.add(new Copies(2)); // Imprime o documento sem exibir uma tela de dialogo printJob.print(textDocument, printerAttributes);

}

}

} catch (FileNotFoundException ex) { System.out.println("Arquivo teste.txt não encontrado!"); } catch (PrintException ex2) { System.out.println("Erro de impressão: " + ex2.getMessage()); }

}

public static void main(String[] args) { new JpsPrintExample(true); }

Listagem 7. Localizando impressora com a JPS e imprimindo um objeto Printable
import java.awt.*; import java.awt.geom.Rectangle2D; import java.awt.print.*; public class JpsPrintableExample { public JpsPrintableExample() { PrintService service = null; // JPS: Localiza todas as impressoras disponíveis // no sistema (inclusive impressoras em rede) PrintService[] printers = PrintServiceLookup.lookupPrintServices(null, null); // JPS: seleciona a última impressora disponível service = printers[printers.length-1]; // Obtem um job de impressao PrinterJob job = PrinterJob.getPrinterJob(); try { // Define que o printer job vai utilizar a // impressora localizada pela JPS

job.setPrintService(service); } catch (PrinterException e1) { System.out.println("Erro acessando impressora: " + e1.getMessage()); } // Define o objeto a ser impresso job.setPrintable(new Desenho()); // exibe o dialogo de impressao. if (job.printDialog()) { try { // imprime o objeto printable job.print(); } catch (PrinterException e) { e.printStackTrace(); } }

}

}

public static void main(String[] args) { new PrintableExample(); }