2013-04-03 43 views
1

我正在研究一个JTextPane,它几乎和stackoverflow上的标签输入字段一样。为此,只要用户点击输入,标签或空格,我就会将文本转换为组件。当然,我不希望任何这些字符实际上被输入到文本窗格。我发现这个解决方案,SSCCE:将某些字符/键的输入重新映射到JTextComponent的最佳方法?

import java.awt.Color; 
import java.awt.event.ActionEvent; 

import javax.swing.AbstractAction; 
import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JTextPane; 
import javax.swing.KeyStroke; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.Element; 
import javax.swing.text.StyledDocument; 

@SuppressWarnings("serial") 
public class TagTextPane extends JTextPane { 

    public TagTextPane() { 
     this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag"); 
     this.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "finalizeTag"); 
     this.getInputMap().put(KeyStroke.getKeyStroke("TAB"), "focusNext"); 
     this.getActionMap().put("focusNext", new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       finalizeTag(); 
       transferFocus(); 
      } 
     }); 
     this.getActionMap().put("finalizeTag", new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       finalizeTag(); 
      } 
     }); 
    } 

    private void finalizeTag() { 
     StyledDocument doc = (StyledDocument) getDocument(); 
     Element element = doc.getCharacterElement(getCaretPosition() - 1); 
     int start = element.getStartOffset(); 
     int len = element.getEndOffset() - start; 
     String tag = ""; 
     try { 
      tag = this.getDocument().getText(start, len); 
     } catch (BadLocationException e) { 
     } 
     this.setSelectionStart(start); 
     this.setSelectionEnd(start + len); 
     JLabel label = new JLabel(tag); 
     label.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     this.insertComponent(label);   
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("TagTextPaneTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     TagTextPane tPane = new TagTextPane(); 
     frame.setSize(400, 100); 
     frame.getContentPane().add(tPane); 
     frame.setVisible(true); 
    } 
} 

击中“标签”通常会导致要插入一个制表符,打“回车”,通常将导致进入一个换行符,以及打击“空间”导致空间被输入。奇怪的是,我的代码停止输入换行符和制表符,但仍允许在执行预期操作时正常输入空格。

  1. 为什么这种方法对这些密钥的行为不同?

  2. 如何阻止输入空间? (也许我想稍后将此行为扩展为逗号等等。)

  3. 如何最佳地控制JTextComponent中某些字符和击键的行为?我见过this,其中建议使用KeyListener,但我也看到this,Rob Camick指出,为什么不应使用KeyListener。所以我应该使用DocumentFilter还是在轮子上打蝴蝶?

  4. 这甚至是建立这种标签输入字段的最佳方式吗?

+0

参见[*如何使用按键绑定*](http://docs.oracle.com/javase/tutorial/uiswing/misc /keybinding.html)有关特殊操作名称“none”。 – trashgod

+0

@trashgod我已经阅读过,但是我的解释是,如果我不想让密钥导致任何其他行为(这是我想要的),那么我就不能使用“无”行为。但重点是我没有使用“无”操作,我已经使用了正确命名的操作。 – nfs

+0

哎呀,我虽然'SPACE'有约束力。也许使用一个'DocumentListener'? – trashgod

回答

2
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag"); 

这是处理的空格字符keyPressed事件。

你要处理的空格字符的事件的keyTyped:

this.getInputMap().put(KeyStroke.getKeyStroke(' '), "finalizeTag"); 
+0

啊哈,“如果输入','按'或'释放'没有指定,则按'按'。” – trashgod

+0

这回答我的问题没有2和3,但它回答没有1?重点是,我以同样的方式(假设'按')注册所有三个键的事件,但它们的行为不同,因为实际上没有键入选项卡和换行符。我可以理解,如果新行的工作方式不同,因为它在不同的系统上不是同一个字符,但标签应该是,对吧? – nfs

+0

@SheridanVespo,所有的键都表现相同,也就是说,你的finalizeTag动作被调用。当您按下空格键时,这也会生成一个keyTyped事件,该事件实际上是在执行完finalizeTag动作之后将“”添加到文档的事件。 Tab和Enter键不会生成keyTyped事件,因此没有任何内容添加到文档中。 – camickr

相关问题