开发者

Swing problem with InputMap/ActionMap

I want my JTextField to process the text not only when ENTER is pressed, but also when SPACE is开发者_Go百科 pressed. You can see in the code below that I associated the action that is usually associated with ENTER to SPACE, but I get some unexpected behavior (see below).

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

If I type "x SPACE" an ActionEvent is produced and the JTextField is cleared. However the refreshed JTextField is not a "null" string as requested, but " ". The SPACE from the previous action has "leaked" to the refreshed JTextField, which is quite annoying.

I looked in the swing code a bit. My best guess is that an ActionEvent is generated from some KeyEvent's, and KeyEvent.isConsumed() has different consequences depending if the KeyEvent was a ENTER or a SPACE (an ENTER is swallowed, but not a SPACE).

Anyone knows how to fix this? Or knows a different method to accomplish my goal?


Multiple events are being generated. Your code is being executed on a keyPressed event. However using the space bar also results in a keyTyped event being generated. This is handled by the text component after the keyPressed code has been executed, so the Document is cleared and then a space is added to it.

Anyone knows how to fix this?

Don't use a KeyListener.

Add your code to the end of the EDT so that is executes AFTER the Document has been updated with the space:

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() + "]");
            }
        });
    }
});


I adapted your test case to use a key listener to consume the space character when it was typed. Just add the following and leave the rest as is.

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

I believe the issue is that ENTER isn't a displayable character for the text field while the space character is. If you tried something similar like this with a text area my guess is that you would encounter the same problem with the ENTER key as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜