Un contexto gráfico permite a un programa dibujar en un dispositivo de renderización como una pantalla, una impresora o una imagen fuera de pantalla. Como los componentes Swing se renderizan a través de un objeto Graphics usando el soporte de gráficos AWT, es fácil imprimir componentes Swing con el nuevo API de impresión. Sin embargo, los componentes AWT no se renderizan a un dispositivo gráfico, debemos extender la clase del componente AWT e implementar el método de dibujo del componente AWT.
La aplicación printbutton.java muestra un panel con un MyButton sobre él. Cuando se pulsa el botón, la aplicación imprime el componente MyButton.
En el código, la clase Button se extiende para implementar Printable e incluye los método paint y print. Este último es necesario porque la clase implementa Printable, y el método paint es necesario porque describe como aparecen la forma del botón y la etiqueta de texto cuando se imprimen.
Para ver el botón, la contexto gráfico de impresión es trasladado a un área imaginable de la impresora, y para ver la etiqueta de texto, se selecciona una fuente en el contexto gráfico de impresión.
En este ejemplo, el botón se imprime a 164/72 pulgadas dentro del margen imaginable (hay 72 pixels por pulgada) y a 5/72 pulgadas del margen superior imaginado. Aquí es donde el botón es posicionado por el controlador de distribución y estos mismo número son devultos por las siguientes llamadas:
Y aquí está el código de la clase MyButton:int X = (int)this.getLocation().getX(); int Y = (int)this.getLocation().getY();
class MyButton extends Button
implements Printable {
public MyButton() {
super("MyButton");
}
public void paint(Graphics g) {
//To see the label text, you must specify a font for
//the printer graphics context
Font f = new Font("Monospaced", Font.PLAIN,12);
g2.setFont (f);
//Using "g" render anything you want.
//Get the button's location, width, and height
int X = (int)this.getLocation().getX();
int Y = (int)this.getLocation().getY();
int W = (int)this.getSize().getWidth();
int H = (int)this.getSize().getHeight();
//Draw the button shape
g.drawRect(X, Y, W, H);
//Draw the button label
//For simplicity code to center the label inside the
//button shape is replaced by integer offset values
g.drawString(this.getLabel(), X+10, Y+15);
}
public int print(Graphics g,
PageFormat pf, int pi)
throws PrinterException {
if (pi >= 1) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
//To see the button on the printed page, you
//must translate the printer graphics context
//into the imageable area
g2.translate(pf.getImageableX(), pf.getImageableY());
g2.setColor(Color.black);
paint(g2);
return Printable.PAGE_EXISTS;
}
Nota: La impresión Graphics2D está basada en la clase BufferedImage y algunas plataformas no permiten un color de fondo negro por defecto. Si este es nuestro caso tenemos que añadir g2.setColor(Color.black) al método print antes de la invocación a paint.
Imprimir un componente Swing es casi lo mismo que imprimir un componente AWT, excepto que la clase MyButton no necesita una implementación del método paint. Sin embargo, si teine un método print que llama al método paint del componente. La implementación del método paint no es necesaria porque los componentes Swing saben como dibujarse a sí mismos.
Aquí está el código fuente completo para la versión Swing de printbutton.java.
class MyButton extends JButton implements Printable {
public MyButton() {
super("MyButton");
}
public int print(Graphics g,
PageFormat pf, int pi)
throws PrinterException {
if (pi >= 1) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
g2.translate(pf.getImageableX(),
pf.getImageableY());
Font f = new Font("Monospaced", Font.PLAIN,12);
g2.setFont (f);
paint(g2);
return Printable.PAGE_EXISTS;
}
Si extendemos un JPanel e implementamos Printable, podemos imprimir un componente panel y todos sus componentes.
public class printpanel extends JPanel
implements ActionListener,
Printable {
Aquí está el código de printpanel.java que imprime un objeto JPanel y el JButton que contiene, y el código de ComponentPrinterFrame.java que imprime un ojeto JFrame y los componentes JButton, JList, JCheckBox,
y JComboBox que contiene.
El método paintComponent llama al método drawShapes para renderizar gráficos 2D en la pantalla cuando arranca la aplicación. Cuando pulsamos sobre el botón, Print, se crea un contexto gráfico de impresión y es pasado al método drawShapes para el dibujado.
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable((MyButton) e.getSource());
if(printJob.printDialog()){
try { printJob.print(); }
catch (Exception PrinterExeption) { }
}
}
Nota: En Swing, la sentencia printJob.setPageable((MyButton) e.getSource()); puede escribirse como printJob.setPrintable((MyButton) e.getSource());. La diferencia es que setPrintable es para aplicaciones que no conocen el número de páginas que están imprimiendo. Si usamos setPrintable, necesitamos añadir if(pi >= 1){ return Printable.NO_SUCH_PAGE: } al principio del método print.
Nota: Algunas plataformas no soportan el diálogo de configuración de página. En estas plataformas, la llamada a pageDialog simplemente devuelven el objeto PageFormat que se les pasó y no muestran ningún diálogo.
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable((MyButton) e.getSource());
PageFormat pf = printJob.pageDialog(
printJob.defaultPage());
if(printJob.printDialog()){
try { printJob.print(); } catch (Exception ex) { }
}
}
El ejemplo print2button.java pone los botones Print y Print 2 del tipo MyButton en un panel. Crea un libro que contiene las páginas para imprimir. Cuando pulsamos algun botón, el libro imprime una copia del botón Print en modo horizontal y dos copias del botón Print 2 en modo vertical, como se especifica en la implementación del método actionPerformed mostrada aquí:
Nota: Actualmente un Bug restringe a la plataforma Solaris a imprimir sólo en vertical.
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
/* Set up Book */
PageFormat landscape = printJob.defaultPage();
PageFormat portrait = printJob.defaultPage();
landscape.setOrientation(PageFormat.LANDSCAPE);
portrait.setOrientation(PageFormat.PORTRAIT);
Book bk = new Book();
bk.append((Printable)b, landscape);
bk.append((Printable)b2, portrait, 2);
printJob.setPageable(bk);
try { printJob.print(); } catch (Exception ex) { }
}