JTextPane/JEditorPane and weird text issue
Asked Answered
H

1

9

I am creating a simple chat program that I want to eventually show html links. My problem right now is that I can't get the text to appear next to the users name as I want it to.

I want the user's name to be bold, and the text to appear right next to it, but for some reason the non bolded text appears centered.

If I do not bold the users name, it works fine. The top two are how it appears when I have the names bolded, the middle is when the name is not bolded, the bottom shows a hyperlink I want it to appear like the middle two, but with the names bolded.

enter image description here

Here is the code, what am I doing wrong? Note that I tried replacing JTextPane with JEditorPane and the same thing happens.

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) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
            
                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);
            }
        });


    }

}
Hrutkay answered 9/7, 2012 at 22:44 Comment(8)
1+ for posting a well-functioning and short demo program, one that shows the problem well.Legitimatize
I'm no JTextPane expert, but I do note that the problem goes away if you comment out the pane.setContentType("text/html"); line.Legitimatize
Yeah, I know the problem goes away with that commented out. I am using text/html because I need it to be able to display hyperlinks, and those only seem to work with text/html set.Hrutkay
I think that you'll want to use HTML then to show different text attributes if the type must be "text/html".Legitimatize
If I use raw HTML, it seems to appear in the text itself (not read as markup). This is frustrating.Hrutkay
If you're trying to display HTML, why are you using a JTextPane anyway instead of a JEditorPane?Legitimatize
I'm not trying to show straight up HTML for the most part... I just need HTML so I can show clickable linksHrutkay
This is a great excuse to check out Swing Explorer. The actual problem is likely to be a weird HTML layout issue. I don't know how you'll get around it, but making the username text bold has a side-effect of grouping the username and text into different paragraph elements, one of which appears to be getting centered for some unknown reason. Check out the HTML that's being generated (minus your text), by viewing in the debugger chat.pane.getText() or printing it to stdout. In fact, every insert (before a newline) after the first one appears to get centeredSlim
C
3

I just played and searched around a bit and found the following solution:

Initialize your JTextPane after setting the content type with something like this:

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

After that initialize the following two new fields (will be used in the methods, just for convenience):

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

Now you can change your method submitALinkWithBold like this:

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

You should be able to adopt this scheme to the other two methods (chatWithBold and chatNoBold) too.

Note that the result does not look good (or does not work at all) until you change all your methods. Also note that even after changing all methods, it does not look like your original example (larger line spacing, other font…). I think this could be fixed by casting pane.getEditorKit() to a HTMLEditorKit and using its setStyleSheet(…) method but I did not try this.

Cheery answered 10/7, 2012 at 20:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.