JTextPane无法正确呈现span标记

时间:2014-11-26 10:02:09

标签: java html swing text

我有一些代码:

package main;

import java.awt.EventQueue;
import java.awt.Font;
import java.io.StringWriter;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DefaultCaret;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;

public class LogConsole extends JFrame {
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JTextPane logPane;
    private HTMLDocument logDoc;
    private HTMLEditorKit logKit;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LogConsole test = new LogConsole();
                    test.setVisible(true);

                    test.log("<span>Hello 1</span><br/>"); //Test 1
                    test.log("<span>Hello 2</span><br/>"); //Test 2
                    test.log("<span>Hello 3</span><br/>"); //Test 3

                    test.log("<span>Hello </span>");       //Test 4
                    test.log("<span>world!</span>");       //Test 5

                    test.printHTML();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Log some data...
     * @param str
     */
    public void log(String s){
        s = s.replaceAll("\n", "<br/>");
        try {
            logKit.insertHTML(logDoc, logDoc.getLength(), s, 0, 0, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void printHTML(){
        try{
            StringWriter writer = new StringWriter();
            logKit.write(writer, logDoc, 0, logDoc.getLength());
            String s = writer.toString();
            System.out.println(s);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void clearLog(){
        try {
            logPane.setText("");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Create the frame.
     */
    public LogConsole() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);

        JScrollPane scrollPane = new JScrollPane();
        GroupLayout gl_contentPane = new GroupLayout(contentPane);
        gl_contentPane.setHorizontalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 404, Short.MAX_VALUE)
                    .addContainerGap())
        );
        gl_contentPane.setVerticalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE)
                    .addContainerGap())
        );

        logPane = new JTextPane();
        logPane.setContentType("text/html");
        logPane.setEditable(false);
        scrollPane.setViewportView(logPane);
        contentPane.setLayout(gl_contentPane);

        DefaultCaret caret = (DefaultCaret)logPane.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

        logDoc = (HTMLDocument) logPane.getDocument();
        logKit = (HTMLEditorKit) logPane.getEditorKit();
        Font font = new Font("Consolas", Font.PLAIN, 14);
        String bodyRule = String.format("body{font-family:%s;font-size:%spt", 
                font.getFamily(), font.getSize());
        StyleSheet style = logDoc.getStyleSheet();
        style.addRule(bodyRule);
    }
}

enter image description here
我想将我的应用程序中的一些数据记录到JTextPane,但是我遇到了一些问题 首先,当我在两个log()语句中添加两个span标记时,它会在其后面添加一个新行(参见Test4 - Test5)。
 所以我认为JTextPane不支持内联标记,并且所有标记都是块标记。
这不是问题,因为每条线上的每个数据记录都非常“闲置”,您不需要添加“&lt; br /&gt;”在每个数据日志上,但我更喜欢自己处理它

如果我在“&lt; br /&gt;”中插入3 log()语句在每个日志数据(测试1,2,3),
第1行写“Hello 1”和新行,再写一个新行 第2行写“Hello 2”,只写一个新行 第3行写“Hello 3”和一个新行
但是Test1和Test 2有相同的声明形式,它产生两种不同的方式,为什么呢?
如果我将测试2改为:

test.log("<span>Hello 2</span>"); //Test 2

它不会改变结果!
任何人都能为我解释这些问题吗?
以及如何解决这些问题。
感谢

2 个答案:

答案 0 :(得分:1)

问题不是插入span,而是使用insertHTML()创建了一些周围的paragrapph元素。

通话工作正常,不会创建2行

test.log("<span>Hello </span><span>World</span>");

试试这个

public void log(String s){
    s = s.replaceAll("\n", "<br/>");
    try {
//            logKit.insertHTML(logDoc, logDoc.getLength(), s, 0, 0, null);
        logDoc.insertAfterEnd(logDoc.getCharacterElement(logDoc.getLength()), s);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

答案 1 :(得分:1)

如果我理解这个问题......如果使用HTMLDocument#insertBeforeEnd(...)而不是HTMLEditorKit#insertHTML(...)会更容易:

enter image description here

logPane = new JTextPane();
logPane.setContentType("text/html");
logPane.setEditable(false);
//http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6700731
//Bug ID: JDK-6700731
//JTextPane now renders HTML paragraph tags differently in/out of tables
//logPane.setText("<html><table><tr><td><p id='log'>");
logPane.setText("<html><p id='log' style='margin-top:0'>");
//logKit.insertHTML(logDoc, logDoc.getLength(), s, 0, 0, null);
logDoc.insertBeforeEnd(logDoc.getElement("log"), s);