2010-01-15 9 views
4

Désolé s'il existe un post similaire au mien mais je suis nouveau sur ce forum et je ne l'ai pas trouvé.Ajustement du texte dans TextField IText

J'ai un problème avec le redimensionnement dynamique La taille du champ TextField dépend de la taille du texte. Je remplis les champs de remplissage PDF existants dans AcroForm:

form.setField ("field", "value"); (etc.)

Tout est OK, mais je veux aussi définir le texte (dans TextField) dont la taille est supérieure à la taille du champ. Comment puis-je redimensionner dynamiquement TextField (après/avant setField ou peut-être définir une propriété de champ dans le processus de création de AcroForm) pour s'adapter au texte (texte plus grand que TextField)? Ce TextField doit avoir la taille exactement comme la taille du texte, sans changer la taille de la police à la plus petite taille et sans défilement dans ce TextField.

Merci d'avance pour votre aide.

+0

Je doute qu'il y ait d'autres questions comme celle-ci. Jamais entendu parler de quelqu'un ayant besoin de quelque chose comme ça avant, après avoir travaillé avec PDF pour> 13 ans. –

Répondre

7

Eh bien, il est facile de faire le contraire de ce que vous voulez, changer la taille de la police de sorte que tout le texte est visible. Vous venez de définir la taille de la police à '0', et iText (ou Acrobat, ou autre) détermine la taille de police à utiliser à la volée (dans certaines limites raisonnables).


Pour déterminer la longueur d'un morceau donné de texte, vous pouvez appeler myBaseFont.getWidthPoint(fieldValToBe, fontSize). Ensuite, vous pouvez dimensionner le champ avant vous appelez setField. iText affiche par défaut les apparences de champs, et ce rendu est fait quand vous le pouvez setField. La modification de la taille du champ afterwords ne modifie pas l'apparence du champ sauf si vous appelez de nouveau setField.

Bon, alors comment changer la taille du champ? iText ne supporte pas cela directement, donc vous devez le faire avec les objets PDF de bas niveau d'iText. Quelque chose comme ceci:

AcroFields.Item fldItem = myAcroFields.getFieldItem("fieldName"); 

for (int i =0; i < fldItem.size(); ++i) { 
    // "widget" is the visible portion of the field 
    PdfDictionary widgetDict = fldItem.getwidget(0); 

    // pdf rectangles are stored as [llx, lly, urx, ury] 
    PdfArray rectArr = widgetDict.getAsArray(PdfName.RECT); // should never be null 
    float origX = rectArr.getAsNumber(0).floatValue(); 
    // overwrite the old value. 
    rectArr.set(2, new PdfNumber(origX + newWidth + FUDGE_FACTOR)); 
} 

FUDGE_FACTOR doit tenir compte des bonnes & épaisseurs de frontière gauche. Je devinerais 3-5 points, en fonction des bordures biseautées et plates, de l'épaisseur de la ligne et ainsi de suite. Vous pouvez probablement juste choisir une valeur et aller avec.

La boucle est probablement inutile, car il est rare que plus d'un champ partage un nom. OTOH, si c'est ce que vous avez à faire, vous devrez peut-être également recalculer newWidth car différentes instances n'ont pas besoin de partager la même taille de police. Enfin, vous devrez peut-être écrire ce nouveau rectArr dans la version "fusionnée" de l'élément ainsi que dans la version du widget. iText fonctionne presque universellement avec la version fusionnée lors de la manipulation d'un champ car toutes les paires clé/valeur possibles sont là, où vous devrez peut-être vérifier les valeurs du champ parent avec la version du widget.

OTOH, une donnée "fusionnée" et "widget" devrait partager le même rectangle PdfArray, rendant le point discutable. "Rect" est une valeur "feuille" et ne sera jamais héritée d'un parent, donc le tableau du widget aura été "copié superficiellement" dans le dictionnaire fusionné ... le partageant ainsi. Dans tous les cas, vous devriez pouvoir le vérifier assez facilement.

assert item.getWidget(0).getAsArray(PdfName.RECT) == 
     item.getMerged(0).getAsArray(PdfName.RECT); 

Notez que c'est == pas .equals. Je ne pense pas PdfArray a un equals(), donc ce point n'est pas tout ce qui concerne non plus.Oh, et juste parce que j'ai vraiment du travail à faire, je vais vous laisser comprendre comment obtenir un BaseFont d'un champ par vous-même, avec un coup de pouce dans la bonne direction. Vous aurez besoin d'un DocumentFont via BaseFont.createFont(PRIndirectReference fontRef), et vous devriez vérifier The PDF Spec, chapitre 12.7 (formulaires interactifs) et 9.5-9.10 (divers types de polices ... dont DocumentFont s'occupera en grande partie pour vous) pour savoir où trouver cette référence indirecte.

Et pour comprendre ce qu'est une référence indirecte, vous aurez besoin de lire le chapitre 7.3, «Objets», en particulier 7.3.10, «Objets indirects».