2009-10-04 8 views
0

Dans mon application Swing, les utilisateurs saisissent du texte stylé dans un JTextPane qui utilise un RTFEditorKit (HTML est également une possibilité). Je dois ensuite restituer plusieurs de ces notes stylisées à des coordonnées spécifiques dans un composant personnalisé.Peindre des chaînes RTF/HTML dans un composant swing personnalisé

Je pense que la méthode View.paint serait utile ici, mais je ne suis pas capable de créer un objet View utilisable.

je la méthode suivante:

public View createView() throws IOException, BadLocationException { 
RTFEditorKit kit = new RTFEditorKit(); 
final Document document = kit.createDefaultDocument(); 
kit.read(new ByteArrayInputStream(text.getBytes("UTF-8")), document, 0); 
return kit.getViewFactory().create(document.getDefaultRootElement()); 
} 

Ce retourne un javax.swing.text.BoxView avec les attributs suivants:

majorAxis = 1 
majorSpan = 0 
minorSpan = 0 
majorReqValid = false 
minorReqValid = false 
majorRequest = null 
minorRequest = null 
majorAllocValid = false 
majorOffsets = {int[0]@2321} 
majorSpans = {int[0]@2322} 
minorAllocValid = false 
minorOffsets = {int[0]@2323} 
minorSpans = {int[0]@2324} 
tempRect = {[email protected]}"java.awt.Rectangle[x=0,y=0,width=0,height=0]" 
children = {javax.swing.text.View[1]@2326} 
nchildren = 0 
left = 0 
right = 0 
top = 0 
bottom = 0 
childAlloc = {[email protected]}"java.awt.Rectangle[x=0,y=0,width=0,height=0]" 
parent = null 
elem = {[email protected]}"BranchElement(section) 0,35\n" 

Notez que parent = null et nEnfants = 0. signifie qu'il n'y a rien de vraiment utile là-bas. Je peux bidouiller quelque chose en appelant le JTextPane.getUI().paint, mais le volet de texte doit être visible, et cela semble être la mauvaise façon de le faire.

Existe-t-il un moyen d'obtenir une représentation visuelle du contenu RTF sans rendre le JTextPane réel?

Répondre

0

Vérifiez la classe ScreenImage qui vous permet de créer une BufferedImage de tout composant Swing. Cela devrait aussi fonctionner pour les composants Swing qui ne sont pas visibles, mais oui, vous devez d'abord faire le rendu.

+0

Merci pour le lien, cela semble plus orienté vers la prise d'un instantané d'un composant qui est déjà visible à l'écran. Je voudrais utiliser une approche «d'estampillage» pour rendre des blocs de texte stylés à divers endroits sur mon composant personnalisé. –

+0

Je ne sais pas ce qu'est un apprach estampage. Peut-être que je ne comprends pas la question, mais l'idée est que vous pouvez créer une image à partir d'un composant non visible. Vous pouvez ensuite créer des sous-images à afficher sur votre composant personnalisé. La clé est que vous n'avez pas besoin d'un composant visible pour créer l'image. – camickr

1

Ce type de code fonctionne, mais semble moins qu'idéale. Y a-t-il une meilleure façon de le faire? Aussi, quel est un bon moyen de rendre le texte quelque part autre que 0,0 sur les graphiques?

private static void testRtfRender() { 
    String s = "{\\rtf1\\ansi\n" + 
      "{\\fonttbl\\f0\\fnil Monospaced;\\f1\\fnil Lucida Grande;}\n" + 
      "\n" + 
      "\\f1\\fs26\\i0\\b0\\cf0 this is a \\b test\\b0\\par\n" + 
      "}"; 

    JTextPane pane = new JTextPane(); 
    pane.setContentType("text/rtf"); 
    pane.setText(s); 

    final Dimension preferredSize = pane.getUI().getPreferredSize(pane); 
    int w = preferredSize.width; 
    int h = preferredSize.height; 

    pane.setSize(w, h); 
    pane.addNotify(); 
    pane.validate(); 

    // would be nice to use this box view instead of instantiating a UI 
    // however, unless you call setParent() on the view it's useless 
    // What should the parent of a root element be? 
    //BoxView view = (BoxView) pane.getEditorKit().getViewFactory().create(pane.getStyledDocument().getDefaultRootElement()); 
    //view.paint(d, new Rectangle(w, h)); 

    BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
    final Graphics2D d = img.createGraphics(); 
    d.setClip(0, 0, w, h); // throws a NullPointerException if I leave this out 
    pane.getUI().paint(d, pane); 
    d.dispose(); 
    JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img))); 
} 
Questions connexes