在JEditorPane中保留空的HTML行的格式

3

我注意到在HTML JEditorPane上如果有一行是空的,之前设置的所有样式都会消失。例如,查看下面的代码示例:

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTMLEditorKit;


public class BlankLineTester {
    private JEditorPane jep;

    public BlankLineTester() {
        String html = "<html><head></head><body>" +
                "<p><b>Line 1</b></p>" +
                "<p><b></b></p>" +
                "<p><b>Line 3</b></p>" +
                "</body></html>";

        jep = new JEditorPane();
        jep.setContentType("text/html");
        jep.setText(html);

        JFrame frame = new JFrame("Blank Line Test");
        frame.getContentPane().add(jep);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        System.out.println("Line 3 is " + isInputAttributeBold());

        jep.getCaret().setDot(8);
        System.out.println("Line 2 is " + isInputAttributeBold());

    }

    private boolean isInputAttributeBold() {
        AttributeSet attSet = ((HTMLEditorKit)jep.getEditorKit()).getInputAttributes();
        return StyleConstants.isBold(attSet);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BlankLineTester();
            }
        });
    }
}

第二行最初设置为空的粗体行,但在解析后,似乎没有保留粗体属性。另外请注意,如果您运行此程序并将光标放在第三行,然后删除该行上的所有内容,则您输入的下一个字符将不会是粗体。我想当HTMLDocument树中的叶子元素被删除时,它们所代表的文本也被消除了,但当用户运行它时,这种行为开始变得像有缺陷的行为。

有没有人有任何想法如何让样式属性在空行上解析,并在删除样式化行上的所有内容时保留样式属性?

谢谢! --安迪


为了更好地解释我的问题,我想保留字符级别的样式,即使该行为空(没有字符)。我上面提供的第一个示例更适合自动化示例,但我的第二个问题更能说明问题。如果我有粗体文本,删除该行上的所有内容,然后键入一些新字符,我希望新字符仍然是粗体的。也就是说,即使不再存在,空行上的输入属性也应保留其样式。在 MS Word 中尝试类似的操作,它会按照您的预期工作! - AndyI
我不认为在MS Word上会发生这种情况,尽管如果您将光标放在已经编写的内容上,那么当您将鼠标指针放在先前编写的字符上时,您的新字符将采用先前编写字符的字体。在JEditorPane中也是同样的情况,如果您运行此程序并尝试删除所有内容,请查看是否发生了这种情况,否则我可能误解了您的意思。 - nIcE cOw
是的,如果您查看StyledEditorKit中的AttributeTracker,它具有一个CaretListener,可以在光标移动时同步编辑器工具包中的输入属性。很酷。不幸的是,当一行为空时,没有字符元素来保存任何属性,因此输入属性会被设置为默认值(或从段落元素、样式表等继承的任何内容)。 - AndyI
1个回答

3

如果您这样编写而不是按照您自己的方式编写,则我想您将获得您想要的行为,就像b & /b一样,标签已经过时,尽管我正在使用JRE 1.7更新3,但以下行也可以正常工作:

String html = "<html><head></head><body>" +
                "<p style = \"font-weight:bold\">Line 1</p>" +
                "<p style = \"font-weight:bold\"></p>" +
                "<p style = \"font-weight:bold\">Line 3</p>" +
                "</body></html>";

尝试运行此代码,当您将光标移到开头时,尝试按Delete键,那么它将保留颜色GREEN,因为这是您的鼠标指针最后触摸到的字符的颜色,然后尝试通过将光标移到末尾并按下Backspace来保留颜色BLUE,因为这是您的鼠标指针最后触摸到的字符的颜色。第三次,只需在已提供的两行之间的每行中写入一个单词,有一行将显示红色字符,请尝试找到该行。我附上下面的图像以澄清红线情况。

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTMLEditorKit;


public class BlankLineTester {
    private JEditorPane jep;

    public BlankLineTester() {
        String html = "<html><head></head><body>" +
                "<p style = \"font-weight:bold; color: blue\">Line 1</p><br />" +
                "<p style = \"font-weight:bold; color: red\"></p><br />" +
                "<p style = \"font-weight:bold; color: green\">Line 3</p>" +
                "</body></html>";

        jep = new JEditorPane();
        jep.setContentType("text/html");
        jep.setText(html);

        JFrame frame = new JFrame("Blank Line Test");
        frame.getContentPane().add(jep);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        System.out.println("Line 3 is " + isInputAttributeBold());

        jep.getCaret().setDot(8);
        System.out.println("Line 2 is " + isInputAttributeBold());

    }

    private boolean isInputAttributeBold() {
        AttributeSet attSet = ((HTMLEditorKit)jep.getEditorKit()).getInputAttributes();
        return StyleConstants.isBold(attSet);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BlankLineTester();
            }
        });
    }
}

FONT STYLE


为什么不将每个“p”中定义的样式移动到“body”元素中?(我对OP试图实现什么非常困惑,所以可能完全离题。) - Andrew Thompson
没错,你总是很正确,这也是我想的,只是因为迄今为止与 OP 缺乏沟通,所以还没有涉及到这个字符串。 - nIcE cOw
是的,我知道<b>标签有点老派,但Swing中的HTML似乎也是来自同一学派,如果您将粗体属性应用于字符元素并序列化为HTML,则会写出这样的内容。您的方法很有趣-将属性应用于整个段落,但并不能完全满足我的需求,因为我需要在每行应用字符级属性,而这些属性在整个段落中不会统一。我会尝试在上面更好地解释我的问题。 - AndyI
感谢您抽出时间来处理这个问题,但是您正在段落级别上添加样式,即使字符消失也会保留。然而,这会强制该段落中的所有内容都具有该样式,至少作为基础。我要寻求的是保留字符级别的样式。为了看清我的意思,请在第3行使用以下内容:"<p><span style=\"color: green\">Line 3</span></p>"删除该行的所有内容,那么您键入的下一个字符将不再是绿色的。对我来说,解决方案可能只是在我认为用户意图时对段落元素应用样式。 - AndyI
非常欢迎,保持微笑 :-) ,我认为你所询问的情况是,你想保留每个字符的样式,这是可以实现的,但可能会很繁琐,如果你使用Map并遵循此线程中给出的建议。 - nIcE cOw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接