CSS JTextPane 中未呈现填充

CSS Padding not Rendered in JTextPane

我正在使用 JTextPane 渲染一些 HTML。我正在使用 HTMLEditorKit and a StyleSheet to add rules to the code property so it looks exactly like the code on Whosebug. The problem is that the JTextPane doesn't render the padding on the code (1 pixel top/bottom, 5 pixels left/right), even though the padding property is listed as one of the properties that is supported by the rendering engine in the documentation.

这是我希望看到的(如 this CSSDeck Lab 所示):
↑-↑ ↑-↑
编辑:
根据@Sharcoux 的建议,我已从 HTML 中的 <code> 标签切换到 <span>。这使得 used-to-be-code 的字体大小与 <pre> 标签中的文本相同,使红色背景与绿色边框具有相同的高度,但是,预期的结果仍然不是生产的。 Here原图有兴趣

这是实际出现的:

我也试过移动 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].

你是对的,外边距和内边距似乎不适用于内联元素。您有 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 以了解如何实现填充或边距。也许其他人可以帮助完成这个。

祝你好运。