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.
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);
}
});
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With