Java JTextPane/JEditorPane和奇怪的文本问题

Java JTextPane/JEditorPane和奇怪的文本问题,java,swing,jtextpane,jeditorpane,Java,Swing,Jtextpane,Jeditorpane,我正在创建一个简单的聊天程序,我希望最终显示html链接。我现在的问题是,我无法让文本按我所希望的方式显示在用户名旁边 我希望用户名为粗体,文本显示在其旁边,但由于某些原因,非粗体文本显示在中间 如果我不加粗用户名,它可以正常工作。上面两个是当我把名字加粗时它的显示方式,中间是当名字不加粗时,底部显示一个超链接,我希望它看起来像中间两个,但名字加粗 这是代码,我做错了什么?请注意,我尝试用JEditorPane替换JTextPane,同样的情况也发生了 package com.test; i

我正在创建一个简单的聊天程序,我希望最终显示html链接。我现在的问题是,我无法让文本按我所希望的方式显示在用户名旁边

我希望用户名为粗体,文本显示在其旁边,但由于某些原因,非粗体文本显示在中间

如果我不加粗用户名,它可以正常工作。上面两个是当我把名字加粗时它的显示方式,中间是当名字不加粗时,底部显示一个超链接,我希望它看起来像中间两个,但名字加粗

这是代码,我做错了什么?请注意,我尝试用JEditorPane替换JTextPane,同样的情况也发生了

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);
            }
        });


    }

}

我只是玩了一下,搜索了一下,找到了以下解决方案:

使用以下内容设置内容类型后,初始化
JTextPane

final String emptyHtml = "<html><body id='bodyElement'></body></html>";
pane.getEditorKit().read(new StringReader(emptyHtml), pane.getDocument(), 0);
final String html =  "<p><b>" + user + ": </b>"
    + "<a href='" + link + "'>" + link + "</a></p>";
doc.insertBeforeEnd(bodyElement, html);
现在,您可以更改方法
submitALinkWithBold
,如下所示:

final String emptyHtml = "<html><body id='bodyElement'></body></html>";
pane.getEditorKit().read(new StringReader(emptyHtml), pane.getDocument(), 0);
final String html =  "<p><b>" + user + ": </b>"
    + "<a href='" + link + "'>" + link + "</a></p>";
doc.insertBeforeEnd(bodyElement, html);
final String html=“”+user+:”
+“

”; doc.insertbeforeed(bodyElement,html);
您应该能够将此方案应用于其他两种方法(
chatWithBold
chatNoBold


请注意,在更改所有方法之前,结果看起来并不好(或者根本不起作用)。还要注意的是,即使在更改了所有方法之后,它看起来也不像原始示例(更大的行距,其他字体…)。我认为可以通过将
pane.getEditorKit()
转换为
HTMLEditorKit
并使用其
setStyleSheet(…)
方法来解决这个问题,但我没有尝试过这个方法。

1+用于发布一个功能良好且简短的演示程序,一个能够很好地显示问题的程序。我不是JTextPane专家,但是我注意到,如果您注释掉
pane.setContentType(“text/html”)行。是的,我知道问题会随着注释掉而消失。我之所以使用text/html,是因为我需要它能够显示超链接,而那些超链接似乎只适用于text/html集。我认为如果类型必须是“text/html”,那么您应该使用html来显示不同的文本属性。这是一个很好的签出借口。实际问题可能是一个奇怪的HTML布局问题。我不知道你将如何处理它,但是将用户名文本加粗会产生一个副作用,即将用户名和文本分组到不同的段落元素中,其中一个似乎由于未知原因而居中。通过在调试器chat.pane.getText()中查看或将其打印到stdout,检查正在生成的HTML(减去文本)。事实上,第一次插入之后的每一次插入(换行前)都会居中