JPanel上的KeyListener随机无响应 [英] KeyListener on JPanel randomly unresponsive

查看:104
本文介绍了JPanel上的KeyListener随机无响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用默认的Java KeyListener时遇到了麻烦. 我注意到有时启动时,KeyListener似乎并没有转发KeyEvent.

问题症状: 启动应用程序时,未处理按键输入.这仅在某些时候发生.有时,我必须关闭并启动应用程序7至8次,直到显示出来.有时这是第一次尝试.发生这种情况时,直到我再次重新启动应用程序,它才起作用.

我正在使用什么: Windows 7 x64以及最新的Eclipse和JDK版本.

我已经发现的内容: 我已经在调试模式下设置了一个断点,并检查了JPanel实例.看来,KeyListener总是总是成功添加到它的. 另外,MouseListener和MouseMotionListener一直都可以正常工作.

最小代码:

public class Player implements KeyListener
{
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e){ }

    public void keyPressed(KeyEvent e){
        System.out.println("Key Pressed!");
    }

}

public class Game {

    public static void main(String[] args) {
        new Game();
    } 

    public Game(){
        JFrame window = new JFrame();
        window.setVisible(true);

        //Now set the window size correctly
        window.setSize(800, 600);  
        //Set-up the rest of the window
        window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        window.setResizable(true);


        //Create our panel
        JPanel canvas = new JPanel();
        canvas.setFocusable(true);
        window.add( canvas ); //Add it to our window

        Player k = new Player();
        canvas.addKeyListener(k);
    }
}

谢谢您的时间!

PS: 好吧,回答我自己的问题:

似乎我必须在设置窗口大小后调用setVisible(true) :

    JFrame window = new JFrame();


    Now set the window size correctly
    window.setSize(800, 600);  
    window.setVisible(true);

像这样切换setSize()和setVisible()似乎可以使其工作.毫无问题地尝试了十几遍.

我想如果setVisible的大小为0x0,则可能不喜欢将Focus赋予窗口. 问题是:为什么这只会在某些情况下导致问题?

解决方案

尝试将JButton添加到画布" JPanel中,然后按该按钮并查看KeyListener发生了什么-失败是因为JPanel失去了焦点.为了防止这种情况的发生,请改用键绑定"(请参阅​​上面我的评论中的链接以获取本教程).例如,

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

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.

Symptoms of the problem: When starting the application key input isn't processed. This only happens sometimes. Sometimes I have to close and start the app 7-8 times until this shows up. Sometimes it's the first try. When it happens it won't work until I restart the app again.

What I'm using: Window 7 x64 and the newest Eclipse and JDK versions.

What I found out already: I've put a breakpoint in debug mode and checked the JPanel instance out. The KeyListener is always successfully added to it, it seems. Also, MouseListener and MouseMotionListener work just fine, all the time.

Minimal code:

public class Player implements KeyListener
{
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e){ }

    public void keyPressed(KeyEvent e){
        System.out.println("Key Pressed!");
    }

}

public class Game {

    public static void main(String[] args) {
        new Game();
    } 

    public Game(){
        JFrame window = new JFrame();
        window.setVisible(true);

        //Now set the window size correctly
        window.setSize(800, 600);  
        //Set-up the rest of the window
        window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        window.setResizable(true);


        //Create our panel
        JPanel canvas = new JPanel();
        canvas.setFocusable(true);
        window.add( canvas ); //Add it to our window

        Player k = new Player();
        canvas.addKeyListener(k);
    }
}

Thank you for your time!

PS: Ok, answer to my own question:

It seems that I have to call setVisible(true) after setting the window's size:

    JFrame window = new JFrame();


    Now set the window size correctly
    window.setSize(800, 600);  
    window.setVisible(true);

Switching out the setSize() and setVisible() like this seems to make it work. Tried it about a dozen times without a problem.

I guess setVisible might not like giving Focus to the window if it's of size 0x0. The question is: Why does this only cause a problem in one out of some cases?

解决方案

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

这篇关于JPanel上的KeyListener随机无响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆