Modelos de renderizado
Hay dos modelos de impresión en Java: Printable
trabajos y Pageable
trabajos.
Imprimibles
Printable
Los trabajos son el más simple de los dos modelos de impresión. Este modelo solo usa uno PagePainter
para todo el documento. Las páginas se representan en secuencia, comenzando con la página cero. Cuando se imprime la última página, PagePainter
debe devolver el NO_SUCH_PAGE
valor. El subsistema de impresión siempre solicitará que la aplicación represente las páginas en secuencia. Por ejemplo, si se le pide a su aplicación que procese las páginas cinco a siete, el subsistema de impresión solicitará todas las páginas hasta la séptima, pero solo imprimirá las páginas cinco, seis y siete. Si su aplicación muestra un cuadro de diálogo de impresión, no se mostrará el número total de páginas que se imprimirán, ya que es imposible saber de antemano el número de páginas del documento que utiliza este modelo.
Pageables
Pageable
Los trabajos ofrecen más flexibilidad que los Printable
trabajos, ya que cada página de un Pageable
trabajo puede presentar un diseño diferente. Pageable
Los trabajos se utilizan con mayor frecuencia con Book
s, una colección de páginas que pueden tener diferentes formatos. Explicaré la Book
clase en un momento.
Un Pageable
trabajo tiene las siguientes características:
- Cada página puede tener su propio pintor. Por ejemplo, podría tener un pintor implementado para imprimir la portada, otro pintor para imprimir el índice y un tercero para imprimir el documento completo.
- Puede establecer un formato de página diferente para cada página del libro. En un
Pageable
trabajo, puede mezclar páginas verticales y horizontales. - El subsistema de impresión puede pedirle a su aplicación que imprima páginas fuera de secuencia y algunas páginas pueden omitirse si es necesario. Nuevamente, no tiene que preocuparse por esto siempre que pueda suministrar cualquier página de su documento a pedido.
- El
Pageable
trabajo no necesita saber cuántas páginas hay en el documento.
Libros
También nuevo desde la versión 1.2 es la Book
clase. Esta clase le permite crear documentos de varias páginas. Cada página puede tener su propio formato y su propio pintor, lo que le brinda la flexibilidad de crear documentos sofisticados. Dado que la Book
clase implementa la Pageable
interfaz, puede implementar su propia Book
clase cuando la Book
clase proporcionada carece de las características que necesita.
Una Book
clase representa una colección de páginas. Cuando se crea por primera vez, el Book
objeto está vacío. Para agregar páginas, simplemente use uno de los dos append()
métodos (consulte mi explicación de esta clase en la sección API para obtener más detalles). Los parámetros de este método son el PageFormat
objeto, que define las características físicas de la página, y un PagePainter
objeto, que implementa la Printable
interfaz. Si no conoce el número de páginas de su documento, simplemente pase el UNKNOWN_NUMBER_OF_PAGES
valor al append()
método. El sistema de impresión encontrará automáticamente el número de páginas llamando a todos los pintores de páginas del libro hasta que reciba un NO_SUCH_PAGE
valor.
Definición de API
La teoría y la práctica se encontrarán en esta sección. En las secciones anteriores, aprendimos sobre la estructura de la página, las unidades de medida y los modelos de representación. En esta sección, veremos la API de impresión de Java.
Todas las clases necesarias para imprimir se encuentran en el java.awt.print
paquete, que se compone de tres interfaces y cuatro clases. Las siguientes tablas definen las clases y las interfaces del paquete de impresión.
Nombre | Tipo | Descripción |
Paper |
Clase | Esta clase define las características físicas de la página. |
PageFormat |
Clase | PageFormat define el tamaño y la orientación de la página. También define cuál Paper usar al renderizar una página. |
PrinterJob |
Clase | Esta clase administra el trabajo de impresión. Sus responsabilidades incluyen crear un trabajo de impresión, mostrar un cuadro de diálogo de impresión cuando sea necesario e imprimir el documento. |
Book |
Clase |
|
Pageable |
Interfaz | Una Pageable implementación representa un conjunto de páginas a imprimir. El Pageable objeto devuelve el número total de páginas del conjunto, así como el PageFormat y Printable para una página específica. La Book clase implementa esta interfaz. |
Printable |
Interfaz | Un pintor de páginas debe implementar la Printable interfaz. Sólo hay un método en este interfaz, print() . |
PrinterGraphics |
Interfaz | El Graphics objeto implementa esta interfaz. PrinterGraphics proporciona el getPrinterJob() método para obtener el trabajo de la impresora que instancia el proceso de impresión. |
Interfaz paginable
La Pageable
interfaz incluye tres métodos:
Nombre del método | Descripción |
int getNumberOfPages() |
Devuelve el número de páginas del documento. |
PageFormat getPageFormat(int pageIndex) |
Devuelve las páginas PageFormat especificadas por pageIndex . |
Printable getPrintable(int pageIndex) |
Devuelve la Printable instancia responsable de representar la página especificada por pageIndex . |
Interfaz imprimible
La Printable
interfaz presenta un método y dos valores:
Nombre | Tipo | Descripción |
int print(Graphics graphics, PageFormat pageFormat, int pageIndex) |
Método | Solicita que los gráficos se manejen con el formato de página especificado para representar la página especificada. |
NO_SUCH_PAGE |
Valor | Esta es una constante. Devuelve este valor para indicar que no hay más páginas para imprimir. |
PAGE_EXISTS |
Valor | El print() método regresa PAGE_EXISTS . Indica que la página pasada como parámetro a print() se ha renderizado y existe. |
Todo pintor de páginas debe implementar la Printable
interfaz. Dado que solo hay un método para implementar, la creación de pintores de páginas puede parecer fácil. Sin embargo, recuerde que su código debe poder representar cualquier página dentro o fuera de secuencia.
Hay tres parámetros para print()
, incluido Graphics
, que es la misma clase que se usa para dibujar en la pantalla. Dado que la Graphics
clase implementa la PrinterGraphic
interfaz, puede obtener el PrinterJob
que instancia este trabajo de impresión. Si el diseño de su página es complejo y requiere algunas funciones de dibujo avanzadas, puede convertir el Graphics
parámetro a un Graphics2D
objeto. A continuación, tendrá acceso a la API 2D de Java completa.
Before you start using the Graphics
object, note that the coordinates are not translated to the top left corner of the printable area. Refer to Figure 3 to find the location of the default origin.
(0, 0) appears at the top left corner of the printer margins. To print a 1-by-1-inch rectangle, 1 inch from both top and left margins, you would use the following code:
1: public int print (Graphics graphics, PageFormat pageFormat, int pageIndex) { 2: Graphics2D graphics2D = (Graphics2D) graphics; 3: Rectangle2D.Double rectangle = new Rectangle2D.Double (); 4: rectangle.setRect (pageFormat.getImageableX () + 72, 5: pageFormat.getImageableY () + 72, 6: 72, 7: 72); 8: graphics2D.draw (rectangle); 9: return (PAGE_EXISTS); }
From the previous example, we see that we must manually translate the origin of the rectangle so that it prints at the top of the printable area as in Figure 1. To simplify the code, we could translate the coordinates once and use (0, 0) as the origin of the printable area. By modifying the previous example, we get:
1: public int print (Graphics graphics, PageFormat pageFormat, int pageIndex) { 2: Graphics2D graphics2D = (Graphics2D) graphics; 3: graphics2D.translate (pageFormat.getImageableX (), pageFormat.getImageableY ()); 4: Rectangle2D.Double rectangle = new Rectangle2D.Double (); 5: rectangle.setRect (72, 72, 72, 72); 6: graphics2D.draw (rectangle); 7: return (PAGE_EXISTS); 8: }
Using the translate()
method in line 3, we can translate the coordinates and set our origin (0, 0) at the top of the printable area. From this point on, our code will be simplified.
PrinterGraphics interface
The PrinterGraphics
interface consists of one method:
Method name | Description |
PrinterJob getPrinterJob() |
Returns the PrinterJob for this rendering request and is implemented by the Graphics class |
Paper class
Eight methods make up the Paper
class:
Method name | Description |
double getHeight() |
This method returns the page's physical height in points (1 inch = 72 points). For example, if you are printing on a letter-size page, the return value will be 792 points, or 11 inches. |
double getImageableHeight() |
This method returns the page's imageable height. The imageable height is the height of the print area that you may draw on. See Figure 1 for a graphical view of the imageable area. |
double getImageableWidth() |
This method returns a page's imageable width (the width of the print area that you may draw on). See Figure 1 for a graphical view of the imageable area. |
double getImageableX() |
This method returns the x origin of the imageable area. Since there is no support for margins, the return value represents the left margin. |
double getImageableY() |
This method returns the y origin of the imageable area. The value returned from this method is equivalent to the top margin. |
double getWidth() |
This method returns the page's physical width in points. If you print on a letter-size paper, the width is 8.5 inches, or 612 points. |
void setImageableArea(double x, double y, double width, double height) |
This method sets the imageable area and specifies the margins on the page. Actually, the API provides no method to set the margins explicitly; you have to calculate them yourself. |
void setSize(double width, double height) |
This method sets the physical page size. To define an 8.5-by-11-inch sheet, you would supply 612 and 792 points. Note that the default size is LETTER . |
Before we move on to the next section, remember that the Paper
class defines the page's physical characteristics. The PageFormat
class represents all the page's characteristics, such as page orientation, size, and the paper type. This class is always passed as a parameter to the Printable
interface's print()
method. Use Paper
to obtain the imageable area location, size, and page orientation along with a transformation matrix.
PageFormat class
The PageFormat
consists of 12 methods:
Method name | Description |
double getHeight() |
This method returns the page's physical height in points (1 inch = 72 points). If your page measures 8.5 by 11 inches, then the return value will be 792 points, or 11 inches. |
double getImageableHeight() |
This method returns the page's imageable height, which is the height of the print area on which you may draw. See Figure 1 for a graphical view of the imageable area. |
double getImageableWidth() |
This method returns the page's imageable width -- the width of the print area on which you may draw. Figure 1 illustrates a graphical view of the imageable area. |
double getImageableX() |
This method returns the x origin of the imageable area. |
double getImageableY() |
This method returns the imageable area's y origin. |
double getWidth() |
This method returns the page's physical width in points. If you print on letter-sized paper, the width is 8.5 inches, or 612 points. |
double getHeight() |
This method returns the page's physical height in points. For example, letter-sized paper is 11 inches in height, or 792 points. |
double[] getMatrix() |
This method returns a transformation matrix that translates user space into the requested page orientation. The return value is in the format required by the AffineTransform constructor. |
int getOrientation() |
This method returns the orientation of the page as either PORTRAIT or LANDSCAPE . |
void setOrientation(int orientation) |
This method sets the orientation of the page, using the constants PORTRAIT and LANDSCAPE . |
Paper getPaper() |
This method returns the Paper object associated with the page format. Refer to the previous section for a description of the Paper class. |
void setPaper(Paper paper) |
This method sets the Paper object that will be used by the PageFormat class. PageFormat must have access to the physical page characteristics to complete this task. |
This concludes the description of the page classes. The next class that we will study is the PrinterJob
.
PrinterJob class
The PrinterJob
class controls the printing process. It can both instantiate and control a print job. Below you will find a definition of the class:
Method name | Description |
abstract void cancel() |
This method cancels the current print job. You can validate the cancellation with the isCancel() method. |
abstract boolean isCancelled() |
This method returns true if the job is cancelled. |
PageFormat defaultPage() |
This method returns the default page format for the PrinterJob . |
abstract PageFormat defaultPage(PageFormat page) |
This method clones the PageFormat passed in parameters and modifies the clone to create the default PageFormat . |
abstract int getCopies() |
This method returns the number of copies that the print job will print. |
abstract void setCopies(int copies) |
This method sets the number of copies that the job will print. Note that if you show a print dialog box, users can alter the number of copies (see the pageDialog method). |
abstract String getJobName() |
This method returns the job name. |
static PrinterJob getPrinterJob() |
This method creates and returns a new PrinterJob . |
abstract String getUserName() |
This method returns the user name associated with the print job. |
abstract PageFormat pageDialog(PageFormat page) |
This method displays a dialog that allows the user to modify the PageFormat . The PageFormat , passed in parameters, sets the fields of the dialog. If the user cancels the dialog, then the original PageFormat will be returned. But if the user accepts the parameters, then a new PageFormat will be created and returned. Since it will not show the same parameters on all operating systems, you must be careful when using the pageDialog . |
abstract void setPageable(Pageable document) |
This method queries the document to obtain the total number of pages. The Pageable will also return the PageFormat and the Printable object for each page. See the definition of the Pageable interface for more information. |
abstract void setPrintable(Printable painter) |
This method sets the Painter object that will render the pages to be printed. A Painter object is an object that implements the Printable class and its print() method. |
abstract void setPrintable(Printable painter, PageFormat format) |
This method completes the same tasks as abstract void setPrintable(Printable painter) , except that you supply the PageFormat that the Painter will use. As indicated in the definition of the Printable interface, the print() method passes a PageFormat object as the first parameter. |
abstract void print() |
This method prints the document. It actually calls the print() method of the Painter previously assigned to this print job. |
abstract void setJobName(String jobName) |
This method sets the name of the print job. |
abstract boolean printDialog() |
This method displays a print dialog box that allows the user to change the print parameters. Note that this interaction's result will not be returned to your program. Instead, it will be passed to the peer operating system. |
abstract PageFormat validatePage(PageFormat page) |
This method will validate the PageFormat passed in parameters. If the printer cannot use the PageFormat that you supplied, then a new one that conforms to the printer will be returned. |
Book class
Seven methods make up the Book
class:
>
Method name | Description |
void append(Printable painter, PageFormat page) |
This method appends a page to the Book . The painter and the PageFormat for that page are passed in parameters. |
void append(Printable painter, PageFormat page, int numPages) |
This method completes the same tasks as void append(Printable painter, PageFormat page) , except that you specify the number of pages. |
int getNumberOfPages() |
This method returns the number of pages currently in the Book . |
PageFormat getPageFormat(int pageIndex) |
This method returns the PageFormat object for a given page. |
Printable getPrintable(int pageIndex) |
This method returns the painter for a given page. |
void setPage(int pageIndex, Printable painter, PageFormat page) |
This method sets the painter and the PageFormat for a given page already in the book. |
The printing recipe
The recipe for printing is very simple. First, create a PrinterJob
object:
PrinterJob printJob = PrinterJob.getPrinterJob ();
Next, using the setPrintable()
method of the PrinterJob
, assign the Painter
object to the PrinterJob
. Note that a Painter
object is one that implements the Printable
interface.
printJob.setPrintable (Painter);
Or you could set the PageFormat
along with the Painter
:
printJob.setPrintable (Painter, pageFormat);
Finally, the Painter
object must implement the print()
method:
public int print (Graphics g, PageFormat pageFormat, int page)
Here the first parameter is the graphics handle that you will use to render the page, the pageFormat
is the format that will be used for the current page, and the last parameter is the page number that must be rendered.
That's all there is to it -- for simple printing, that is.
Introduction to the framework
The print framework that we will build in this series will be completely independent of the Java printing API. It will allow for greater flexibility in producing different outputs. Its structure will allow you to create documents, pages, and print objects. You will be able to add print objects to a page while adding pages to a document. By using this structure, you will be able to easily implement export features to PDF or HTML files, or print directly to the printer using the print API. But the main goal of the framework is to simplify the creation of printed documents. When you print using the print API, you only end up with a graphic canvas to draw on. It fails to address the concepts of paragraphs, images, drawings, graphics, tables, or running headers and footers. Because you must compute the (x, y) origin, the width and height of the printable area, setting margins is a chore. Our print framework will address all of these weaknesses.
Conclusion
We covered a lot of ground in this first part. We looked at measurement units, the structure of page, the two rendering models (Pageable
and Printable
), and Books
, and we concluded with a detailed explanation of the printing API. Next month, we'll focus primarily on code, as we will be putting everything into practice. We will also look at the issues that arise when printing on multiple platforms. Looking ahead to Part 3, I will explain in detail the design and implementation of the framework.
Más información sobre este tema
- "Impresión en Java", Jean-Pierre Dubé ( JavaWorld )
- Parte 1: Familiarícese con el modelo de impresión de Java (20 de octubre de 2000)
- Parte 2: Imprima su primera página y renderice documentos complejos (1 de diciembre de 2000)
- Parte 3: Jean-Pierre Dubé presenta el marco de impresión que funciona sobre la API de impresión de Java (5 de enero de 2001)
- Part 4: Code the print framework
- (February 2, 2001)
- Part 5: Discover the print framework's support classes
- (March 2, 2001)
- You will find tons of books covering Java AWT, but none will cover this subject to the extent of this book. If you're writing GUIs, you must have this book next to your computer: Graphic Java 2, Mastering The JFCAWT, Volume 1, David M. Geary (Prentice Hall, 1998)
//www.amazon.com/exec/obidos/ASIN/0130796662/javaworld
- This book was helpful when Java 1.1 came out, and was the first to talk about printing in Java: Migrating from Java 1.0 to Java 1.1, Daniel I. Joshi and Pavel A. Vorobiev (Ventana Communications Group, 1997)
//www.amazon.com/exec/obidos/ASIN/1566046866/javaworld
- Probablemente el mejor libro sobre Java 2D, este libro cubre todos los aspectos de la API 2D y también proporciona un
Graphics
marco para composiciones 2D avanzadas: Java 2D API Graphics, Vincent J. Hardy (Prentice Hall, 1999)//www.amazon.com/exec/obidos/ASIN/0130142662/javaworld
- Una excelente introducción a la API de Java 2D "Getting Started with Java 2D", Bill Day ( JavaWorld, julio de 1998)
//www.javaworld.com/javaworld/jw-07-1998/jw-07-media.html
Esta historia, "Impresión en Java, Parte 1" fue publicada originalmente por JavaWorld.