0

请原谅我可能有误导性的标题,但这个问题有点难以描述。

我目前正在尝试使用 Java 中的 JTextPane 创建一个基本的文本编辑器,但遇到了一个问题。

正如您在大多数文本编辑器中所知道的那样,您可以将插入符号/光标放在一段样式文本(例如粗体文本)后面,然后您可以继续输入相同的样式(例如附加更多粗体字符)。

幸运的是,这在 JTextPane 中默认存在,但我想为某种样式禁用它。主要是我编码的 URL 样式(基本上这个只是将样式中的 HTML.Attribute.HREF 属性设置为 URL)。

因此,如果我将插入符号放在作为 URL 的单词(或一段文本)后面,我想确保将要添加的下一个字符不会采用 URL 样式。

例如。我认为tinymce有这种行为:

  • 你选择文字
  • 单击插入 URL 按钮
  • 插入网址
  • 将光标放在 URL 之后,然后以正常样式再次开始输入

有没有办法在 JTextPane 中强制执行此行为?

我在想这样的事情:

  • 为文档中的内容更改添加监听器
  • 检查添加的字符是否放置在带有 URLstyle 的文本的后面
  • 如果是这种情况=>从这些字符的样式中删除“href”属性

我用于将 URL 样式设置为所选文本的代码可以在下面找到。"dot" 和 "mark" 从插入符号中检索。

        SimpleAttributeSet attr = new SimpleAttributeSet(doc.getCharacterElement(dot).getAttributes());
        StyleConstants.setUnderline(attr, true);
        StyleConstants.setForeground(attr, Color.BLUE);
        attr.addAttribute(HTML.Attribute.HREF, url);
        doc.setCharacterAttributes((dot < mark) ? dot : mark, length, attr, true);

(注意:为了能够区分普通的“蓝色下划线”文本和 URL,HREF 属性用于 URL。)

PS:这是我在这里的第一个问题,所以希望我提供了足够的信息。;)

语言:Java、JDK 1.7

提前致谢。

4

2 回答 2

3

添加一个CaretListener检测移动并检查当前插入位置是否需要样式重置。如果检测到使用

StyledEditorKit的方法

public MutableAttributeSet getInputAttributes()

这里只需删除您不需要的属性(URL、蓝色、下划线)。

于 2013-05-15T06:14:45.673 回答
2

我想我会分享我对这个问题的解决方案(在 StanislavL 的回答的帮助下找到 - 再次感谢你让我走上正轨)。

从插入符监听器中调用以下方法,传递通过“getInputAttributes”函数找到的属性以及插入符的点和标记。

private void blockURLTyping(MutableAttributeSet inputAttr, int dot, int mark)
{
    StyledDocument doc = getStyledDocument();
    int begin = (dot < mark) ? dot - 1 : mark - 1;
    if(begin >= 0)
    {
        Element dotEl = doc.getCharacterElement(begin);
        Element markEl = doc.getCharacterElement((dot < mark) ? mark : dot);
        AttributeSet dotAttr = dotEl.getAttributes();
        AttributeSet markAttr = markEl.getAttributes();
        if(dotAttr.isDefined(HTML.Attribute.HREF)) // Ensure atleast one of them isn't null
        {
            if(dotAttr.getAttribute(HTML.Attribute.HREF) == markAttr.getAttribute(HTML.Attribute.HREF))
            {
                inputAttr.addAttribute(HTML.Attribute.HREF, dotAttr.getAttribute(HTML.Attribute.HREF));
                inputAttr.addAttribute(StyleConstants.Foreground, Color.BLUE);
                inputAttr.addAttribute(StyleConstants.Underline, true);
                return;
            }
        }
    }
    if(inputAttr.isDefined(HTML.Attribute.HREF)) // In all other cases => remove
    {
        inputAttr.removeAttribute(HTML.Attribute.HREF);
        inputAttr.removeAttribute(StyleConstants.Foreground);
        inputAttr.removeAttribute(StyleConstants.Underline);
    }
}

重要的提示; inputAttributes在插入位置更改但保持在同一元素内时不会更新。所以:当插入符号位于 URL 的末尾,在最后一个字符后面 => 删除上面代码中可以看到的三个属性 => 但是,当插入符号移动到 URL 中的另一个位置时,属性保持不变删除,因为该集不更新。

因此在实践中,这意味着当您从属性集中删除属性时,它们将一直被删除,直到 StyledEditorKit 更新输入属性。

为了解决这个问题,如果插入符号位于 URL 的中间,我决定再次添加属性,允许您在 URL 的中间插入字符 - 但不能附加或前置字符(就像我想要的那样)。

代码可能可以再优化一点,因为在大多数情况下 dot==mark,但我想分享这个解决方案。

PS:HREF-attributes的比较是为了处理一个文本中两个不同的URL位置相邻的情况。它基本上应该检查它们是否都是某个对象的不同实例,即使 URL 本身可能相同。

调用此函数的代码:

@Override
protected void fireCaretUpdate(CaretEvent e) 
{
    super.fireCaretUpdate(e);
    MutableAttributeSet attr = getStyledEditorKit().getInputAttributes();
    int dot = e.getDot();
    int mark = e.getMark();

    blockURLTyping(attr, dot, mark);
    ...
}
于 2013-05-15T13:00:04.473 回答