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.
精彩评论