【问题标题】:Best way to remap input of certain characters/keys to a JTextComponent?将某些字符/键的输入重新映射到 JTextComponent 的最佳方法?
【发布时间】:2013-04-03 10:38:50
【问题描述】:

我正在开发一个JTextPane,它的工作方式(几乎)与stackoverflow 上的标签输入字段完全一样。为此,只要用户点击输入、制表符或空格,我就会将文本转换为组件。自然地,我不希望将这些字符中的任何一个实际输入到文本窗格中。我找到了这个解决方案,SSCCE:

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);
    }
}

点击“tab”通常会导致插入一个制表符,点击“enter”通常会导致输入换行符,点击“space”会导致输入空格。奇怪的是,我的代码阻止了换行符和制表符的输入,但仍然允许正常输入空格,同时执行预期的操作。

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

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

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

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

【问题讨论】:

  • 请参阅How to Use Key Bindings 了解特殊操作名称“none”。
  • @trashgod 我已经读过,但我将其解释为,如果我不希望密钥导致任何其他行为(这是我想要的),那么我不能使用“无”动作。但关键是我没有使用“无”动作,我已经在使用正确命名的动作。
  • 糟糕,我虽然 SPACE 有一个绑定。也许使用DocumentListener
  • @trashgod 也许吧。为此,我需要更好地理解这一点。您能否指出一个教程或其他内容,在其中我可以了解在用户按下键和以编程方式预期的动作开始之间展开的确切事件链?
  • tutorial和其他examples

标签: java swing input keylistener jtextcomponent


【解决方案1】:
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag");

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

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

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

【讨论】:

  • 啊哈,“如果未指定 typedpressedreleased,则假定为 pressed。”
  • 这回答了我的问题 2 和 3,但它是否回答了问题 1?关键是,我以相同的方式注册所有三个键的事件(假设pressed),但它们的行为不同,因为实际上既没有输入制表符也没有输入换行符。我可以理解,如果新行的工作方式不同,因为它在不同系统上不是同一个字符,但选项卡应该是,对吧?
  • @SheridanVespo,所有键的行为都相同,即调用您的 finalizeTag 操作。当您按下空格键时,这也会生成一个 keyTyped 事件,该事件实际上是在 finalizeTag 操作执行后将“”添加到文档中的事件。 Tab 和 Enter 键不会生成 keyTyped 事件,因此不会向文档中添加任何内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
相关资源
最近更新 更多