# Java > Interfaces Graphiques en Java > AWT/Swing >  Ajouter un logo dans l'entte de print JTable

## fideel

salut.
je veux imprimer un Jtable avec deux logos en en-tte, comment pouvais-je faire svp?
et merci d'avance.



```

```

----------


## joel.drigo

Salut,

On ne peut pas le faire de base. L'impression de JTable par Printable se limite  l'impression de la JTable et d'enttes de type texte (monoligne centre en plus). J'ai fait une petite extension de ce systme pour imprimer des enttes multilignes, mais a se limite  du texte.

L'impression des composants Swing est limite. Parce que normalement, on imprime pas des composants de GUI : ils sont fait pour grer une interface pour l'cran. Pour imprimer, on imprime. Soit on fait l'impression compltement (en Java2D dans un Printable), soit on gnre un PDF (avec une API comme IText, ou PDFbox), soit on utilise une API de rapport, comme IReport ou Birt.

Tu peux t'en sortir en intercalant l'impression de tes logos et en modifiant le PageFormat pour faire croire  la JTable qu'il y une norme marge (la place rserve pour ton logo ou quoique tu veuilles imprimer en entte ou en pied-de-page (et a se limite  a, pas de rupture, de trailer, etc, parce qu'on a pas accs au flux de lignes, pour a il faudrait se faire son propre TablePrintable, comme j'ai fait pour les enttes multilignes).

Voici une classe qui s'occupe de a :


```

```

Dmo :



```

```

Et l'impression correspondante :

----------


## fideel

salut.

merci de ta rponse..

y a un problme avec TextUtils ..il me demande de crer la classe  TextUtils mme se j'ai fait les imports..

----------


## joel.drigo

TextUtils  ::roll::

----------


## fideel

aah oui..c'tait cache..

j'ai plac un logo  gauche , un logo  droit et un texte au milieu. les trois sont comme il faut, mais ce qui n'est pas le cas c'est la table, elle prend toute la largeur de la page. je veux qu'elle laisse des marges gauche et droite.

----------


## joel.drigo

Avec une impression papier, a m'tonnerait, tu dois forcment avoir des marges (sauf peut-tre sur certains traceurs). L, tu dois faire tes tests en PDF, non ? Ce qui pourrait expliquer pourquoi tu n'as aucune marge. En PDF, tu peux utiliser le dialogue de configuration des marges pour le faire avant de lancer l'impression.



Toujours est-il que si tu veux des marges, soit tu interviens sur le Paper. On peut forcer les marges par quelque chose comme a (on donne en faite les dimensions de l'espace imprimable, donc la taille du papier sans l'espace autour consituant des marges)


```

```

Ensuite utiliser a avec la mthode Job.print() adquate.
Attention  la problmatique de la marge minimum (une imprimante a la plupart du temps une marge minimum, ncessaire pour des raisons mcaniques lies  l'entrainement du papier).

Sinon, en passant par mon code, c'est plus ou moins le mme principe que celui que j'ai utilis pour l'entte et le pied de page, sauf qu'au lieu de rduire la marge haute et la marge basse, tu rduis les marges droite et gauche.

Si tu regardes la classe HeaderFooterPageFormat, tu verras dans sa mthode computeImageable que je recalcule le y et le height de l'imageable du PageFormat.



```

```

Tu peux faire quelque chose de similaire avec les marges droite et gauche.

Par exemple, tu peux faire un truc du genre (c'est mieux d'utiliser un max, parce qu'on ne peut pas savoir les marges minimums de l'imprimante de manire simple) :



```
int realmargin = Math.max(pageFormat.getImageableX(), margin); // margin est un attribut de la classe que tu peux passer au constructeur par exemple
```

et donc ensuite tu appliques a  pageFormat.getImageableX() et pageFormat.getImageableWidth()  la cration du Rectangle...

----------


## fideel

emm. j'ai dj modifier dans pageFormat.getImageableX() et pageFormat.getImageableWidth() , en ajoutant une valeur v1 pour les deux  paramtres, mais c'est une erreur puisqu'elle dcale la table  droite par la valeur v1 . maintenant j'ai fait:
pageFormat.getImageableX() + v1  et  pageFormat.getImageableWidth() - 2*v1

a centre la table et laisse la mme marge v1 droite et  gauche..

c'est valable??

est-ce que je peux afficher a comme aperu avant impression dans ma classe PrintPreview .?? 

et Merci pour votre suivi.

----------


## joel.drigo

> c'est valable??


C'est valable si tu veux imposer une marge supplmentaire  celle choisie par l'utilisateur ou impose par l'imprimante.




> est-ce que je peux afficher a comme aperu avant impression dans ma classe PrintPreview .??


TablePrinter  est un Printable qui va remplacer celui que tu utilisais avant avec table.getPrintable(). J'ai juste intgr le traitement du problme de la rutilisation (qu'on ne peut pas avec le TablePrintable), donc il n'y a pas besoin d'en recrer un  chaque fois que tu rimprimes ou tu changes l'orientation (il se dbrouille tout seul, normalement), mais si tu fais comme si ce n'tait pas rutilisable a fonctionnera de toute manire.

----------


## fideel

donc si je remplace le m_target par le tableprinter a va march??
comme a :



```

```

----------


## fideel

salut.. j'ai essay de jouer par le m_target  et le printable tableprinter pour l'afficher avant d'tre imprimer, mais j'arrive pas  le faire.
je pense il y a des choses doivent se changer dans la mthode getThePreviewPages().??

----------


## joel.drigo

Normalement, si partout o il y avait table.getPrintable() tu fais new TablePrinter(...), il n'y a pas de raison que a ne fonctionne pas.

----------


## fideel

oui c'est a ce que j'ai fait.

l'erreur que j'ai commis c'est de faire le construction de header et footer dans une fonction void et je l'ai appele dans l'actionlistener du bouton print.
maintenant j'ai corrig et a fonctionne mais ce qui n'est  bon c'est que a ajoute une autre entte et autre pied de page vides.

----------


## joel.drigo

Montres-moi le code, ce sera plus simple de comprendre ce qu'il fait, qu'avec tes explications.

----------


## fideel

j'ai fait la cration de header et footer dans une mthode buildHeaderFooter() que j'ai appele dans le constructeur puisque ils sont  dclars comme static HeadBandPrintable.

la position de header, footer et les marges sont rgls dans le tablePrinter(). le problme c'est que tout le contenu tableprinter devient comme un contenu principale dans le printview,
et il se voit au milieu de page avec des nouvelles marges, header et footer. 





```

```

----------


## joel.drigo

> j'ai fait la cration de header et footer dans une mthode buildHeaderFooter() que j'ai appele dans le constructeur puisque ils sont  dclars comme static HeadBandPrintable.


Que l'interface HeadBandPrintable n'oblige en rien des variables de classe implmentant cette interface d'tre elles-mmes statiques. En plus, dans ton code, c'est incohrent : les variables header et footer sont statiques, alors que le code pour leur donner une valeur ne l'est pas. Pourquoi ne pas simplement crer des mthodes statiques ?




> e problme c'est que tout le contenu tableprinter devient comme un contenu principale dans le printview,


Oui et c'est un peu le principe. Ce que tu essaies de me dire c'est que tu voudrais prvisualiser sans le header et le footer, mais imprimer avec ? C'est absurde, parce que le nombre de pages n'est pas le mme.




> et il se voit au milieu de page avec des nouvelles marges, header et footer.


Je ne comprends pas ce que tu veux dire.

Sinon, ici :


```

```

Tu cres deux ActionListener pour deux boutons, un qui imprime avec header/footer texte standard (sans logo) et un qui imprimer avec TablePrinter. Faudrait savoir, parce que si on prvisualise une impression, il serait logique que le "print" imprime ce qu'on voit. Il serait si simple si tu utilisais systmatiquement un Supplier de Printable et c'est marre, on utilise toujours le supplier pour obtenir un Printable qui reprsente toujours la mme chose, dans tous les cas, impression, prvisualisation, comptage des pages, etc. Et a t'vite de dupliquer du code un peu partout, entre autres.



Et puis un autre truc :


```

```

alors que la mthode run() de PrintPreview fait des accs Swing. JAMAIS on n'excute du Swing en dehors de l'Event Dispatch Thread !!! Si le souci est que a prend du temps  s'excuter et qu'on ne veut pas bloquer l'UI pendant ce temps, on utilise un SwingWorker. Mais pas un Thread ! En plus, il vaut mieux viter de faire ces trucs d'implmenter les mthodes des interfaces dans la classe englobante, c'est sale, permissif et difficile  suivre et a complique les implmentations avec des if ou des switch pour distinguer les sources. Sans faire ncessairement des Action (ce qui est le plus souple), une lambda ou une classe anonyme vite d'ajouter des mthodes publiques  la classe.

Enfin, je ne suis pas sr que la prvisualisation d'une impression soit le meilleur endroit pour saisir les libells de header ou choisir si on en imprime un ou pas, ou alors, il faut regnrer la preview  chaque changement.

----------


## fideel

pour donner une valeur  header et footer j'ai fait la mthode buildHeaderFooter() dans le constructeur.
mes deux logos s'affichent dans le header..
le problme du positionnement au milieu regarde ici :



mes logos sont les noires je veux qu'ils seront les rouges en haut.

je sais pas pourquoi le titre dans le header et ainsi le footer ne s'affichent pas.

pour les boutons print:
le premier c'est l'ancienne version avant d'intgrer les logos.
le 2me bouton print c'tait pour imprimer la page courante toute seule, j'ai pas russi  implmenter son code correctement et je l'utilise pour un print avec les logos.
s'il fonctionne correctement je vais liminer le premier bouton..

----------


## joel.drigo

Tu n'as rien modifi dans TablePrinter ?

----------


## joel.drigo

> je sais pas pourquoi le titre dans le header et ainsi le footer ne s'affichent pas.


C'est simplement parce qu'il y a a :T


```
  g.setColor(Color.white);
```

dans le code de preview (juste pour remplir de blanc le fond de la page, ce qui ne devrait pas tre ncessaire pour un type RGB). Donc tout ce qui est dessin (crire c'est dessiner) aprs est blanc. Blanc sur blanc...
Normalement, le plus propre c'est de crer un graphics spcifique pour chaque traitement est d'en disposer aprs, afin de restituer une graphics de base. 

Tu peux aussi simplement ajouter un graphics.setColor(Color.BLACK); juste avant le TextUtils.drawString...

----------


## fideel

non.sauf dans les coordonnes X et Y..j'ai ajout des petites valeurs pour laisser des marges..je l'ai supprims maintenant toujours il y a une grande marge en dessus de mes logos..le titre et le footer s'affichent en blanc, c'est pour a qu'ils ne sont pas visible.

----------


## fideel

lorsque j'imprime avec les nouvelles valeurs que j'ai ajout au coordonnes que ce soit dans

 computepage() 



```

```

ou dans buildHeaderFooter()



```

```

tous s'imprime comme il faut.



le problme c'est au niveau de la prs visualisation ..

il ajoute des autres marges en haut, bas, gauche et droite..ce qui n'est pas similaire avec ce qu'est imprim.

----------


## joel.drigo

> .je l'ai supprims maintenant toujours il y a une grande marge en dessus de mes logos..


a, c'est normal, pour la hauteur du header, tu as mis 2 fois la hauteur de l'image de gauche ! getHeight() doit retourner la hauteur du header. 

Si tu veux pouvoir grer des marges autour de la table, tu peux utiliser cette version :









```

```

----------


## joel.drigo

> lorsque j'imprime avec les nouvelles valeurs que j'ai ajout au coordonnes que ce soit dans
> 
>  computepage() 
> 
> 
> 
> ```
> 
> ```


a c'est du bidouillage, pour ne pas dire du merdouillage. Si tu regardes bien, le HeaderFooterPageFormat est utilis pour imprimer la table, le header et le footer (et le nom de la classe n'est pas sans lien avec a) !
Non seulement a a des effets de bord, mais tu les contres avec des trucs absurdes comme afficher le logo de gauche en -30 !!!
Avec la nouveau TablePrinter que je t'ai donn dans le message prcdent, tu peux ajouter une marge autour de la table, sans bidouiller. Et si tu as besoin de marges dans les header ou footer, bah tu dcales les draw et tu ajoutes de la hauteur dans getHeight() en correspondance, pour qu'il y ait la place.

----------


## fideel

j'ai implment la nouvelle version tablePrinter().
j'ai rien touch..j'ai aussi rinitialis les coordonnes su header et footer..
rsultat:

----------


## fideel

les marges supplmentaires qui me drange et grce  eux Nous ne voyons pas le mme problme. 
je crois qu'ils sont ajouts dans le paper de la prs visualisation..parce que aprs l'impression y a pas ces marges supplmentaires..

impression:



prs visualisation:

----------


## joel.drigo

> j'ai implment la nouvelle version tablePrinter().
> j'ai rien touch..j'ai aussi rinitialis les coordonnes su header et footer..


Et ? Donc ? Si la question non nonce, c'est qu'il n'y a pas de marge entre le header et la table, c'est parce que tu n'en as pas mise, Et si le titre s'affiche par dessus la table, c'est parce que c'est ce que fait le code (du header).


Essaye comme a puis ajuste :


```

```

----------


## joel.drigo

> je crois qu'ils sont ajouts dans le paper de la prs visualisation..parce que aprs l'impression y a pas ces marges supplmentaires..


a c'est probablement dans la manire de dterminer le paper. A priori, le souci, doit tre qu'on n'affiche pas la preview aprs choix dans un printDialog, mais avant, donc le format n'est pas spcifiquement celui d'un PrintService particulier. Le dialogue de prvisualisation doit tre affich aprs le choix de la destination et du paramtrage des marges, et aprs, on ne doit plus afficher de dialogue (sur le bouton print dans la prvisu).

En clair, le souci vient de l :     pp_pf = prnJob.defaultPage();. On utilise le format par dfaut pour la preview. Alors qu'on devrait utiliser le mme que pour l'impression.

----------


## fideel

c'est bon pour les le titre et la table.
maintenant regarde ici la prs visualisation:



et ici limpression :

----------


## fideel

> En clair, le souci vient de l :     pp_pf = prnJob.defaultPage();. On utilise le format par dfaut pour la preview. Alors qu'on devrait utiliser le mme que pour l'impression.


voil maintenant on est sur le mme souci.

----------


## joel.drigo

Oui, mais, a c'est ce que je t'ai dit dans mon prcdent message : c'est d au fait que l'impression et la preview ne sont pas fait avec le mme format (parce que l'impression n'est pas faite avec le defaultPage()).

----------


## fideel

et comment faire pour rgler a. c'est mieux de toucher la preview pour pouvoir rgler les marges facilement..

et merci beaucoup beaucoup de ton effort..

----------


## fideel

j'ai mis l'impression en dfautpage()..  les logos sont plus bas..

----------


## joel.drigo

Le plus simple, c'est de prendre la defaultPage() (sur le job, comme tu fais). Et pour imprimer, tu utilises le format que tu utilises pour la preview, celui qui est dans pp_pf : au lieu de job.setPrintable(printable), tu utilises job.setPrintable(printable, pp_pf) au moment d'imprimer, mais de ne plus afficher le printDialog ou le pageDialog  ce moment (parce qu'on peut y changer le format). Ce qui veut dire qu'il faudrait le faire avant d'afficher la preview, pour pouvoir choisir l'imprimante au moins et donc rcuprer le format aprs l'affichage du dialogue (printDialog et/ou pageDialog). Ou de refaire cette partie dans le dialogue de preview, avec une combo (voir PrintServiceLookup.lookupPrintServices(null,null) pour la liste et job.setPrintService(ps)).

----------


## fideel

salut..

j'ai fait comme tu m'as dit: job.setPrintable(printable, pp_pf) . a marche.. mais la marges en haut de page ,en dessus des logos pas pratique non??.  :;):  :;):

----------


## joel.drigo

> mais la marges en haut de page ,en dessus des logos pas pratique non??.


Bah, a c'est les marges par dfaut, 72 points, soit 1 pouce, soit 25,4 mm.

Tu peux forcer les marges, ou permettre  l'utilisateur de les configurer aussi avec un "PageDialog" ou une interface custom.

Pour forcer les marges, aprs avoir rcuprer le defaultFormat :



```

```

Avec


```

```

----------


## fideel

emm..o je doit implmenter ce code pour ne pas tomber dans ce qu'est Interdit ??

----------


## joel.drigo

> aprs avoir rcuprer le defaultFormat


donc juste aprs a :


```
pp_pf = prnJob.defaultPage();
```

par exemple, tu fais une mthode setDefaultMargins(PageFormat defaultFormat) avec le code ci-avant dedans, et tu l'appelles setDefaultMargins(pp_pf);. Et si tu veux permettre l'utilisateur de changer les marges dans l'interface, tu te fais une mthode avec les marges en paramtres...

----------


## fideel

voil, c'est impeccable maintenant..tu es vraiment super. 

une dernire chose pour terminer cette application.

comment je peux rcuprer le nombre e page avant l'affichage??

----------


## joel.drigo

> comment je peux rcuprer le nombre e page avant l'affichage??


Bah, tu le faisais dj a... tu simulais une impression, en imprimant chaque page successivement jusqu' obtenir NO_SUCH_PAGE.

----------


## fideel

se sera aprs l'impression?? je veux le rcuprer pour l'afficher dans le footer.



```

```

----------


## joel.drigo

Tu le fais dj dans getThePreviewPages ! C'est pageIndex,  la fin de la boucle de simulation. Sauf que tu ne le stockes pas l o il serait accessible en dehors de cette mthode. Si tu le stockes par exemple en variable de classe,  tu pourras le rutiliser l o tu veux dans la classe (donc au moment o tu construis le footer...)

----------


## fideel

j'ai dclar une variable static pageCount.

et  la fin de la boucle while de getThePreviewPage() j'ai affect pageIndex  pageCount..et a me donne dans le footer ( "page" +pageIndex+"/" 0)  dans la prs visualisation..
mais aprs l'impression a marche bien..

----------


## joel.drigo

Oui sauf que dans ta boucle tu gnres des images de page, alors que pageCount n'est pas encore calcul... il faut faire la boucle d'abord pour compter et connatre la valeur de pageCount, puis la refaire ensuite pour faire les images...

----------


## fideel

oui c'est a ce que je suis entrain de faire.

----------


## fideel

c'est bon. c'est fait..
merci beaucoup beaucoup de ton aide joel.drigo . :;):

----------

