Vous êtes sur la page 1sur 36

L'impression en java

par Bruno Richeton

Date de publication : 1 juin 2009

Cet article prsente un retour d'exprience personnelle sur l'impression en Java. Il prsente l'API officielle pour l'impression ainsi que ses limites. Il prsente aussi les techniques que j'ai employes pour contourner ces limites. Ce document n'est donc pas une documentation officielle mais plutt le fruit de recherches individuelles pour arriver obtenir une impression de qualit en Java.

L'impression en java par Bruno Richeton

I - Remerciements....................................................................................................................................................... 3 II - Avant-propos.......................................................................................................................................................... 3 III - L'API java existante.............................................................................................................................................. 4 III-A - Quoi imprimer ?............................................................................................................................................4 III-A-1 - L'interface Printable............................................................................................................................. 4 II-A-2 - L'interface Pageable............................................................................................................................. 5 III-B - Comment imprimer ?....................................................................................................................................6 III-B-1 - La classe PrinterJob............................................................................................................................6 III-B-1-a - Les PrintRequestAttribute ou requtes d'impression..................................................................7 IV - Les problmes rencontrs.................................................................................................................................. 11 IV-A - Botes de configuration natives ou non.....................................................................................................11 IV-B - La gestion de la rsolution de l'impression............................................................................................... 11 IV-C - L'aperu avant impression.........................................................................................................................12 IV-D - Le dcoupage en bande........................................................................................................................... 12 IV-E - Afficher la progression de l'impression......................................................................................................13 V - Les solutions retenues.........................................................................................................................................14 V-A - Botes de configuration d'impression natives ou non.................................................................................14 V-B - Gestion de la rsolution de l'impression.................................................................................................... 14 V-C - L'aperu avant impression......................................................................................................................... 20 V-C-1 - Rcuprer les informations sur l'cran.............................................................................................. 20 V-C-2 - Rcuprer les informations sur la feuille de papier........................................................................... 20 V-C-3 - Emuler l'impression sur l'cran..........................................................................................................25 V-C-4 - L'impression par bande..................................................................................................................... 31 V-C-5 - Affichage de la progression............................................................................................................... 32 V-C-5-a - Le thread d'impression.............................................................................................................. 36 V-C-6 - La bote d'impression.........................................................................................................................36

-2Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

I - Remerciements
Avant tout, je tiens faire divers remerciements : Au site Developpez.com d'offrir nous autres, dveloppeurs francophones, un formidable espace de communications et d'informations. A Ricky81 pour le temps qu'il m'a consacr en tant que responsable java. A RideKick et Xavlours pour leur relecture attentive de cet article.

II - Avant-propos
Ce document n'est pas une documentation officielle mais plutt le fruit de recherches individuelles pour arriver obtenir une impression de qualit en Java. Ce document ne propose aucune solution cl en main mais uniquement des principes appliquer pour effectuer une impression de qualit en Java. Tout au long de ce document, du code est prsent. Ce code est issu d'un projet Netbeans de dmonstration dont les sources sont tlchargeables ici

-3Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

III - L'API java existante


Le but de ce chapitre est de prsenter succinctement l'API mise la disposition d'un dveloppeur voulant raliser une impression en Java. Ce n'est en aucun cas une documentation complte.

III-A - Quoi imprimer ?


Pour l'impression, il faut tout d'abord un contenu. Pour cela, Java propose plusieurs interfaces dont Printable.

III-A-1 - L'interface Printable


Cette interface ne dfinit qu'une seule mthode : Mthode de rendu d'une page imprimer.
int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException

Paramtres

graphics: Contexte graphique pour le rendu de la page imprimer. pageFormat: Informations sur le format de la page imprimer comme la taille et l'orientation. pageIndex: Index de la page imprimer

Valeur retourne

Retourne Printable.PAGE_EXISTS si le rendu de la page s'est bien droule et Printable.NO_SUCH_PAGE si pageIndex spcifie une page non existante.

Exceptions

PrinterException : Lance quand l'impression est interrompue.

Ainsi pour vouloir imprimer une page contenant un simple rectangle entourant la page, suivie d'une page contenant une ellipse de mme dimension, il suffit d'implmenter cette interface comme ceci :
import import import import import java.awt.Color; java.awt.Graphics; java.awt.print.PageFormat; java.awt.print.Printable; java.awt.print.PrinterException;

public class PrintRectangle implements Printable { /** Constructeur par dfaut de PrintRectangle */ public PrintRectangle() { } public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { // Par dfaut, retourne NO_SUCH_PAGE => la page n'existe pas int retValue = Printable.NO_SUCH_PAGE; switch(pageIndex){ case 0 : { // Dessin de la premire page // Rcupre la dimension de la zone imprimable double xLeft = pageFormat.getImageableX(); double yTop = pageFormat.getImageableY(); double width = pageFormat.getImageableWidth(); double height = pageFormat.getImageableHeight();

-4Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawRect((int)xLeft, (int)yTop, (int)width, (int)height); // La page est valide retValue = Printable.PAGE_EXISTS; break;

} case 1 : { // Dessin de la seconde page // Rcupre la dimension de la zone imprimable double xLeft = pageFormat.getImageableX(); double yTop = pageFormat.getImageableY(); double width = pageFormat.getImageableWidth(); double height = pageFormat.getImageableHeight(); // Dessine l'ellipse graphics.setColor(Color.BLACK); graphics.drawOval((int)xLeft, (int)yTop, (int)width, (int)height); // La page est valide retValue = Printable.PAGE_EXISTS; break;

} }

} } return retValue;

Cette implmentation teste d'abord l'index de la page imprimer transmis la mthode print. Pour la premire page (pageIndex = 0), les informations sur la zone imprimable de la page sont rcupres l'aide du paramtre pageFormat, puis un rectangle est dessin l'aide du contexte graphique transmis. La seconde page fait la mme opration en remplaant le rectangle par une ellipse. Aprs chaque page rendue, la mthode retourne la constante Printable.PAGE_EXISTS pour indiquer le bon droulement de l'impression. Dans le cas o l'index de page est invalide, il suffit de retourner Printable.NO_SUCH_PAGE.

II-A-2 - L'interface Pageable


Dans l'exemple prcdent, nous avons dfini un Printable grant 2 pages. Dans ce cas plusieurs pages, il est prfrable d'utiliser l'interface Pageable qui reprsente un conteneur de Printable o chaque page peut choisir son format d'impression. Cette interface dfinit 3 mthodes. Mthode qui retourne le nombre de pages imprimer.
int getNumberOfPages()

Valeur retourne

Retourne le nombre de pages imprimer ou Pageable.UNKOWN_NUMBER_OF_PAGES si ce nombre est indtermin.

Mthode qui retourne le format de page pour une page donne.


PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException

-5Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

Paramtres

pageIndex : Index de la page.

Valeur retourne

Retourne les informations sur la taille et l'orientation de la page souhaite pour cette page.

Exceptions

IndexOutOfBoundsException : Lance si pageIndex est erron..

Mthode qui retourne l'objet de rendu pour une page donne.


Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException

Paramtres

pageIndex : Index de la page.

Valeur retourne

Retourne l'objet de rendu pour cette page.

Exceptions

IndexOutOfBoundsException : Lance si pageIndex est erron..

III-B - Comment imprimer ? III-B-1 - La classe PrinterJob


Une fois dfini le contenu imprimer, il faut envoyer un travail d'impression un service d'impression. Cette tche est ralise par la classe PrinterJob.
import java.awt.print.PrinterException; import java.awt.print.PrinterJob; public class Main { /** Creates a new instance of Main */ public Main() { } /** * @param args the command line arguments */ public static void main(String[] args) { // Rcupre un PrinterJob PrinterJob job = PrinterJob.getPrinterJob(); // Dfinit son contenu imprimer job.setPrintable(new PrintRectangle()); // Affiche une bote de choix d'imprimante if (job.printDialog()){ try { // Effectue l'impression job.print(); } catch (PrinterException ex) { ex.printStackTrace(); } } }

-6Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

La classe PrinterJob n'a pas de constructeur accessible. De ce fait, une instance de cette classe est obtenue en appelant sa mthode statique getPrinterJob(). Une fois, cette instance obtenue il est possible : de lui affecter un contenu imprimer (setPrintable, setPageable,...). de demander l'utilisateur de choisir l'imprimante o imprimer (printDialog,...). d'effectuer l'impression par la mthode print.

En excutant, ce petit programme, vous devez voir apparatre cette bote de dialogue :

Cette bote est la bote standard de configuration d'impression de l'OS (ici Windows). Vous pouvez slectionner et configurer l'imprimante. En appuyant sur Ok, vous imprimez 2 pages (l'une avec un rectangle et l'autre avec une ellipse) sur l'imprimante. L'appui sur Annuler, annule videmment l'impression. Et voil, en quelques lignes de code, nous avons russi imprimer deux pages. Toutefois, toute la configuration de l'imprimante a t laisse au choix de l'utilisateur et c'est au rendu d'impression (l'implmentation de l'interface Printable) de s'adapter. Mais comment spcifier des prfrences pour l'impression ? La solution est d'utiliser les requtes d'impression ou PrintRequestAttribute.

III-B-1-a - Les PrintRequestAttribute ou requtes d'impression


Bases sur la notion d'Attribute, les requtes d'impression permettent aux dveloppeurs de contrler la configuration de l'impression. L'interface javax.print.attribute.Attribute dfinit deux mthodes : Mthode qui retourne la catgorie de cet attribut.

-7Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton Class< ? extends Attribute> getCategory()

Valeur retourne

Retourne la classe de la catgorie de cet attribut.

Mthode qui retourne le nom de la catgorie de cet attribut.


String getName()

Valeur retourne

Retourne le nom de la catgorie de cet attribut.

Ces attributs peuvent tre rangs dans un javax.print.attribute.AttributeSet o il ne peut y avoir au mme instant qu'une seule (ou zro) valeur d'une catgorie donne. Par exemple, si on prend la catgorie javax.print.attribute.standard.Chromacity qui est la catgorie pour le choix entre l'impression noir & blanc et l'impression couleur. Cette catgorie ne contient que deux instances possibles : Chromacity.MONOCHROM et Chromacity.COLOR. Alors ces deux choix ne peuvent cohabiter dans un mme set d'attributs ; c'est l'un ou l'autre ou aucun. Cette notion tant utilise plusieurs endroits dans l'API d'impression de java, des familles d'attributs permettent de spcialiser les attributs pour des fonctions spcifiques. Ces familles sont matrialises par un hritage de l'interface Attribute : DocAttribute : Catgorie d'attributs de configuration d'un document (notion non aborde ici) PrintJobAttribute : Catgorie d'attributs pour obtenir le statut ou d'autres caractristiques d'un travail d'impression. PrintRequestAttribute : Catgorie d'attributs pour configurer une impression. PrintServiceAttribute : Catgorie d'attributs pour obtenir un statut ou d'autres caractristiques d'un service d'impression (Un service d'impression peut tre assimil une imprimante) SupportedValuesAttribute : Catgorie d'attributs pour rcuprer les valeurs supportes par une autre catgorie d'attributs. Par exemple, il est possible de connatre les rsolutions supportes par une imprimante.

Modifions l'exemple prcdent :


import import import import java.awt.print.PrinterException; java.awt.print.PrinterJob; javax.print.attribute.HashPrintRequestAttributeSet; javax.print.attribute.standard.OrientationRequested;

/** * * */ public class Main2 { /** Constructeur par dfaut de Main2 */ public Main2() { } /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here PrinterJob job = PrinterJob.getPrinterJob(); HashPrintRequestAttributeSet printRequestSet = new HashPrintRequestAttributeSet(); printRequestSet.add(OrientationRequested.LANDSCAPE);

-8Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton job.setPrintable(new PrintRectangle()); if (job.printDialog(printRequestSet)){ try { job.print(); } catch (PrinterException ex) { ex.printStackTrace(); } }

Excutons-le. La bote suivante s'affiche :

Ce n'est plus du tout la bote de dialogue native du systme mais au contraire une bote spcifique Java. Si on peut encore choisir l'imprimante, le bouton proprits est gris. Par contre, on peut voir dans l'onglet Mise en page que la demande d'impression en paysage a bien t prise en compte.

-9Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

De plus quand l'utilisateur clique sur imprimer, le set de requtes transmis la mthode printDialog est mis jour automatiquement pour reflter les choix de l'utilisateur. Il est donc possible ce stade de connatre ces choix pour, par exemple, afficher un aperu avant impression. Par contre, cette bote ne permet plus de configurer les attributs spcifiques une imprimante comme la sortie d'une page de garde, de l'agrafage des pages, etc...

- 10 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

IV - Les problmes rencontrs


Dans le chapitre prcdent, nous avons vu brivement comment imprimer en Java. Ce chapitre numre les diffrents problmes et lacunes que j'ai pu rencontrer lors de l'impression.

IV-A - Botes de configuration natives ou non


Nous avons vu que la mthode printDialog affiche deux botes diffrentes en fonction de la prsence ou non d'un set de requtes. Ne peut-on pas spcifier un set de requtes et conserver la bote de configuration native qui est plus complte ?

IV-B - La gestion de la rsolution de l'impression


En consultant la documentation de PageFormat, on constate que toutes les mthodes retournent des mesures en 1/72 de pouce soit du 72 DPI. Faisons le petit test suivant :
import import import import import import java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; java.awt.print.PageFormat; java.awt.print.Printable; java.awt.print.PrinterException;

public class PrintResolution implements Printable { /** Constructeur par dfaut de PrintResolution */ public PrintResolution () { } public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { int retValue = Printable.NO_SUCH_PAGE; if (pageIndex == 0){ Graphics2D g2d = (Graphics2D)graphics; // Device String text = "Taille du device : " + g2d.getDeviceConfiguration().getBounds().toString(); graphics.drawString(text, (int)(pageFormat.getImageableX()), (int) (pageFormat.getImageableY()+pageFormat.getImageableHeight()/3.0)); // clipping text = "Taille du clipping : " + g2d.getClipBounds().toString(); graphics.drawString(text, (int)(pageFormat.getImageableX()), (int) (pageFormat.getImageableY()+pageFormat.getImageableHeight()/2.0)); // imageable Rectangle rect = new Rectangle((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY(), (int)pageFormat.getImageableWidth(), (int)pageFormat.getImageableHeight()); text = "Taille de l'imageable : " + rect.toString(); graphics.drawString(text, (int)(pageFormat.getImageableX()), (int) (pageFormat.getImageableY()+2.0*pageFormat.getImageableHeight()/3.0)); retValue = PAGE_EXISTS; } return retValue; } }

Pour une impression configure en 600 DPI, nous pouvons avoir le rsultat suivant (en fonction des marges acceptes par l'imprimante) :
- 11 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

Taille du device : java.awt.Rectangle[x=0,y=0,width=4960,height=7015] Taille du clipping : java.awt.Rectangle[x=0,y=0,width=595,height=842] Taille de l'imageable : java.awt.Rectangle[x=0,y=0,width=594,height=841]

Ainsi le contexte graphique transmis la mthode print est toujours configur en 72 DPI, c'est--dire qu'une ligne de 72 pixels de long aura pour longueur un pouce sur la feuille. Pourtant l'utilisateur a demand une impression en 600 DPI. Comment faire pour respecter cette rsolution ? Ce choix de rsolution fixe 72 DPI s'explique facilement pour la gestion des polices de caractres ; toutes les tailles de police en java tant exprimes en points c'est--dire en 1/72 de pouce. Cette gestion de la taille de police pose un problme si l'affichage a lieu une autre rsolution que les fameux 72 DPI. Ainsi, pour un affichage en 72 DPI, une police de 12 points a donc une hauteur de 12 pixels. Les contextes graphiques de java considrent automatiquement que la rsolution d'affichage est de 72 DPI. Pour obtenir un affichage une rsolution autre, il faudra donc retailler le texte en fonction ; dans une rsolution de 600 DPI, une police de 12 points a une hauteur de : 1 pouce => 600 pixels => 72 points 0.1667 pouces => 100 pixels => 12 points Remarque : Ce problme de taille de caractres survient mme l'cran. En effet, sous Windows, la rsolution native de l'cran est du 96 DPI voire plus alors que les contextes java se considrent en 72 DPI. C'est pourquoi une police de 12 points java est plus petite qu'une police 12 points systme comme y rpond l'extrait de la FAQ de Sun ci-dessous : Q: Why does (eg) a 10 pt font in Java applications appear to have a different size from the same font at 10pt in a native application? A: Conversion from the size in points into device pixels depends on device resolution as reported by the platform APIs. Java 2D defaults to assuming 72 dpi. Platform defaults vary. Mac OS also uses 72 dpi. Linux desktops based on GTK (Gnome) or Qt (KDE) typically default to 96 dpi and let the end-user customise what they want to use. Windows defaults to 96 dpi (VGA resolution) and also offers 120 dpi (large fonts size) and lets users further specify a custom resolution. So a couple of things can now be seen * The DPI reported by platform APIs likely has no correspondence to the true DPI of the display device * Its unlikely that Java 2D's default matches the platform default. So a typical results is that for Window's default 96 DPI that a 10 pt font in a Java application is 72/96 of the size of the native counterpart. Note that Swing's Windows and GTK L&Fs do scale fonts based on the system DPI to match the desktop. If you want to do the same in your application you can call java.awt.Toolkit.getScreenResolution() and use this to apply a simple scale to the size you specify for fonts. http://java.sun.com/products/java-media/2D/reference/faqs/ index.html#Q_What_are_the_different_ways_th

IV-C - L'aperu avant impression


Java ne propose aucune API pour afficher un aperu avant impression c'est--dire muler l'affichage d'une page imprime en 600 DPI monochrome par exemple, sur un cran en 96 DPI couleur.

IV-D - Le dcoupage en bande


Une page A4 en 600 DPI atteint des dimensions de l'ordre de 5000x7000 pixels. Ces tailles peuvent tre trs coteuses en mmoire pour imprimer des images par exemple. L'impression doit donc dcouper en bandes l'image finale pour se cantonner des dimensions ngligeables en mmoire.
- 12 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

IV-E - Afficher la progression de l'impression


Une impression n'est pas une opration rapide. Il faut donc informer l'utilisateur de la progression de celle-ci. Il n'est pas superflu non plus d'offrir l'utilisateur la possibilit d'annuler l'impression.

- 13 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

V - Les solutions retenues V-A - Botes de configuration d'impression natives ou non


En effectuant un peu de dbogage sur les printJob aprs un appel la mthode printDialog, j'ai dcouvert qu'un attribut tait ajout dans les requtes et qui visiblement pilote la bote affiche. C'est l'attribut de catgorie sun.print.DialogTypeSelection. Cette catgorie possde deux valeurs possibles : DialogTypeSelection.COMMON : Pour les botes d'impression swing. DialogTypeSelection.NATIVE : Pour les botes d'impression natives.

Ainsi, en modifiant un peu le code comme ceci :


import import import import import java.awt.print.PrinterException; java.awt.print.PrinterJob; javax.print.attribute.HashPrintRequestAttributeSet; javax.print.attribute.standard.OrientationRequested; sun.print.DialogTypeSelection;

public class Main4 { /** Constructeur par dfaut de Main2 */ public Main4() { } /** * @param args the command line arguments */ public static void main(String[] args) { PrinterJob job = PrinterJob.getPrinterJob(); HashPrintRequestAttributeSet printRequestSet = new HashPrintRequestAttributeSet(); printRequestSet.add(OrientationRequested.LANDSCAPE); printRequestSet.add(DialogTypeSelection.NATIVE); job.setPrintable(new PrintRectangle()); if (job.printDialog(printRequestSet)){ try { job.print(); } catch (PrinterException ex) { ex.printStackTrace(); } }

Nous obtenons la bote d'impression native au prix de quelques warnings lors de la compilation : warning: sun.print.DialogTypeSelection is Sun proprietary API and may be removed in a future release Au dveloppeur de voir s'il accepte un jour de revoir son code quand celui-ci ne sera plus support par Sun.

V-B - Gestion de la rsolution de l'impression


Comme nous avons vu dans la partie de prsentation de cette problmatique, le contexte graphique transmis la mthode print d'un printable est automatiquement configur en 72 DPI. Toutefois, en interrogeant la configuration de ce contexte (getDeviceConfiguration), il est possible d'obtenir la vraie rsolution. Comment passer de la configuration 72 DPI la configuration rsolution relle ?

- 14 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

Tout est dans la transformation associe au contexte graphique. Par dfaut, elle est donc configure pour une sortie en 72 DPI en respectant les marges d'impression ainsi que l'orientation de la feuille. Le dveloppeur doit donc tout reconfigurer : Associer au contexte graphique une transformation identit pour passer en mode 1 unit graphique = 1 pixels. Effectuer une ventuelle rotation pour respecter l'orientation de la feuille (portrait/paysage) Effectuer une translation pour respecter les marges d'impression
import import import import import import import import import java.awt.Color; java.awt.Font; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; java.awt.geom.AffineTransform; java.awt.print.PageFormat; java.awt.print.Printable; java.awt.print.PrinterException;

public class PrintRectangleRes implements Printable { // Rsolution d'un contexte graphique Java private static final double JAVA_DPI = 72.0; // Police d'affichage du texte private Font font = new Font(Font.MONOSPACED, Font.BOLD, 16); /** Constructeur par dfaut de PrintRectangle */ public PrintRectangleRes() { } /** * Mthode qui restaure le contexte graphique dans sa rsolution relle. * * @param graphics le contexte graphique * @param pageFormat information sur le format de la page * @return le rectangle de la zone imprimable dans la rsolution relle */ protected Rectangle restoreRealDpi(Graphics2D graphics, PageFormat pageFormat){ Rectangle retValue = new Rectangle(); // Dtermine la rsolution relle Rectangle deviceBounds = graphics.getDeviceConfiguration().getBounds(); double pageWidth72Dpi = pageFormat.getWidth(); double pageHeight72Dpi = pageFormat.getHeight(); double widthResolution = (JAVA_DPI * deviceBounds.getWidth())/pageWidth72Dpi; double heightResolution = (JAVA_DPI * deviceBounds.getHeight())/pageHeight72Dpi; // Dtermine les dimensions relles de la zone imprimable double realImageableX = (pageFormat.getImageableX()*widthResolution)/ JAVA_DPI; double realImageableWidth = (pageFormat.getImageableWidth()*widthResolution)/ JAVA_DPI; double realImageableY = (pageFormat.getImageableY()*heightResolution)/ JAVA_DPI; double realImageableHeight = (pageFormat.getImageableHeight()*heightResolution)/ JAVA_DPI; // Modifie la transformation du contexte graphique graphics.setTransform(new AffineTransform()); // Passe en rsolution relle switch (pageFormat.getOrientation()){ case PageFormat.LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; - 15 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton realImageableHeight = temp; // Effectue la rotation graphics.rotate(-Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(-realImageableWidth + realImageableX, realImageableY); break;

} case PageFormat.REVERSE_LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; realImageableHeight = temp;

} retValue.x retValue.y retValue.width retValue.height }

} default : { // Mode portrait // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY); } = = = = (int)Math.ceil(realImageableX); (int)Math.ceil(realImageableY); (int)Math.floor(realImageableWidth); (int)Math.floor(realImageableHeight);

// Effectue la rotation graphics.rotate(Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY - realImageableHeight); break;

return retValue;

public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { // Par dfaut, retourne NO_SUCH_PAGE => la page n'existe pas int retValue = Printable.NO_SUCH_PAGE; switch(pageIndex){ case 0 : { // Restaure la rsolution relle Rectangle margin = restoreRealDpi((Graphics2D)graphics, pageFormat); // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawRect(0, 0, margin.width, margin.height); // Affiche les marges graphics.setFont(font); graphics.drawString(margin.toString(), 0, margin.height/2); // La page est valide retValue = Printable.PAGE_EXISTS; break;

} case 1 : { // Dessin de la seconde page // Restaure la rsolution relle Rectangle margin = restoreRealDpi((Graphics2D)graphics, pageFormat); // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawOval(0, 0, margin.width, margin.height); - 16 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton // Affiche les marges graphics.setFont(font); graphics.drawString(margin.toString(), 0, margin.height/2); // La page est valide retValue = Printable.PAGE_EXISTS; break;

} } return retValue;

L'implmentation d'un Printable ci-dessus ajoute la mthode restoreRealDpi qui s'occupe de configurer le contexte graphique en rsolution relle. Si l'affichage des figures gomtriques est correct, l'affichage du texte dpend fortement de la rsolution. Plus la rsolution est leve, plus le texte est petit alors que dans le code sa taille est constante (16 points). Ce fonctionnement est tout fait normal pour Java puisque celui-ci considre toujours que la rsolution est de 72 DPI pour l'affichage du texte. Il faut donc fournir des mthodes pour afficher du texte une rsolution donne. C'est l que les choses se compliquent. En interne, les contextes graphiques java utilisent une transformation spcifique pour l'affichage du texte, malheureusement cette transformation est en lecture seule. Il nous faut donc effectuer le rendu du texte nous mme. Heureusement, les polices java nous permettent de rcuprer des GlyphVector qu'il est possible d'afficher ensuite comme si cela tait une gomtrie quelconque.
import import import import import import import import import import import import import java.awt.Color; java.awt.Font; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; java.awt.font.FontRenderContext; java.awt.font.GlyphVector; java.awt.font.TextLayout; java.awt.geom.AffineTransform; java.awt.geom.Point2D; java.awt.print.PageFormat; java.awt.print.Printable; java.awt.print.PrinterException;

public class PrintRectangleResText implements Printable { // Rsolution d'un contexte graphique Java private static final double JAVA_DPI = 72.0; // Police d'affichage du texte private Font font = new Font(Font.MONOSPACED, Font.BOLD, 16); // Rsolution de l'impression private int resolution = 72; /** Constructeur par dfaut de PrintRectangle */ public PrintRectangleResText() { } /** * Mthode qui restaure le contexte graphique dans sa rsolution relle. * * @param graphics le contexte graphique * @param pageFormat information sur le format de la page * @return le rectangle de la zone imprimable dans la rsolution relle */ protected Rectangle restoreRealDpi(Graphics2D graphics, PageFormat pageFormat){ Rectangle retValue = new Rectangle(); // Dtermine la rsolution relle Rectangle deviceBounds = graphics.getDeviceConfiguration().getBounds(); - 17 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton double pageWidth72Dpi = pageFormat.getWidth(); double pageHeight72Dpi = pageFormat.getHeight(); double widthResolution = (JAVA_DPI * deviceBounds.getWidth())/pageWidth72Dpi; double heightResolution = (JAVA_DPI * deviceBounds.getHeight())/pageHeight72Dpi; // Dtermine la rsolution pour l'affichage du texte resolution = (int)Math.round((widthResolution + heightResolution)/2.0); // Dtermine les dimensions relle de la zone imprimable double realImageableX = (pageFormat.getImageableX()*widthResolution)/ JAVA_DPI; double realImageableWidth = (pageFormat.getImageableWidth()*widthResolution)/ JAVA_DPI; double realImageableY = (pageFormat.getImageableY()*heightResolution)/ JAVA_DPI; double realImageableHeight = (pageFormat.getImageableHeight()*heightResolution)/ JAVA_DPI; // Modifie la transformation du contexte graphique graphics.setTransform(new AffineTransform()); // Passe en rsolution relle switch (pageFormat.getOrientation()){ case PageFormat.LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; realImageableHeight = temp; // effectue la rotation graphics.rotate(-Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(-realImageableWidth + realImageableX, realImageableY); break;

} case PageFormat.REVERSE_LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; realImageableHeight = temp;

} retValue.x retValue.y retValue.width retValue.height }

} default : { // Mode portrait // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY); } = = = = (int)Math.ceil(realImageableX); (int)Math.ceil(realImageableY); (int)Math.floor(realImageableWidth); (int)Math.floor(realImageableHeight);

// effectue la rotation graphics.rotate(Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY - realImageableHeight); break;

return retValue;

/** * Affiche du texte indpendamment de la rsolution * * @param graphics le contexte graphics * @param text le texte afficher - 18 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton * @param x l'abscisse o placer le texte * @param y l'ordonne o placer le texte */ public void printText(Graphics2D graphics, String text, int x, int y){ Font currentFont = graphics.getFont(); // Calcul l'chelle du texte double fontScale = ((double)(resolution*currentFont.getSize()))/(JAVA_DPI * 72.0); // transformation de la police AffineTransform fontShapeTransform = new AffineTransform(); fontShapeTransform.setToScale(fontScale, fontScale); // Font de rcupration de glyph vector Font computeFont = new Font(currentFont.getName(), currentFont.getStyle(), 72); // Font de calcul de largeur d'un caractre => ignore le flag italique Font sizeFont = computeFont; if (font.isItalic()) { sizeFont = new Font(currentFont.getFontName(), currentFont.getStyle()-Font.ITALIC, 72); } // La position courante du texte Point2D.Double textPos = new Point2D.Double(x, y); // Rcupre le contexte de rendu de police FontRenderContext frc = graphics.getFontRenderContext(); // On boucle sur chaque caractres char[] carIterator = new char[1]; int textLength = text.length(); for (int i = 0; i < textLength; i++) { // rcupre le caractre courant text.getChars(i, i+1, carIterator, 0); // Rcupre le glyph de ce caractre pour la police de calcul GlyphVector glyph = computeFont.createGlyphVector(frc, carIterator); graphics.translate(textPos.x, textPos.y); glyph.setGlyphTransform(0, fontShapeTransform); graphics.drawGlyphVector(glyph, 0.f, 0.f); graphics.translate(-textPos.x, -textPos.y); // Incrmente la position du texte TextLayout layout = new TextLayout(new String(carIterator), sizeFont, frc); textPos.x += (double)layout.getAdvance()* fontScale;

public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { // Par dfaut, retourne NO_SUCH_PAGE => la page n'existe pas int retValue = Printable.NO_SUCH_PAGE; switch(pageIndex){ case 0 : { Graphics2D g2d = (Graphics2D)graphics; // Restaure la rsolution relle Rectangle margin = restoreRealDpi(g2d, pageFormat); // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawRect(0, 0, margin.width, margin.height); // Affiche les marges graphics.setFont(font); printText(g2d, margin.toString(), 0, margin.height/2); // La page est valide retValue = Printable.PAGE_EXISTS; break;

- 19 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton case 1 : { // Dessin de la seconde page Graphics2D g2d = (Graphics2D)graphics; // Restaure la rsolution relle Rectangle margin = restoreRealDpi(g2d, pageFormat); // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawOval(0, 0, margin.width, margin.height); // Affiche les marges graphics.setFont(font); printText(g2d, margin.toString(), 0, margin.height/2); // La page est valide retValue = Printable.PAGE_EXISTS; break;

} } return retValue;

Dans l'exemple ci-dessus, toute la gestion de l'affichage du texte est contenue dans la mthode printText. Le principe de cette mthode est de rcuprer un GlyphVector d'une fonte de rfrence. Ici, la police de rfrence a une taille de 72 points pour une rsolution de 72 DPI. Ensuite une transformation de mise l'chelle est applique cette fonte de rfrence pour l'afficher la taille voulue. Dans un premier temps, le facteur de mise l'chelle est dtermin. Nous souhaitons afficher une police de taille fontSize une rsolution donne resolution partir d'une police de taille 72 points pour une rsolution de 72 DPI. Ainsi : fontScale = (fontSize * resolution)/ (72 * 72) Ensuite pour chaque caractre du texte afficher, on rcupre son GlyphVector pour la police de rfrence que l'on positionne et retaille la taille voulue. Pour calculer l'espacement entre chaque caractre, un TextLayout est utilis. A noter, qu'il faut ignorer l'attribut italique qui fausse ce calcul.

V-C - L'aperu avant impression


L'aperu avant impression consiste afficher l'cran une image destine tre rendue sur une feuille de papier. Pour cela, il nous faut : Des informations sur la dimension et la rsolution de la fentre d'affichage de l'cran. Des informations sur la dimension et la rsolution de la feuille de papier. Emuler l'affichage de la feuille de papier l'cran

V-C-1 - Rcuprer les informations sur l'cran


L'aperu sera rendu grce un JComponent et sa mthode paint. La rcupration de la dimension de ce composant ne pose donc aucun souci. Il suffit d'appeler la mthode getSize(). Pour la rsolution cran, elle est tout simplement retourne par un appel java.awt.Toolkit.getDefaultToolkit().getScreenResolution().

V-C-2 - Rcuprer les informations sur la feuille de papier


Ces informations sont directement issues du choix de l'utilisateur pour la configuration de l'imprimante. Nous avons vu qu'il est possible de rcuprer les choix de l'utilisateur aprs une configuration de l'imprimante grce aux requtes d'impression. Il nous suffit d'encapsuler les paramtres importants nos yeux dans une instance d'une classe PrintParameters que nous mettrons jour aprs chaque modification de la configuration d'impression.

- 20 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

import import import import import import import import import import import import import import

java.awt.geom.Rectangle2D; java.awt.print.PageFormat; java.awt.print.PrinterException; java.awt.print.PrinterJob; java.util.logging.Level; java.util.logging.Logger; javax.print.PrintService; javax.print.PrintServiceLookup; javax.print.attribute.HashPrintRequestAttributeSet; javax.print.attribute.PrintRequestAttributeSet; javax.print.attribute.standard.Chromaticity; javax.print.attribute.standard.MediaPrintableArea; javax.print.attribute.standard.OrientationRequested; javax.print.attribute.standard.PrinterResolution;

/** * * */ public class PrintParameters { /** * Les dimensions de la feuille de papier en inches */ private Rectangle2D.Double paperArea; /** * Les marges imprimables en inches */ private Rectangle2D.Double printableArea; /** * La rsolution en DPI */ private int DPI; /** * L'orientation du papier */ private OrientationRequested orientation; /** * Les attributs de la requte d'impression courante */ private PrintRequestAttributeSet attributes; /** * Le service d'impression (ou imprimante) slectionn */ private PrintService printService; /** * Indique si l'impression est en couleur ou non */ private boolean monochrom; public PrintParameters(){ this(new HashPrintRequestAttributeSet(), PrintServiceLookup.lookupDefaultPrintService()); } public PrintParameters(PrintRequestAttributeSet attributesSet, PrintService printService){ try { this.attributes = attributesSet; this.printService = printService; // Rcupre la rsolution PrinterResolution res = (PrinterResolution) attributesSet.get(PrinterResolution.class); if (res == null) { res = (PrinterResolution) printService.getDefaultAttributeValue(PrinterResolution.class); } DPI = res.getResolution(PrinterResolution.DPI)[0];

- 21 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton // Rcupre l'orientation orientation = (OrientationRequested)attributesSet.get(OrientationRequested.class); if (orientation == null){ orientation = (OrientationRequested)printService.getDefaultAttributeValue(OrientationRequested.class); } // Dtermine les dimensions de la feuille et des marges PrinterJob printerJob = PrinterJob.getPrinterJob(); printerJob.setPrintService(printService); // Rcupre les marges physiques de l'imprimante float [] physicalMargin; MediaPrintableArea printableZone = (MediaPrintableArea)attributesSet.get(MediaPrintableArea.class); if (printableZone == null){ printableZone = (MediaPrintableArea)printService.getDefaultAttributeValue(MediaPrintableArea.class); } PageFormat pageFormat = printerJob.getPageFormat(attributesSet);

double paperWidth = pageFormat.getWidth() / 72.0; double paperHeight = pageFormat.getHeight() / 72.0; if (printableZone == null){ physicalMargin = new float[4]; physicalMargin[0] = 0.0f; physicalMargin[1] = 0.0f; physicalMargin[2] = (float)paperWidth; physicalMargin[3] = (float)paperHeight; } else { physicalMargin = printableZone.getPrintableArea(MediaPrintableArea.INCH); } if (orientation.equals(OrientationRequested.LANDSCAPE) ||orientation.equals(OrientationRequested.REVERSE_LANDSCAPE)) // Inversion des marges physiques float temp = physicalMargin[0]; physicalMargin[0] = physicalMargin[1]; physicalMargin[1] = temp; temp = physicalMargin[2]; physicalMargin[2] = physicalMargin[3]; physicalMargin[3] = temp; } // Calcul des diffrences physicalMargin[2] = (float)(paperWidth - (physicalMargin[2] + physicalMargin[0])); physicalMargin[3] = (float)(paperHeight - (physicalMargin[3] + physicalMargin[1])); double xMargin = (pageFormat.getImageableX() / 72.0) + physicalMargin[0]; double yMargin = (pageFormat.getImageableY() / 72.0) + physicalMargin[1]; double imageWidth = (pageFormat.getImageableWidth() / 72.0) - (physicalMargin[0] + physicalMargin[2]); double imageHeight = (pageFormat.getImageableHeight() / 72.0) - (physicalMargin[1] + physicalMargin[3]); paperArea = new Rectangle2D.Double(0.0, 0.0, paperWidth, paperHeight); printableArea = new Rectangle2D.Double(xMargin, yMargin, imageWidth, imageHeight); // La gestion de la couleur Chromaticity chromaticity = (Chromaticity) attributesSet.get(Chromaticity.class); if (chromaticity == null) { chromaticity = (Chromaticity) printService.getDefaultAttributeValue(Chromaticity.class); } monochrom = chromaticity.equals(Chromaticity.MONOCHROME); } catch (PrinterException ex) { Logger.getLogger(PrintParameters.class.getName()).log(Level.SEVERE, null, ex); }

/** - 22 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton * Retourne les dimensions de la feuille de papier en inches * * @return les dimensions de la feuille en inches */ public Rectangle2D.Double getPaperArea() { return paperArea; } /** * Retourne la zone imprimable en inches * @return la zone imprimable en inches */ public Rectangle2D.Double getPrintableArea() { return printableArea; } /** * Retourne la rsolution de l'impression en DPI * @return la rsolution de l'impression en DPI */ public int getDPI() { return DPI; } /** * Indique si l'impression est en couleur ou monochrome * @return true si l'impression est monochrome */ public boolean isMonochrom() { return monochrom; } /** * Retourne l'orientation de la feuille * @return l'orientation de la feuille */ public OrientationRequested getOrientation() { return orientation; } /** * Retourne les requtes d'impression courantes * * @return les requtes d'impression courantes */ protected PrintRequestAttributeSet getAttributes() { return attributes; } /** * Retourne le service d'impression slectionn * * @return le service d'impression slectionn */ protected PrintService getPrintService() { return printService; }

Cette classe est un simple conteneur non mutable o tous les champs sont initialiss dans le constructeur. Elle possde deux constructeurs : Un constructeur qui utilise un service d'impression et un set de requte. Un constructeur par dfaut qui appelle le prcdent en lui passant le service d'impression par dfaut et un set de requtes vide.

Cette classe contient :

- 23 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

La dimension de la feuille en pouces Les marges d'impression en pouces L'orientation de la feuille La rsolution en DPI Un indicateur d'impression couleur ou noir et blanc

Dans cette classe, nous voyons comment rcuprer des informations partir d'un service d'impression et d'un set de requtes. Tous les attributs rpondant sur le mme principe, nous dcrivons seulement la rcupration de la rsolution.
PrinterResolution res = (PrinterResolution) attributesSet.get(PrinterResolution.class); if (res == null) { res = (PrinterResolution) printService.getDefaultAttributeValue(PrinterResolution.class); } int DPI = res.getResolution(PrinterResolution.DPI)[0];

On teste la prsence d'un attribut de la catgorie PrinterResolution dans le set de requtes. Si aucun attribut n'existe, alors on interroge le service d'impression pour rcuprer sa rsolution par dfaut. Ensuite la rsolution est extraite de l'attribut retourn. A partir de cette classe, il est facile de stocker les paramtres d'impression.
import import import import import java.awt.print.PrinterException; java.awt.print.PrinterJob; javax.print.attribute.HashPrintRequestAttributeSet; javax.print.attribute.standard.OrientationRequested; sun.print.DialogTypeSelection;

/** * * */ public class Main7 { /** Constructeur par dfaut de Main7 */ public Main7() { } /** * @param args the command line arguments */ public static void main(String[] args) { PrinterJob job = PrinterJob.getPrinterJob(); HashPrintRequestAttributeSet printRequestSet = new HashPrintRequestAttributeSet(); printRequestSet.add(DialogTypeSelection.NATIVE); job.setPrintable(new PrintRectangleResText()); if (job.printDialog(printRequestSet)){ PrintParameters params = new PrintParameters(printRequestSet, job.getPrintService()); System.out.println("L'utilisateur a choisi d'imprimer sur " + job.getPrintService().getName()); System.out.println(String.format(" la rsolution est de : %s DPI",params.getDPI())); if (params.getOrientation().equals(OrientationRequested.PORTRAIT)){ System.out.println(" mode PORTRAIT"); } else { System.out.println(" mode PAYSAGE"); } } }

- 24 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

V-C-3 - Emuler l'impression sur l'cran


A ce stade, nous disposons de toutes les informations ncessaires pour effectuer un aperu avant impression.
import import import import import import import import import import import import import import import import java.awt.Color; java.awt.Dimension; java.awt.Font; java.awt.Graphics; java.awt.Graphics2D; java.awt.Rectangle; java.awt.Toolkit; java.awt.font.FontRenderContext; java.awt.font.GlyphVector; java.awt.font.TextLayout; java.awt.geom.AffineTransform; java.awt.geom.Point2D; java.awt.geom.Rectangle2D; java.awt.print.PageFormat; java.awt.print.Printable; java.awt.print.PrinterException;

public class PrintRectangleResTextPreview implements Printable { // Rsolution d'un contexte graphique Java private static final double JAVA_DPI = 72.0; // Police d'affichage du texte private Font font = new Font(Font.MONOSPACED, Font.BOLD, 16); // Rsolution de l'impression private int resolution = 72; /** Constructeur par dfaut de PrintRectangle */ public PrintRectangleResTextPreview() { } /** * Mthode qui restaure le contexte graphique dans sa rsolution relle. * * @param graphics le contexte graphique * @param pageFormat information sur le format de la page * @return le rectangle de la zone imprimable dans la rsolution relle */ protected Rectangle restoreRealDpi(Graphics2D graphics, PageFormat pageFormat){ Rectangle retValue = new Rectangle(); // Dtermine la rsolution relle Rectangle deviceBounds = graphics.getDeviceConfiguration().getBounds(); double pageWidth72Dpi = pageFormat.getWidth(); double pageHeight72Dpi = pageFormat.getHeight(); double widthResolution = (JAVA_DPI * deviceBounds.getWidth())/pageWidth72Dpi; double heightResolution = (JAVA_DPI * deviceBounds.getHeight())/pageHeight72Dpi; // Dtermine la rsolution pour l'affichage du texte resolution = (int)Math.round((widthResolution + heightResolution)/2.0); // Dtermine les dimensions relle de la zone imprimable double realImageableX = (pageFormat.getImageableX()*widthResolution)/ JAVA_DPI; double realImageableWidth = (pageFormat.getImageableWidth()*widthResolution)/ JAVA_DPI; double realImageableY = (pageFormat.getImageableY()*heightResolution)/ JAVA_DPI; double realImageableHeight = (pageFormat.getImageableHeight()*heightResolution)/ JAVA_DPI; // Modifie la transformation du contexte graphique graphics.setTransform(new AffineTransform()); // Passe en rsolution relle switch (pageFormat.getOrientation()){ - 25 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton case PageFormat.LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; realImageableHeight = temp; // Effectue la rotation graphics.rotate(-Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(-realImageableWidth + realImageableX, realImageableY); break;

} case PageFormat.REVERSE_LANDSCAPE : { // Les marges retournes par pageFormat prennent en compte la rotation // Il faut les inverser double temp = realImageableX; realImageableX = realImageableY; realImageableY = temp; temp = realImageableWidth; realImageableWidth = realImageableHeight; realImageableHeight = temp;

} retValue.x retValue.y retValue.width retValue.height }

} default : { // Mode portrait // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY); } = = = = (int)Math.ceil(realImageableX); (int)Math.ceil(realImageableY); (int)Math.floor(realImageableWidth); (int)Math.floor(realImageableHeight);

// Effectue la rotation graphics.rotate(Math.PI / 2.0); // Translation pour s'aligner sur les marges graphics.translate(realImageableX, realImageableY - realImageableHeight); break;

return retValue;

/** * Affiche du texte indpendamment de la rsolution * * @param graphics le contexte graphics * @param text le texte afficher * @param x l'abscisse o placer le texte * @param y l'ordonne o placer le texte */ public void printText(Graphics2D graphics, String text, int x, int y){ Font currentFont = graphics.getFont(); // Calcul de l'chelle du texte double fontScale = ((double)(resolution*currentFont.getSize()))/(JAVA_DPI * 72.0); // Transformation de la police AffineTransform fontShapeTransform = new AffineTransform(); fontShapeTransform.setToScale(fontScale, fontScale); // Font de rcupration de glyph vector Font computeFont = new Font(currentFont.getName(), currentFont.getStyle(), 72); // Font de calcul de largeur d'un caractres => ignore le flag italique Font sizeFont = computeFont; if (font.isItalic()) { sizeFont = new Font(currentFont.getFontName(), currentFont.getStyle()-Font.ITALIC, 72); - 26 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton } // La position courante du texte Point2D.Double textPos = new Point2D.Double(x, y); // Rcupre le contexte de rendu de police FontRenderContext frc = graphics.getFontRenderContext(); // On boucle sur chaque caractres char[] carIterator = new char[1]; int textLength = text.length(); for (int i = 0; i < textLength; i++) { // rcupre le caractre courant text.getChars(i, i+1, carIterator, 0); // Rcupre le glyph de ce caractre pour la police de calcul GlyphVector glyph = computeFont.createGlyphVector(frc, carIterator); graphics.translate(textPos.x, textPos.y); glyph.setGlyphTransform(0, fontShapeTransform); graphics.drawGlyphVector(glyph, 0.f, 0.f); graphics.translate(-textPos.x, -textPos.y); // Incrmente la position TextLayout layout = new TextLayout(new String(carIterator), sizeFont, frc); textPos.x += (double)layout.getAdvance()* fontScale;

/** * Affiche du texte indpendamment de la rsolution * * @param graphics le contexte graphics * @param text le texte afficher * @param x l'abscisse o placer le texte * @param y l'ordonne o placer le texte */ public void printPreviewText(Graphics2D graphics, String text, int x, int y, int printDpi, double screenScale){ Font currentFont = graphics.getFont(); int screenDpi = Toolkit.getDefaultToolkit().getScreenResolution(); // Calcul l'chelle du texte double fontScale = ((double)(printDpi*currentFont.getSize()))/(double)(screenDpi * 72.0); // Transformation de la police AffineTransform fontShapeTransform = new AffineTransform(); fontShapeTransform.setToScale(fontScale*screenScale, fontScale*screenScale); // Font de rcupration de glyph vector Font computeFont = new Font(currentFont.getName(), currentFont.getStyle(), 72); // Font de calcul de largeur d'un caractres => ignore le flag italique Font sizeFont = computeFont; if (font.isItalic()) { sizeFont = new Font(currentFont.getFontName(), currentFont.getStyle()-Font.ITALIC, 72); } graphics.scale(1.0/screenScale,1.0/screenScale); // La position courante du texte Point2D.Double textPos = new Point2D.Double(x*screenScale, y*screenScale); // Rcupre le contexte de rendu de police FontRenderContext frc = graphics.getFontRenderContext(); // On boucle sur chaque caractre char[] carIterator = new char[1]; int textLength = text.length(); for (int i = 0; i < textLength; i++) { // Rcupre le caractre courant - 27 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton text.getChars(i, i+1, carIterator, 0); // Rcupre le glyph de ce caractre pour la police de calcul GlyphVector glyph = computeFont.createGlyphVector(frc, carIterator); glyph.setGlyphTransform(0, fontShapeTransform); graphics.translate(textPos.x, textPos.y); graphics.drawGlyphVector(glyph, 0.f, 0.f); graphics.translate(-textPos.x, -textPos.y); // Incrmente la position TextLayout layout = new TextLayout(new String(carIterator), sizeFont, frc); textPos.x += (double)layout.getAdvance()* fontScale*screenScale;

} }

graphics.scale(screenScale,screenScale);

public void preview(Graphics2D graphics, Dimension screenSize, PrintParameters printParameters){ // Taille de la feuille en pouce Rectangle2D.Double paperArea = printParameters.getPaperArea(); // Convertit en pixels int printDpi = printParameters.getDPI(); double paperAreaPixelsWidth = paperArea.width * printDpi; double paperAreaPixelsHeight = paperArea.height * printDpi; double xScaleRatio = screenSize.width / paperAreaPixelsWidth; double yScaleRatio = screenSize.height / paperAreaPixelsHeight; double projectionScale = xScaleRatio; if (yScaleRatio < xScaleRatio){ projectionScale = yScaleRatio; } int screenPageWidth = (int)(paperAreaPixelsWidth * projectionScale); int screenPageHeight = (int)(paperAreaPixelsHeight * projectionScale); int xScreenPageOffset = (screenSize.width - screenPageWidth)/2; int yScreenPageOffset = (screenSize.height - screenPageHeight)/2; // Dessine le fond du composant graphics.setColor(Color.DARK_GRAY); graphics.fillRect(0, 0, screenSize.width, screenSize.height); // Modifie la transformation graphics.translate(xScreenPageOffset, yScreenPageOffset); graphics.scale(projectionScale, projectionScale); // Dessine la feuille graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, (int)paperAreaPixelsWidth, (int)paperAreaPixelsHeight); // Dessine les marges Rectangle2D.Double margin = printParameters.getPrintableArea(); int xMargin = (int)(margin.x * printDpi); int yMargin = (int)(margin.y * printDpi); int widthMargin = (int)(margin.width * printDpi); int heightMargin = (int)(margin.height * printDpi); graphics.setColor(Color.LIGHT_GRAY); graphics.drawRect(xMargin, yMargin, widthMargin, heightMargin); // Dfinit le clipping graphics.setClip(xMargin, yMargin, widthMargin, heightMargin); - 28 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

graphics.setColor(Color.BLACK); graphics.drawOval(xMargin, yMargin, widthMargin, heightMargin); Rectangle marg = new Rectangle(xMargin, yMargin, widthMargin, heightMargin); graphics.setFont(font); printPreviewText(graphics, marg.toString(), xMargin, yMargin+heightMargin/2, printDpi, projectionScale);

public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { // Par dfaut, retourne NO_SUCH_PAGE => la page n'existe pas int retValue = Printable.NO_SUCH_PAGE; if (pageIndex==0){ Graphics2D g2d = (Graphics2D)graphics; // Restaure la rsolution relle Rectangle margin = restoreRealDpi(g2d, pageFormat); // Dessine le rectangle graphics.setColor(Color.BLACK); graphics.drawOval(0, 0, margin.width, margin.height); // Affiche les marges graphics.setFont(font); printText(g2d, margin.toString(), 0, margin.height/2); // La page est valide retValue = Printable.PAGE_EXISTS;

} return retValue;

import import import import import import import import import import import import import import import import

java.awt.BorderLayout; java.awt.Dimension; java.awt.FlowLayout; java.awt.Graphics; java.awt.Graphics2D; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.ComponentEvent; java.awt.event.ComponentListener; java.awt.print.PrinterException; java.awt.print.PrinterJob; javax.print.attribute.PrintRequestAttributeSet; javax.swing.JButton; javax.swing.JFrame; javax.swing.JPanel; sun.print.DialogTypeSelection;

public class Main8 extends JFrame{ private PrintParameters printParameters = new PrintParameters(); private PrintRectangleResTextPreview printableObject = new PrintRectangleResTextPreview(); private PreviewPanel previewPanel = new PreviewPanel(); /** Constructeur par dfaut de Main8 */ public Main8() { JPanel internalPanel = new JPanel(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); internalPanel.setLayout(new BorderLayout()); setTitle(printParameters.getPrintService().getName());

- 29 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); JButton configButton = new JButton("Configuration"); configButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PrinterJob job = PrinterJob.getPrinterJob(); PrintRequestAttributeSet attribSet = printParameters.getAttributes(); attribSet.add(DialogTypeSelection.NATIVE); try { job.setPrintService(printParameters.getPrintService()); if (job.printDialog(attribSet)){ printParameters = new PrintParameters(attribSet, job.getPrintService()); setTitle(printParameters.getPrintService().getName()); previewPanel.repaint(); } } catch (PrinterException ex) { ex.printStackTrace(); } } }); buttonPanel.add(configButton); JButton printButton = new JButton("Imprimer"); printButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(printableObject); job.setPrintService(printParameters.getPrintService()); job.print(printParameters.getAttributes()); } catch (PrinterException ex) { ex.printStackTrace(); } } }); buttonPanel.add(printButton); internalPanel.add(buttonPanel, BorderLayout.SOUTH); internalPanel.add(previewPanel, BorderLayout.CENTER); setContentPane(internalPanel); pack(); } /** * @param args the command line arguments */ public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Main8().setVisible(true); }

});

private class PreviewPanel extends JPanel{ PreviewPanel(){ addComponentListener(new ComponentListener() { public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { repaint(); } public void componentShown(ComponentEvent e) { repaint(); - 30 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton } }); setPreferredSize(new Dimension(400,400)); } public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Dimension size = getSize(); } } } printableObject.preview(g2d, size, printParameters);

Dans un premier temps, nous enrichissons la prcdente implmentation de Printable dans une nouvelle classe PrintRectangleResTextPreview. Deux mthodes ont t rajoutes : La mthode printPreviewText. La mthode preview

La mthode printPreviewText reprend la logique de la prcdente mthode printText en rajoutant la prise en compte du scaling associ au contexte graphique. A savoir que dans tout le corps de cette mthode, la mise l'chelle est resete (graphics.scale(1.0/screenScale,1.0/screenScale);) car l'object TextLayout, utilis pour calculer l'avance du texte, prend en compte cette mise l'chelle mais de manire discontinue (En interne, les tailles de polices doivent tre arrondies au point prs). En annulant cette transformation, nous prenons entirement la main sur la taille de la police souhaite et sur son avance. La mthode preview dtermine la mise l'chelle ncessaire pour effectuer le preview et modifie la transformation du contexte graphique pour muler le bon affichage. Elle s'occupe aussi d'afficher la page blanche ainsi que les marges d'impression. Pour tester l'aperu avant impression, une petite application base sur une JFrame a t cre. Le comportement de cette application repose sur : Une instance printParameters de PrintParameters qui contiennent la configuration d'impression actuellement slectionne. Ces paramtres sont remis jour lors d'un changement de configuration et utilis pour l'impression (Code des boutons "Configurer" et "Imprimer"). Une instance printableObject de la classe PrintRectangleResTextPreview pour rendre l'aperu et l'impression. Un composant interne previewPanel qui surcharge sa mthode paint pour afficher l'aperu.

V-C-4 - L'impression par bande


Une impression en A4 et 600 DPI revient gnrer une image d'environ 5000X7000 pixels. La mmoire de la JVM peut donc trs vite arriver saturation si l'image imprime est rendue en une seule passe. Heureusement, un mcanisme trs simple existe : faire le rendu successif de petits bouts de l'image finale comme une mosaque. Il semble que Java gre d'office ce mode car j'ai constat que la mthode print d'un Printable peut tre appele plusieurs fois de suite pour une mme page. Par contre, j'ai constat que certains attributs de dessin pouvaient modifier ce comportement comme afficher une couleur avec transparence. Dans ce cas l, Java essaye d'allouer une image la taille correspondante mais en 72 DPI qui est le paramtrage initial du contexte de rendu transmis la mthode print. Dans ce cas l, tout est fauss car le nouveau rendu essaye toujours de faire un rendu la rsolution de l'imprimante et seul le coin suprieur gauche est imprim comme le montre le schma ci-dessous :

- 31 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

Il y a donc certains comportements viter lors de l'impression comme utiliser la transparence. Je n'ai pas la liste exhaustive de ces comportements bannis mais leur utilisation se remarque la premire impression.

V-C-5 - Affichage de la progression


Afficher une bote pendant l'impression se rsout en utilisant plusieurs threads :

Dans le diagramme ci-dessus : Les tches identifies par un nombre sont excutes dans le thread AWT. Les tches identifies par une lettre sont excutes dans un thread spcifique l'impression.

Modifions donc la JFrame de l'exemple prcdent, pour respecter ce schma :


import java.awt.BorderLayout; - 32 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton import import import import import import import import import import import import import import import import import import import import java.awt.Dimension; java.awt.FlowLayout; java.awt.Graphics; java.awt.Graphics2D; java.awt.Point; java.awt.Toolkit; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.ComponentEvent; java.awt.event.ComponentListener; java.awt.print.PrinterException; java.awt.print.PrinterJob; javax.print.attribute.PrintRequestAttributeSet; javax.swing.JButton; javax.swing.JDialog; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.SwingUtilities; sun.print.DialogTypeSelection;

/** * * */ public class Main9 extends JFrame{ private PrintParameters printParameters = new PrintParameters(); private PrintRectangleResTextPreview printableObject = new PrintRectangleResTextPreview(); private PreviewPanel previewPanel = new PreviewPanel(); private PrinterThread printerThread = null; private ProgressDialog dialog = null; /** Constructeur par dfaut de Main8 */ public Main9() { JPanel internalPanel = new JPanel(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); internalPanel.setLayout(new BorderLayout()); setTitle(printParameters.getPrintService().getName()); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); JButton configButton = new JButton("Configuration"); configButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PrinterJob job = PrinterJob.getPrinterJob(); PrintRequestAttributeSet attribSet = printParameters.getAttributes(); attribSet.add(DialogTypeSelection.NATIVE); try { job.setPrintService(printParameters.getPrintService()); if (job.printDialog(attribSet)){ printParameters = new PrintParameters(attribSet, job.getPrintService()); setTitle(printParameters.getPrintService().getName()); previewPanel.repaint(); } } catch (PrinterException ex) { ex.printStackTrace(); } } }); buttonPanel.add(configButton); JButton printButton = new JButton("Imprimer"); printButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (printerThread == null){ - 33 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton printerThread = new PrinterThread(); dialog = new ProgressDialog(); printerThread.start(); dialog.setVisible(true);

}); buttonPanel.add(printButton); internalPanel.add(buttonPanel, BorderLayout.SOUTH); internalPanel.add(previewPanel, BorderLayout.CENTER); setContentPane(internalPanel); pack(); } /** * @param args the command line arguments */ public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Main9().setVisible(true); }

});

/** * Panel de l'aperu **/ private class PreviewPanel extends JPanel{ PreviewPanel(){ addComponentListener(new ComponentListener() { public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { repaint(); } public void componentShown(ComponentEvent e) { repaint(); } }); setPreferredSize(new Dimension(400,400)); } /** */ public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Dimension size = getSize(); } } /** * Bote de progression **/ private class ProgressDialog extends JDialog { JLabel progressLabel = new JLabel(); ProgressDialog(){ super(Main9.this, true); setTitle("Impression"); setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); - 34 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

printableObject.preview(g2d, size, printParameters);

L'impression en java par Bruno Richeton

JPanel panel = new JPanel(); panel.setPreferredSize(new Dimension(300, 40)); panel.setLayout(new BorderLayout()); panel.add(progressLabel, BorderLayout.CENTER); setContentPane(panel); pack(); // Centre la bote Dimension dialogSize Dimension parentSize Point parentLocation Dimension screenSize = = = = getSize(); Main9.this.getSize(); Main9.this.getLocation(); Toolkit.getDefaultToolkit().getScreenSize();

int xBox = parentLocation.x+(parentSize.width - dialogSize.width)/2; int yBox = parentLocation.y+(parentSize.height - dialogSize.height)/2; if (xBox < 0){ xBox = 0; } else { if ((xBox +dialogSize.width)> screenSize.width){ xBox = screenSize.width-dialogSize.width; } } if (yBox < 0){ yBox = 0; } else { if ((yBox +dialogSize.height)> screenSize.height){ yBox = screenSize.height-dialogSize.height; } } } setLocation(xBox, yBox);

public void close(){ if (SwingUtilities.isEventDispatchThread()){ dispose(); dialog = null; } else { SwingUtilities.invokeLater(new Runnable() { public void run() { close(); } }); } } public void setText(String text){ if (SwingUtilities.isEventDispatchThread()){ progressLabel.setText(text); } else { SwingUtilities.invokeLater(new TextThread(text)); } }

} private class TextThread implements Runnable{ String text; TextThread(String text){ this.text = text; } public void run() { dialog.setText(text); } }

- 35 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

L'impression en java par Bruno Richeton

/** * Thread d'impression **/ private class PrinterThread extends Thread{ PrinterThread(){ super("Thread d'impression"); } public void run() { try { dialog.setText("Dbut de l'impression"); sleep(1000); PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(printableObject); job.setPrintService(printParameters.getPrintService()); dialog.setText("Impression"); sleep(1000); job.print(printParameters.getAttributes()); dialog.setText("Fin de l'impression"); sleep(1000); dialog.close(); } catch (Throwable ex) { ex.printStackTrace(); } printerThread = null;

} } }

Deux champs ont t rajouts la classe : Une instance du thread d'impression PrinterThread. Une instance de la bote de progression ProgressDialog

V-C-5-a - Le thread d'impression


Le thread d'impression ralise l'impression proprement parler. Par contre, il a accs la bote de dialogue pour lui envoyer des notifications de progression. Dans un vrai projet, ces notifications seraient plutt envoyes par l'implmentation de Printable pour afficher des informations sur la page en cours d'impression. Par contre, la fin de l'impression, le thread a la charge de dtruire la bote de progression par l'appel dialog.close().

V-C-6 - La bote d'impression


Dans cet exemple, la bote contient juste un label pour afficher un texte. Cette bote propose la mthode setText pour modifier le contenu de ce label. Cette mthode doit obligatoirement tre synchronise avec le thread AWT puisqu'elle est destine tre appele par le thread d'impression. Dans le mme acabit, la bote propose la mthode close() pour pouvoir tre ferme la fin de l'impression

- 36 Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2009 Bruno RICHETON. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://bruno-richeton.developpez.com/tutoriels/java/swing/impression-java/

Vous aimerez peut-être aussi