【问题标题】:Have I found a bug in Java? Regarding AttributeSet我是否在 Java 中发现了错误?关于属性集
【发布时间】:2011-08-01 08:19:45
【问题描述】:

我一直在编写的应用程序中使用 JTextPane(或我的子类版本),因此我一直在使用 Styles。我的程序没有按照我想要的方式运行,我跟踪了我认为是 AttributeSet.containsAttributes(AttributeSet attributes) 方法中的错误的行为。我写了以下简短的程序来说明它:

import javax.swing.JTextPane;
import javax.swing.text.StyleConstants;
import javax.swing.text.Style;

public class StyleBug {
    public static void main(String[] args) {

        JTextPane textPane = new JTextPane();
        textPane.setText("This is a test string");

        Style bold = textPane.addStyle(BOLD, null);
        StyleConstants.setBold(bold, true);

        Style italic = textPane.addStyle(ITALIC, null);
        StyleConstants.setItalic(italic, true);

        int start = 5;
        int end = 10;

        textPane.getStyledDocument().setCharacterAttributes(start, end - start, textPane.getStyle(BOLD), false);
        textPane.getStyledDocument().setCharacterAttributes(start, end - start, textPane.getStyle(ITALIC), false);

        for(int i = start; i < end; i++)
            System.out.println(textPane.getStyledDocument().getCharacterElement(i).getAttributes()
            .containsAttributes(textPane.getStyle(BOLD))); //all print false
    }

    private static final String BOLD = "Bold";
    private static final String ITALIC = "Italic";
}

这是一个错误,还是我在这里遗漏了什么?

【问题讨论】:

  • 您指的是静态初始化吗?
  • textPane.getStyle(BOLD) 和 textPane.getStyle(ITALIC),
  • @Mikaveli,我指的错误是 containsAttributes 方法说文本不是粗体,即使我应用了具有 Bold 属性的样式。

标签: java swing coding-style jtextpane


【解决方案1】:

如果我注释掉这一行:

// textPane.getStyledDocument().setCharacterAttributes(start, end - start, textPane.getStyle(ITALIC), false);

然后它为所有元素打印 true。根据setCharacterAttributes 的Javadoc,它使用您传入的样式中的所有属性,因此您只需用ITALIC 选择覆盖BOLD 选择。

编辑:

我调出调试器并获得了getCharacterElement(5) 的属性数组。

[0] javax.swing.text.StyleConstants$FontConstants "italic"
[1] java.lang.Boolean "true"
[2] javax.swing.text.StyleConstants "name"
[3] java.lang.String "Italic"
[4] javax.swing.text.StyleConstants$FontConstants "bold"
[5] java.lang.Boolean "true"

如您所见,属性以 2 个为一组进行排序。italic 设置为 true,bold 设置为 true,name 设置为 "Italic"。这可能意味着一个角色的命名属性集只允许一个名称。请注意,未命名的属性已正确合并,因此即使您看不到某个特定的命名属性是否应用于角色,它在行为上也是您想要的。

【讨论】:

  • 感谢您帮助我解决这个问题。是的,我也注意到了。但是当我添加斜体属性时,我希望它保持粗体属性。我在 setCharacterAttributes 中使用的第四个参数应该确定新属性是覆盖旧属性还是与旧属性合并。来自 Javadoc:布尔替换 - 指示是否应在设置新属性之前清除先前的属性。如果为 true,则该操作将完全替换以前的属性。如果为 false,则新属性将与之前的属性合并。
  • (对不起,这是我第一次发帖)
  • @Mark 我已经编辑了我的答案,因为你已经指出了这一点。如果要将样式合并在一起,您似乎不能依赖样式的名称(这是有道理的)。
  • 非常感谢您的帮助。你完全正确地认为它在行为上是正确的;当我查看 JTextPane 时,这些字符都是粗体和斜体。在我看来,他们应该改变这种行为,这样样式的名称就不会被算作一个属性,而是无论如何。我将在下面发布我的工作。再次感谢你的帮助。你能告诉我你是如何启动调试器并获得这些信息的吗?我以前从未见过这种东西。
  • @Mark 我使用jetbrains.com/idea 作为我的IDE。我在末尾附近设置了一个断点,并使用“评估表达式”函数 (Alt+F8) 来评估textPane.getStyledDocument().getCharacterElement(5)。然后它给了我一个包含所有元素的树,其中一个是名为 attributes 的变量,其类型为 Object[]
【解决方案2】:

Bringer128 发现了上面的问题,不过我再澄清一点。

将样式添加到 JTextPane 时,作为参数传递的字符串实际上作为属性放置在样式中(毫不奇怪,NameAttribute)。当 Style 应用于一系列字符时,NameAttribute 将与 Style 上设置的任何其他属性一起应用。因此,当应用我的 BOLD 样式时,该范围内的每个字符都将其 BoldAttribute 设置为 true,并将其 NameAttribute 设置为“Bold”。然后,当应用我的 ITALIC 样式时,每个字符的 ItalicAttribute 设置为 true,然后 NameAttribute 设置为“Italic”。然后,当 containsAttributes() 检查我的 BOLD 样式中的所有属性是否都应用于这些字符时,它返回 false,因为它们的 NameAttributes 已从“Bold”更改为“Italic”。我希望这不会让任何人感到困惑。

这是我的工作(我认为它实际上比原始代码更简单)。它的要点是我从不使用 Styles 或 JTextPane.addStyle() 。我只是保持不变的 MutableAttributeSets。

import javax.swing.JTextPane;
import javax.swing.text.StyleConstants;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;

public class StyleBugFix {
    public static void main(String[] args) {

        JTextPane textPane = new JTextPane();
        textPane.setText("This is a test string");

        StyleConstants.setBold(BOLD, true);

        StyleConstants.setItalic(ITALIC, true);

        int start = 5;
        int end = 10;

        textPane.getStyledDocument().setCharacterAttributes(start, end - start, BOLD, false);
        textPane.getStyledDocument().setCharacterAttributes(start, end - start, ITALIC, false);
        for(int i = start; i < end; i++)
            System.out.println(textPane.getStyledDocument().getCharacterElement(i).getAttributes()
                .containsAttributes(BOLD)); //all now print true
    }

    private static final MutableAttributeSet BOLD = new SimpleAttributeSet();
    private static final MutableAttributeSet ITALIC = new SimpleAttributeSet();
}

再次感谢 Bringer128 提供的所有帮助。

【讨论】:

  • +1 用于发布最终解决方案作为答案。这应该可以帮助遇到此问题的其他任何人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 2011-02-11
  • 2011-04-26
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
相关资源
最近更新 更多