使用InputMap / ActionMap的Swing问题

时间:2011-08-02 17:39:18

标签: java swing

我希望我的JTextField不仅在按下ENTER时处理文本, 而且当按下SPACE时。您可以在下面的代码中看到我将通常与ENTER关联的操作关联到SPACE,但是我得到了一些意外的行为(见下文)。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class Test extends JFrame {

    private JTextField textField;

    public Test() {
        textField = new JTextField();
        add(textField);
        InputMap inputMap = this.textField.getInputMap();
        Object actionSubmit = inputMap.get(KeyStroke.getKeyStroke("ENTER"));
        Object actionSubmitSp = inputMap.get(KeyStroke.getKeyStroke("SPACE"));
        System.out.println("actionSubmit for space = " + actionSubmitSp);
        ActionMap actionMap = this.textField.getActionMap();
        Action action = actionMap.get(actionSubmit);
        System.out.println("actionSubmit = " + actionSubmit);
        textField.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),
                actionSubmit);

        textField.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent evt) {
                textField.setText(null);
                System.out.println("event received:[" + 
                        evt.getActionCommand() + "]");
            }
        });
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                Test test = new Test();
                test.pack();
                test.setVisible(true);
            }
        });
    }
}

如果我输入“x SPACE”,则会生成一个ActionEvent并清除JTextField。 但刷新了JTextField 不是请求的“空”字符串,而是“”。前一个动作的SPACE 已经“泄露”到刷新的JTextField,这非常烦人。

我看了一下挥杆码。我最好的猜测是从一些KeyEvent生成一个ActionEvent,而KeyEvent.isConsumed()具有不同的结果,这取决于KeyEvent是一个ENTER还是一个SPACE(吞下一个ENTER,但不是一个SPACE)。

任何人都知道如何解决这个问题?或者知道一种不同的方法来实现我的目标?

2 个答案:

答案 0 :(得分:4)

正在生成多个事件。您的代码正在keyPressed事件上执行。但是,使用空格键也会导致生成keyTyped事件。这是在执行keyPressed代码后由文本组件处理的,因此Document被清除,然后向其添加空格。

  

任何人都知道如何解决这个问题?

请勿使用KeyListener

将您的代码添加到EDT的末尾,以便在使用空格更新Document之后执行:

textField.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(final ActionEvent evt)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                textField.setText(null);
                System.out.println("event received:[" + evt.getActionCommand() + "]");
            }
        });
    }
});

答案 1 :(得分:2)

我调整了您的测试用例,以便在键入时使用键侦听器来使用空格字符。只需添加以下内容,其余部分保持不变。

    textField.addKeyListener(new KeyListener() {
        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == ' ') {
                System.out.println("Was a space character");
                e.consume();
            }
        }

        public void keyPressed(KeyEvent e) {
        }

        public void keyReleased(KeyEvent e) {
        }
    });

我认为问题是当空格字符是时,ENTER不是文本字段的可显示字符。如果您尝试使用文本区域进行类似的操作,我的猜测是您也会遇到与ENTER键相同的问题。