在JTextPane中没有渲染CSS填充

时间:2016-09-03 21:57:48

标签: java html css swing jtextpane

我使用JTextPane呈现一些HTML。我使用HTMLEditorKitStyleSheetcode属性添加规则,因此它看起来与StackOverflow上的代码完全相同。问题是JTextPane不会在代码上呈现填充(1像素顶部/底部,左/右5像素),即使padding属性被列为其中一个属性渲染引擎in the documentation支持

以下是我期望看到的内容(如this CSSDeck Lab所示): Expected Output <子>←
↑ - ↑↑ - ↑
修改
我已经从使用HTML中的<code>标记切换到@Sharcoux的建议切换到<span>。这使得用于代码的字体大小与<pre>标签中的文本相同,使得红色背景与绿色边框具有相同的高度,但是,预期结果仍然不是产生的。如果您感兴趣,Here是原始图片。

实际出现的是: Actual Output

我也尝试过将CSS内联到文本中,但无济于事。

MCVE(也编辑):

import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

public class CodePaddingMCVE {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            JFrame frame = new JFrame("Code Padding Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JTextPane tp = new JTextPane();
            tp.setContentType("text/html");

            HTMLEditorKit kit = new HTMLEditorKit();
            tp.setEditorKit(kit);
            StyleSheet sheet = kit.getStyleSheet();
            sheet.addRule("span {padding: 1px 5px; background-color: red}"); //Using span here
            sheet.addRule("pre {padding: 0px; background-color: green}");
            tp.setDocument(kit.createDefaultDocument());
            tp.setText("<html><pre>NotCode<span>Code</span>NotCode</pre></html>"); //Using <span> here too

            JScrollPane sp = new JScrollPane(tp) {
                private static final long serialVersionUID = 1L;

                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(250, 50);
                }

            };

            frame.getContentPane().add(sp);
            frame.pack();
            frame.setVisible(true);
        });
    }

}

我正在使用OS X Yosemite 10.10.15,Eclipse Mars.2 4.5.2和Java 8 [1.8.0_66]。

1 个答案:

答案 0 :(得分:1)

你是对的,边距和填充似乎不适用于内联元素。你有3个选择。

1)放弃JTextPane并改为使用JavaFX WebView。

2)放弃HTMLDocument并使用其他实现。

3)尝试在HTMLEditorKit中扩展HTMLFactory,并扩展InlineView。它会给你一些东西:

import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.StyleSheet;

public class CodePaddingMCVE {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Code Padding Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JTextPane tp = new JTextPane();
                tp.setContentType("text/html");

                HTMLEditorKit kit = new HTMLEditorKit() {
                    public ViewFactory getViewFactory() {
                        return new HTMLFactory() {
                            public View create(Element elem) {
                                AttributeSet attrs = elem.getAttributes();
                                Object elementName =
                                    attrs.getAttribute(AbstractDocument.ElementNameAttribute);
                                Object o = (elementName != null) ?
                                    null : attrs.getAttribute(StyleConstants.NameAttribute);
                                if (o instanceof HTML.Tag) {
                                    HTML.Tag kind = (HTML.Tag) o;
                                    if (kind == HTML.Tag.CONTENT) {
                                        return new InlineView(elem) {
                                            private short left;
                                            private short right;
                                            private short top;
                                            private short bottom;
                                            protected void setPropertiesFromAttributes() {
                                                AttributeSet attr = getAttributes();
                                                if (attr != null) {
                                                    top = (short) StyleConstants.getSpaceAbove(attr);
                                                    left = (short) StyleConstants.getLeftIndent(attr);
                                                    bottom = (short) StyleConstants.getSpaceBelow(attr);
                                                    right = (short) StyleConstants.getRightIndent(attr);
                                                }
                                                super.setPropertiesFromAttributes();
                                            }
                                            //TODO : use the top, left, bottom and right properties to draw the margin/padding
                                        };
                                    }
                                }
                                return super.create(elem);
                            }
                        };
                    }
                };
                tp.setEditorKit(kit);
                StyleSheet sheet = kit.getStyleSheet();
                sheet.addRule("span {padding: 5px 5px 5px 5px; background-color: red}"); //Using span here
                sheet.addRule("pre {padding: 0px; background-color: green}");
                tp.setDocument(kit.createDefaultDocument());
                tp.setText("<html><pre>NotCode<span>Code</span>NotCode</pre></html>"); //Using <span> here too

                JScrollPane sp = new JScrollPane(tp) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(250, 50);
                    }

                };

                frame.getContentPane().add(sp);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

如果您希望继续使用此路径,则需要深入了解LabelView和GlyphView,以了解如何实现填充或边距。也许其他人可以帮助完成这个。

祝你好运。