KeyListener on JPanel randomly unresponsive

前端 未结 2 1282
夕颜
夕颜 2021-01-15 10:33

I\'m having trouble with the default Java KeyListener in my project. I noticed that the KeyListener doesn\'t seem to get KeyEvents forwarded sometimes when I start.

相关标签:
2条回答
  • 2021-01-15 11:00

    Try adding a JButton to your "canvas" JPanel, then pressing the button and seeing what happens to your KeyListener -- it fails because the JPanel lost the focus. To prevent this from happening, use Key Bindings instead (see the link in my comment above for the tutorial). For e.g.,

    import java.awt.event.*;
    import java.awt.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class Game2 {
    
       private static final String UP = "up";
    
       public static void main(String[] args) {
          new Game2();
       }
    
       public Game2() {
          JFrame window = new JFrame("Press up-arrow key");
          window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
          JPanel canvas = new JPanel();
          canvas.setPreferredSize(new Dimension(400, 300));
          window.add(canvas);
    
          canvas.add(new JButton(new AbstractAction("Press space-bar") {
             public void actionPerformed(ActionEvent e) {
                System.out.println("Button or space-bar pressed");
             }
          }));
          ActionMap actionMap = canvas.getActionMap();
          int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
          InputMap inputMap = canvas.getInputMap(condition);
    
          inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), UP);
          actionMap.put(UP, new UpAction());
    
          window.pack();
          window.setLocationRelativeTo(null);
          window.setVisible(true);
       }
    }
    
    @SuppressWarnings("serial")
    class UpAction extends AbstractAction {
       @Override
       public void actionPerformed(ActionEvent arg0) {
          System.out.println("Up Arrow pressed!");
       }
    }
    
    0 讨论(0)
  • 2021-01-15 11:03

    Don't know if this is related to your problems, but due to the intermittent nature of it perhaps it is...You should execute setVisible() last and in the swing thread. You could call setSize after setVisible if you want to, but the user might see a flicker and it likewise should be done in the swing thread. Do this as your last step:

    SwingUtilities.invokeLater( new Runnable() {
       public void run() {
          window.setVisible( true );
       }
    } );
    

    To do this, you will also need to make window declaration final:

    ...
    final JFrame window = new JFrame();
    ...
    
    0 讨论(0)
提交回复
热议问题