防止在JTextPane中键入相同的样式

时间:2013-05-14 22:29:32

标签: java swing url text jtextpane

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

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

正如你在最texteditors知道你可以把你的插入符号/光标一块样式的文本(对于这是大胆的示例文本)的后面,那么你就可以在相同的风格继续输入(例如,追加更多的粗体字)。< / p>

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

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

EG。我认为tinymce有这种行为:

  • 您选择文字
  • 点击“插入网址”按钮
  • 插入网址
  • 将光标放在网址后面,然后以正常风格再次开始输入

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

我在考虑这样的事情:

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

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

        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

提前致谢。

2 个答案:

答案 0 :(得分:3)

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

StyledEditorKit的方法

public MutableAttributeSet getInputAttributes()

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

答案 1 :(得分:2)

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

从caretlistener中调用以下方法,传递通过&#34; getInputAttributes&#34; -function和插入符号的点和标记找到的属性。

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的末尾时,在最后一个字符后面=&gt;你删除了上面代码中可以看到的三个属性=&gt;但是,当插入符号移动到URL中的另一个位置时,该属性会保持删除状态,因为该集合不会更新。

所以在实践中这意味着当你从属性集中删除属性时,它们将保持被移除,直到StyledEditorKit更新inputattributes。

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

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

PS:HREF属性的比较是为了处理两个不同的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);
    ...
}