Imprimir JPanel/JFrame a escala en Java

Bueno pues aqui va una adaptación de la primera version para imprimr un JPanel / JFrame, pero a escala:

1. Implementar la interfaz Printable en la clase que queremos imprimir:


public class PrintMeScale extends javax.swing.JFrame implements Printable{...

2. Sobreescribimos el método print en la clase que queremos imprimir:



    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

        if (pageIndex > 0)
          return NO_SUCH_PAGE;

        Graphics2D g2d = (Graphics2D)graphics;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
        //-------------------------ESCALAR LA IMPRESION-------------------------------//
        g2d.scale( ((Number) campo_escala.getValue()).doubleValue(), ((Number) campo_escala.getValue()).doubleValue());
        //----------------------------------------------------------------------------//
        jPanel1.printAll(graphics);

        return PAGE_EXISTS;
    }

Como se pede ver el truco esta en utilizar el método scale(X,Y) del objeto g2d, este recibe dos parametros de tipo Double que representan la escala para el alto (X) y el ancho (Y). Ejemplo:

100% == 1.00
80% == 0.80
etc…

Imprime el obejo escalado al 70%
g2d.scale(0.70,0.70);

3. Y por último mandar a ejecutar la impresión:




try {

                PrinterJob job = PrinterJob.getPrinterJob();

                job.setPrintable(this);

                //--------------------------------------------

                boolean aceptar_impresion =job.printDialog();

                 if(aceptar_impresion)

                    job.print();

                //---------------------------------------------

        }
catch (PrinterException ex) {

            Logger.getLogger(PrintMeScale.class.getName()).log(Level.SEVERE, null, ex);
        }

NOTA: Al ejecutarse la impresion se abre el dialogo de impresion, sin embargo en esta version se ha agreado el boolean aceptar_impresion, porque al darle clic al boton CANCELAR  se ejecutaba el trabajo de impresion, con esto queda solucionado.

Dejo la captura del ejemplo con su código.

Source

Source

Saludos =P

27 comentarios en “Imprimir JPanel/JFrame a escala en Java

  1. Miguel Jose dijo:

    Te agradezco broder por toda tu ayuda, no sabes cuanto me han ayudado tus ejemplos de impresion en el desarrollo de mi proyecto.

    Sigue enviando tus ejemplos porque son de gran utilidad. Gracias por tu ayuda, estamos en contacto.

    • jaehoo dijo:

      De nada, me da gusto que te hayan servido…
      Aun me falta darle un poco de orden a los temas y unos enlaces pero espero poder seguir escribiendo (si es que me da tiempo) para que poco a poco esto pueda convertirse en un sitio de referencia o por lo menos un catalogo de consulta, saludos

  2. leonardo dijo:

    el codigo esta muy bueno no lo habia encontrado en ningun lado mi consulta es la siguiente yo puse el codigo en la ventana que quiero imprimir y no me sale nada para imprimir no soy muy entendido en esto que puedo hacer?
    este es mi codigo

    … COMENTE TODO TU CODIGO =P

    • jaehoo dijo:

      Hola n_n, lo siento comente todo el código que pusiste, para tu problema veo que hay dos cosas:

      1. La clase ventana no implementa la interfaz Serializable.
      2. Te falta sobre sobre-escribir el método print().

      Con esas dos cosas ya debe funcionar, ya modifique el código e imprime la ventana, solo checa los puntos que puse en la entrada.

      Saludos.

  3. marbin dijo:

    hola jaehoo ,primero que nada felicitarte por el blog esta super y agradecerte por los posteos que haces bien completos la verdad.
    veras tengo una pregunta y no se como resolverla,la cuestion es que tengo un frame y un jlabel con una imagen debajo tengo un jlabel con texto y al costado un jtxtfield,debajo de los anteriores tengo un jtable con muchas filas y deco imprimirlas todas con el misma composicion del frame osea con los jlabels y jtxtfield,como el jtable es largo mas de una hoja diria yo como podria resolver ese problema.
    espero puedas ayudarme con tu infinita sbiduria jajaja.
    gracias de antemano.
    atentamente Marbin

    • jaehoo dijo:

      Hola, deberias de poder imprimir todo el contenido del frame sin problemas siempre y cuando todos los componentes que estas mandando estan dentro del panel principal.

      Saludos

  4. fredy dijo:

    hay dios no le entiendo a tu codigo!!

    =(

    como le puedo hacer para que no me escale la ventana??
    y agregar mas componentes como labels, jtables , combo , chck?

    contestame porfavor

    gracias!!

    • jaehoo dijo:

      jaja es chistoso, primero escribes un comentario donde me pides que escriba mas y luego este =P…

      Pero haber no es tan dificil, si ves mucho codigo raro es porque el frame lo cree con la herramienta visual de netbeans por eso hay mucho codigo raro, pero a eso no le hagas caso.

      Hasta abajo al final del post deje el codigo fuente completo por si quieres bajarlo y modificarlo.

      Bueno como puedes ver la clase tiene :
      1 constructor = PrintMeScale(), inicializa la clase.
      4 metodos:
      initComponents() = lo genera netbeans en automatico, a este NO le hagas caso, lo unico que tiene son los botones los labels, etc… todo lo que forma el frame.
      jButton1ActionPerformed(java.awt.event.ActionEvent evt)”: Este metodo es la acción que manda a imprimir el frame
      main(String args[]): Es el metodo con el que ejecutamos la clase.
      print(Graphics graphics, PageFormat pageFormat, int pageIndex): el metodo que sobreescribimos de la interfaz printable para poder imprimir.

      Y eso es todo en realidad como vez no es nada complicado, ahora si no quieres que la impresion salga a escala solo comenta la linea:

      //g2d.scale( ((Number) campo_escala.getValue()).doubleValue(), ((Number) campo_escala.getValue()).doubleValue());

      Y si quieres agregar mas cosas pues… no se tendrias que aventartelo a mano, pero yo te sugeriria que probaras el NetBeans, por lo menos para las aplicaciones swing (y a mi punto de vista) es el más completo.

      Espero te sriva saludos

  5. edstapia dijo:

    Gracias…. muy buen aporte…
    desde hace tiempo estuve buscando algo similar, ahora se me facilitaran mucho las cosas.
    Segun revisaba tu codigo es muy facil imprimir cualquier componente swing, el unico requisito es que tenga el metodo printAll()….

    Si a alguien le sirve yo lo implemento de esta manera:

    public class DocumentoAImprimir implements Printable{
    private JTextArea ComponenteSwing;
    private double escalaX,escalaY;
    public DocumentoAImprimir(JTextArea texto,double escalax, double escalay){
    ComponenteSwing=texto;
    escalaX = escalax;
    escalaY = escalay;
    }
    public int print(Graphics g, PageFormat pf, int page){
    if (page > 0) {
    return NO_SUCH_PAGE;
    }
    Graphics2D g2d = (Graphics2D)g;
    g2d.translate(pf.getImageableX(), pf.getImageableY());
    g2d.scale(escalaX, escalaY);
    ComponenteSwing.printAll(g2d);
    return PAGE_EXISTS;
    }
    }

    Luego lo llamo desde otro lado pasandole el componente que deseo imprimir (jtable, jframe, jtextarea, etc) junto con las escalas de X y Y. Luego llamamos a un Printerob comun…

    PrinterJob printJob = PrinterJob.getPrinterJob();
    Book libro = new Book();
    libro.append(new DocumentoAImprimir(txtResumen, 1.0, 1.0),
    printJob.defaultPage());
    printJob.setPageable(libro);
    if (printJob.printDialog()) {
    try {
    printJob.print();
    } catch (Exception PrinterException) {
    javax.swing.JOptionPane.showMessageDialog(null, PrinterException.getMessage());
    }
    }

    • edstapia dijo:

      por cierto para mi ejemplo yo imprimo un JTextArea… si se desea imprimir otro tipo de componente se debe de reemplazar por un JTable, JTextPane,etc….

    • Daniel Betancourt dijo:

      Aquí dejo el método y la clase que he utilizado para hacer la impresión !
      Que ademas me ha funconado perfectamente !

      public class Impresión implements Printable
      {
      private JPanel componente; //Cualquier Componente
      private double escalaX,escalaY;

      public Impresión(JPanel panelUno,double escalax, double escalay)
      {
      componente = panelUno;
      escalaX = escalax;
      escalaY = escalay;
      }

      public int print(Graphics graficar, PageFormat pageFormat, int pageIndex)
      {
      if (pageIndex > 0)
      return NO_SUCH_PAGE;

      Graphics2D graficar2D = (Graphics2D)graficar;

      graficar2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
      graficar2D.scale(escalaX, escalaY);

      componente.printAll(graficar2D);

      return PAGE_EXISTS;
      }
      }

      Este método se encontraba en otra clase, la clase Ejecutable o principal.

      public static void imprimir()
      {
      PrinterJob printJob = PrinterJob.getPrinterJob();

      Book libro = new Book();
      libro.append(new Impresión(panelUno, 0.9, 0.9),

      printJob.defaultPage());
      printJob.setPageable(libro);

      if (printJob.printDialog())
      try
      {
      printJob.print();
      }
      catch (Exception PrinterException)
      {
      JOptionPane.showMessageDialog(null, PrinterException.getMessage());
      }
      }

      • Daniel Betancourt dijo:

        Ahora la pregunta es:
        Tengo cuatro paneles para imprimir, como se hace para que cada uno se imprima en una hoja diferente ???
        y que sea de forma automática, es decir que no le aparezca 4 ventanas de solicitud de impresión al usuario !

        Alguien podría ayudarme ???

      • Daniel Betancourt dijo:

        Ya esta la solución para imprimir los paneles que se quiera, solo es quitar del método print(Graphics, PageFormat, int) de la clase Impresión las siguientes líneas:

        if (pageIndex > 0)
        return NO_SUCH_PAGE;

        y así, si se imprime las páginas que se quieran !

      • Daniel Betancourt dijo:

        Claro y tambien habria los otros paneles al objeto Book:

        libro.append(new Impresión(panelDos, 0.9, 0.9),printJob.defaultPage());

        libro.append(new Impresión(panelTres, 0.9, 0.9),printJob.defaultPage());

        libro.append(new Impresión(panelCuatro, 0.9, 0.9),printJob.defaultPage());


        ..
        .

  6. RoxCobain dijo:

    Si sirve, te daré un millón de dólares okno… sucede que tengo varios objetos graphics (del generalPath) en el panel, y hasta el momento solo me imprime el primer elemento que encuentre en el panel, veamos que sucede :s

  7. nanjimenez dijo:

    Viejo que buen aporte utilice el codigo que dejaste pero tengo un problema, estoy tratando de imprimir un panel pero es demaciado grande y se me sale de la hoja de impresion, no hay una obcion de ajustar el panel con la hoja de impresion?, si me puedes ayudar se lo agradeceria

  8. Emanuel dijo:

    Hola, disculpen yo hice un jframe (el JFrame se llama Personal)en donde por medio de un boton agrego una imagen en un jpanel y ademas texto en etiquetas, pero ademas el usuario ademas de agreagar la imagen al jpanel tambien pondra texto en varios textfieldt, mi pregunta es como le puedo hacer para mandar a imprimir todo el jframe con la imagen y el texto de los textfield o en el peor de los casos como exportarlo a PDF???

    • jaehoo dijo:

      hola, ps en todo caso se me ocurren estas ideas:
      1. Que generes un boton imprimir que te genere la vista previa de todo lo que quieres imprimir y en esa hoja (Jframe) aplicar este truco para imprimir.
      2. Existe un framework llamado Itext y POI, que te permiten generar archivos PDF, pero tendrias que investigar como acoplarla a tu proyecto.
      3. Hay otra herramienta llamada Jasper Reports, se utiliza para imprimir reportes que también puede ser una buena opción.

      Saludos

  9. drake dijo:

    tengo una pregunta disculpa pero no se mucho de programacion
    bueno al escalar la impresion utilizas una variable lammada campo_escala
    donde la inicializas o la creas en el formulario ?

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s