2012-07-09 8 views
9

Tworzę prosty program do czatowania, który chcę w końcu pokazać linki html. Mój problem polega na tym, że nie mogę umieścić tekstu obok nazwy użytkownika, tak jak tego chcę.JTextPane/JEditorPane i dziwny problem tekstowy

Chcę, aby nazwa użytkownika była pogrubiona, a tekst powinien pojawić się obok niej, ale z jakiegoś powodu tekst nie pogrubiony jest wyśrodkowany.

Jeśli nie pogrubię nazwy użytkownika, działa poprawnie. Dwie pierwsze są takie, jak się pojawiają, gdy mam pogrubione nazwy, w środku jest, gdy nazwa nie jest pogrubiona, na dole pokazuje hiperłącze, chcę, aby wyglądało jak środkowe dwa, ale z nazwami pogrubionymi.

enter image description here

Oto kod, co robię źle? Zauważ, że próbowałem zastąpić JTextPane JEditorPanem i to samo się dzieje.

package com.test; 

import java.awt.BorderLayout; 
import java.awt.Color; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextPane; 
import javax.swing.WindowConstants; 
import javax.swing.event.HyperlinkEvent; 
import javax.swing.event.HyperlinkEvent.EventType; 
import javax.swing.event.HyperlinkListener; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.SimpleAttributeSet; 
import javax.swing.text.StyleConstants; 
import javax.swing.text.html.HTML; 

public class JTextPaneTest extends JPanel { 

    JTextPane pane; 

    public JTextPaneTest() { 
     this.setLayout(new BorderLayout()); 

     pane = new JTextPane(); 
     pane.setEditable(false); 
     pane.setContentType("text/html"); 

     JScrollPane scrollPane = new JScrollPane(pane); 
     this.add(scrollPane, BorderLayout.CENTER); 

     pane.addHyperlinkListener(new HyperlinkListener() { 

      @Override 
      public void hyperlinkUpdate(HyperlinkEvent e) { 
       if (e.getEventType() == EventType.ACTIVATED) { 
        System.out.println(e.getDescription()); 
       } 

      } 
     }); 

    } 

    public void chatWithBold(String user, String text) { 

     SimpleAttributeSet bold = new SimpleAttributeSet(); 
     StyleConstants.setBold(bold, true); 

     SimpleAttributeSet normal = new SimpleAttributeSet(); 

     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        user + ": ", bold); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        text + "\n", normal); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public void chatNoBold(String user, String text) { 

     SimpleAttributeSet bold = new SimpleAttributeSet(); 
     StyleConstants.setBold(bold, true); 

     SimpleAttributeSet normal = new SimpleAttributeSet(); 

     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        user + ": ", normal); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        text + "\n", normal); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    private void submitALinkWithBold(String user, String link) { 
     SimpleAttributeSet bold = new SimpleAttributeSet(); 
     StyleConstants.setBold(bold, true); 

     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        user + ": ", bold); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     SimpleAttributeSet attrs = new SimpleAttributeSet(); 
     attrs.addAttribute(HTML.Attribute.HREF, link); 

     SimpleAttributeSet htmlLink = new SimpleAttributeSet(); 
     htmlLink.addAttribute(HTML.Tag.A, attrs); 
     StyleConstants.setUnderline(htmlLink, true); 
     StyleConstants.setForeground(htmlLink, Color.BLUE); 
     try { 
      pane.getDocument().insertString(pane.getDocument().getLength(), 
        link + "\n", htmlLink); 
     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 

     JTextPaneTest chat = new JTextPaneTest(); 
     frame.add(chat); 

     frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 

     chat.chatWithBold("User1", "Hi everyone"); 
     chat.chatWithBold("User2", "Hey.. Hows it going"); 

     chat.chatNoBold("User1", "Hi everyone"); 
     chat.chatNoBold("User2", "Hey.. Hows it going"); 

     chat.submitALinkWithBold("User1", "http://www.stackoverflow.com"); 

     frame.setSize(400, 400); 

     frame.setVisible(true); 

    } 

} 
+2

1+ za opublikowanie dobrze działającego i krótkiego programu demonstracyjnego, który dobrze pokazuje problem. –

+1

Nie jestem ekspertem JTextPane, ale zauważam, że problem zniknie, jeśli skomentujesz linię 'pane.setContentType (" text/html ");'. –

+0

Tak, wiem, że problem zniknie z tym, co skomentowałem. Używam text/html, ponieważ potrzebuję go do wyświetlania hiperłączy, a te działają tylko z zestawem text/html. – systemoutprintln

Odpowiedz

3

po prostu grał i szukał około trochę i znalazłem następujące rozwiązanie:

zainicjować JTextPanepo ustawieniu typu zawartości z mniej więcej tak:

final String emptyHtml = "<html><body id='bodyElement'></body></html>"; 
pane.getEditorKit().read(new StringReader(emptyHtml), pane.getDocument(), 0); 

Po tym initialize następujące dwa nowe pola (zostaną użyte w metodach, tylko dla wygody):

this.doc = (HTMLDocument) pane.getDocument(); 
this.bodyElement = this.doc.getElement("bodyElement"); 

Teraz można zmienić metodę submitALinkWithBold tak:

final String html = "<p><b>" + user + ": </b>" 
    + "<a href='" + link + "'>" + link + "</a></p>"; 
doc.insertBeforeEnd(bodyElement, html); 

powinien być w stanie przyjąć ten schemat do pozostałych dwóch metod (chatWithBold i chatNoBold) też.

Należy zauważyć, że wynik nie wygląda dobrze (lub w ogóle nie działa), dopóki nie zostaną zmienione wszystkie metody. Zwróć też uwagę, że nawet po zmianie wszystkich metod nie wygląda to na Twój oryginalny przykład (większy odstęp między wierszami, inna czcionka ...). Myślę, że można to naprawić, przesyłając pane.getEditorKit() do HTMLEditorKit i używając jej metody setStyleSheet(…), ale nie próbowałem tego.