使用自定义HTMLEditorKit时,Java JTextPane会忽略<br/>标记

时间:2018-08-21 22:37:32

标签: java html swing jtextpane htmleditorkit

在我的应用程序中,我使用嵌入在JScrollPane中的JTextPane来显示使用HTML标记格式化的文本。最初,我使用JTextArea,但是后来切换到JTextPane以能够使用HTML和颜色。然后,我需要JTextPane支持基于字母的换行,而不仅仅是空白的默认换行。换句话说,如果内容太长,则应将其包装,并且JScrollPane的水平滚动条将不可见。

因此,我在此答案中找到了一个非常有效的解决方案:https://stackoverflow.com/a/6330483/3871673。 它为JTextPane使用了自定义HTMLEditorKit。

但是使用此解决方案,JTextPane会忽略带有HTML标记<br>的任何换行符。我不得不承认我并不真正知道解决方案中的代码是如何工作的。如果有人能找到如何使HTML新行<br>标签与该解决方案一起工作的话,那就太好了。

以下是一个最小,完整且可验证的示例:

import javax.swing.*;
import javax.swing.text.Element;
import javax.swing.text.ParagraphView;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import java.awt.*;

public class JTextPaneTest extends JFrame {

    public static void main(String[] args) {
        new JTextPaneTest();
    }

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

        JTextPane textPane = new JTextPane();
        textPane.setContentType("text/html");
        textPane.setEditorKit(new HTMLEditorKitWrapSupport());  // makes JTextPane ignore <br> tag

        // example 1 (JTextPane ignores <br> tag when using the custom HTMLEditorKit)
        textPane.setText("<html><body style='font-size:22pt'>  <p>Line 1 <br> Line 2</p>  </body></html>");

        // example 2 (the text should be wrapped and the JScrollPane's horizontal bar should not be visible)
        //textPane.setText("<html><body style='font-size:25pt'>  <p>LONGWORDWITHOUTSPACES_LONGWORDWITHOUTSPACES_LONGWORDWITHOUTSPACES_LONGWORDWITHOUTSPACES_LONGWORDWITHOUTSPACES_</p>  </body></html>");

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

        setSize(new Dimension(500, 500));
        setVisible(true);
    }

    class HTMLEditorKitWrapSupport extends HTMLEditorKit {

        @Override
        public ViewFactory getViewFactory() {

            return new HTMLEditorKit.HTMLFactory() {

                public View create(Element element) {

                    View view = super.create(element);

                    if (view instanceof InlineView) {

                        return new InlineView(element) {

                            @Override
                            public int getBreakWeight(int axis, float pos, float len) {
                                return GoodBreakWeight;
                            }

                            @Override
                            public View breakView(int axis, int p0, float pos, float len) {
                                if (axis == View.X_AXIS) {
                                    checkPainter();
                                    int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
                                    if (p0 == getStartOffset() && p1 == getEndOffset()) {
                                        return this;
                                    }
                                    return createFragment(p0, p1);
                                }
                                return this;
                            }
                        };

                    } else if (view instanceof ParagraphView) {
                        return new ParagraphView(element) {
                            protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements sizeRequirements) {
                                if (sizeRequirements == null) {
                                    sizeRequirements = new SizeRequirements();
                                }

                                float pref = layoutPool.getPreferredSpan(axis);
                                float min = layoutPool.getMinimumSpan(axis);

                                // Don't include insets, Box.getXXXSpan will include them.
                                sizeRequirements.minimum = (int) min;
                                sizeRequirements.preferred = Math.max(sizeRequirements.minimum, (int) pref);
                                sizeRequirements.maximum = Integer.MAX_VALUE;
                                sizeRequirements.alignment = 0.5f;
                                return sizeRequirements;
                            }

                        };
                    }
                    return view;
                }

            };
        }
    }    
}

0 个答案:

没有答案