java keylistener 未调用

Posted

技术标签:

【中文标题】java keylistener 未调用【英文标题】:java keylistener not called 【发布时间】:2012-01-18 21:59:35 【问题描述】:

我在 Java 中使用 KeyListener 编写了一个示例代码, 我创建了一个 JPanel,然后将其可聚焦设置为 true,我创建了一个 KeyListener,请求焦点,然后将 KeyListener 添加到我的面板中。但是永远不会调用 keyListener 的方法。似乎虽然我请求了焦点,但它没有焦点。

有人可以帮忙吗?

listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);

 class KeyLis implements KeyListener

    @Override
    public void keyPressed(KeyEvent e) 
        currentver += 5;
         switch (e.getKeyCode()) 
            case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;  
                 break;
            case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;  
                 break;
        
        repaint();
    

    @Override
    public void keyReleased(KeyEvent e) 
        // TODO Auto-generated method stub

    

    @Override
    public void keyTyped(KeyEvent e) 
    

如果需要任何可运行的代码:

  import java.awt.Color;
  import java.awt.Graphics;
  import java.util.Random;

  import javax.swing.JFrame;
  import javax.swing.JLabel;


 public class test extends JFrame 

private AreaOfGame areaOfGame;

public test()

    super("");
    setVisible(true);
    this.setBackground(Color.darkGray);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.pack();
    setLayout(null);
    setBounds(200, 10, 400, 700);

    areaOfGame = new AreaOfGame();
    this.add(areaOfGame);

    startGame();


public int generateNext()

    Random r = new Random();
    int n = r.nextInt(7);
    return n;


public void startGame()

    while(!areaOfGame.GameOver())
    
        areaOfGame.startGame(generateNext());
    



public static void main(String[] args) 
    new MainFrame();



import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JPanel;

public class AreaOfGame extends JPanel 


    private static final int rightside = 370;

    private int bottom;
    private int top;

    private int currentPos;
    private int currentver;
    private KeyLis listener;

    public AreaOfGame()
    
        super();

        bottom = 650;
        top = 50;
        setLayout(null);
        setBounds(20, 50, 350, 600);
        setVisible(true);


        this.setBackground(Color.lightGray);

        listener = new KeyLis();
        this.setFocusable(true);
        if(this.requestFocus(true))
            System.out.println("true");;
        this.addKeyListener(listener);


        currentPos = 150;
        currentver=0;
    

    public void startGame(int n)
    
        while(verticallyInBound())
            System.out.println("anything");

        


    

    public boolean verticallyInBound()
    
        if(currentPos<= bottom -50)
            return true;
        return false;
    


    public boolean GameOver()
    
        if(top>= bottom)
            System.out.println("game over");
            return true;
        

        else return false;
    


    public boolean horizontalyInBounds()
    
        if(currentPos<=rightside && currentPos>= 20)
            return true;
        else return false;
    


class KeyLis implements KeyListener

        @Override
        public void keyPressed(KeyEvent e) 
            System.out.println("called");
            currentver += 5;
             switch (e.getKeyCode()) 
                case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;  break;
                case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;  break;
            
            repaint();


        

        @Override
        public void keyReleased(KeyEvent e) 
            // TODO Auto-generated method stub

        

        @Override
        public void keyTyped(KeyEvent e) 
            System.out.println("called 3");
        



【问题讨论】:

如果你能给我们你的“KeyLis”课程会有所帮助,也许问题就在那里。 谢谢,我添加了监听类 嗯...我想我曾经遇到过类似的问题。尝试在 keyPressed(KeyEvent e) 方法的末尾调用方法“e.consume()”。让我知道它是否有效。 @BBB 尝试将System.out.println("something unique") 添加到侦听器的每个方法中。这将确保它们实际上没有被调用。 您的while (true) 循环正在锁定您的事件线程。 【参考方案1】:

我敢打赌,您会在 JPanel 被渲染之前请求焦点(在***窗口调用 pack()setVisible(true) 之前),如果是这样,这将不起作用。只有在渲染组件之后 才可能授予焦点请求。您是否检查过您对requestFocus() 的呼叫已返回?它必须返回 true 才能使您的呼叫有任何成功的机会。另外最好使用requestFocusInWindow() 而不是requestFocus()

但更重要的是,您不应该为此使用 KeyListeners,而是使用键绑定,这是 Swing 本身用来响应按键的更高级别的概念。

编辑SSCCE 的示例:

import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

public class TestKeyListener extends JPanel 
   private KeyLis listener;

   public TestKeyListener() 
      add(new JButton("Foo")); // something to draw off focus
      listener = new KeyLis();
      this.setFocusable(true);
      this.requestFocus();
      this.addKeyListener(listener);
   

   @Override
   public Dimension getPreferredSize() 
      return new Dimension(300, 200);
   

   private class KeyLis extends KeyAdapter 
      @Override
      public void keyPressed(KeyEvent e) 
         switch (e.getKeyCode()) 
         case KeyEvent.VK_LEFT:
            System.out.println("VK_LEFT pressed");
            break;
         case KeyEvent.VK_RIGHT:
            System.out.println("VK_RIGHT pressed");
            break;
         
      
   

   private static void createAndShowGui() 
      TestKeyListener mainPanel = new TestKeyListener();

      JFrame frame = new JFrame("TestKeyListener");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   

   public static void main(String[] args) 
      SwingUtilities.invokeLater(new Runnable() 
         public void run() 
            createAndShowGui();
         
      );
   

编辑 2 以及使用键绑定的等效SSCCE:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class TestKeyBindings extends JPanel 

   public TestKeyBindings() 
      add(new JButton("Foo")); // something to draw off focus
      setKeyBindings();
   

   private void setKeyBindings() 
      ActionMap actionMap = getActionMap();
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition );

      String vkLeft = "VK_LEFT";
      String vkRight = "VK_RIGHT";
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft);
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight);

      actionMap.put(vkLeft, new KeyAction(vkLeft));
      actionMap.put(vkRight, new KeyAction(vkRight));

   

   @Override
   public Dimension getPreferredSize() 
      return new Dimension(300, 200);
   

   private class KeyAction extends AbstractAction 
      public KeyAction(String actionCommand) 
         putValue(ACTION_COMMAND_KEY, actionCommand);
      

      @Override
      public void actionPerformed(ActionEvent actionEvt) 
         System.out.println(actionEvt.getActionCommand() + " pressed");
      
   

   private static void createAndShowGui() 
      TestKeyBindings mainPanel = new TestKeyBindings();

      JFrame frame = new JFrame("TestKeyListener");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   

   public static void main(String[] args) 
      SwingUtilities.invokeLater(new Runnable() 
         public void run() 
            createAndShowGui();
         
      );
   

编辑 3 关于您最近的 SSCCE,您的 while (true) 循环正在阻塞您的 Swing 事件线程,并且可能会阻止用户交互或绘画的发生。最好使用 Swing Timer 而不是 while (true)。例如:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;

import javax.swing.*;

public class BbbTest extends JFrame 

   private AreaOfGame areaOfGame;

   public BbbTest() 
      super("");
//      setVisible(true);
      this.setBackground(Color.darkGray);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.pack();
      setLayout(null);
      setBounds(200, 10, 400, 700);

      areaOfGame = new AreaOfGame();
      this.add(areaOfGame);
      setVisible(true);

      startGame();
   

   public int generateNext() 
      Random r = new Random();
      int n = r.nextInt(7);
      return n;
   

   public void startGame() 
      // while (!areaOfGame.GameOver()) 
      // areaOfGame.startGame(generateNext());
      // 

      areaOfGame.startGame(generateNext());
   

   public static void main(String[] args) 
      new BbbTest();
   

   class AreaOfGame extends JPanel 

      private static final int rightside = 370;

      private int bottom;
      private int top;

      private int currentPos;
      private int currentver;
      private KeyLis listener;

      public AreaOfGame() 
         super();

         bottom = 650;
         top = 50;
         setLayout(null);
         setBounds(20, 50, 350, 600);
         setVisible(true);

         this.setBackground(Color.lightGray);

         listener = new KeyLis();
         this.setFocusable(true);
         if (this.requestFocus(true))
            System.out.println("true");
         ;
         this.addKeyListener(listener);

         currentPos = 150;
         currentver = 0;
      

      public void startGame(int n) 
         // while (verticallyInBound()) 
         // System.out.println("anything");
         // 

         int timeDelay = 50; // msecs delay
         new Timer(timeDelay , new ActionListener() 

            public void actionPerformed(ActionEvent arg0) 
               System.out.println("anything");
            
         ).start();

      

      public boolean verticallyInBound() 
         if (currentPos <= bottom - 50)
            return true;
         return false;
      

      public boolean GameOver() 
         if (top >= bottom) 
            System.out.println("game over");
            return true;
         

         else
            return false;
      

      public boolean horizontalyInBounds() 
         if (currentPos <= rightside && currentPos >= 20)
            return true;
         else
            return false;
      

      class KeyLis implements KeyListener 

         @Override
         public void keyPressed(KeyEvent e) 
            System.out.println("called");
            currentver += 5;
            switch (e.getKeyCode()) 
            case KeyEvent.VK_LEFT:
               if (horizontalyInBounds())
                  currentPos -= 5;
               break;
            case KeyEvent.VK_RIGHT:
               if (horizontalyInBounds())
                  currentPos += 5;
               break;
            
            repaint();

         

         @Override
         public void keyReleased(KeyEvent e) 
            // TODO Auto-generated method stub

         

         @Override
         public void keyTyped(KeyEvent e) 
            System.out.println("called 3");
         
      
   

【讨论】:

实际上这些都是在我的框架有 pack() 和 setVisible(true) 之后完成的。如果使用键绑定是唯一的选择,我会这样做,但我真的很想知道为什么会这样不工作,因为之前似乎没有任何机构有这个问题,我检查了空指针、焦点、被调用的方法、正在添加的侦听器,但没有工作。 @BBB:再次,您是否检查过您的requestFocus() 方法调用已返回?是返回真还是假? 一直返回false 这实际上是我在我的问题中提到的,虽然我要求,但它似乎没有重点,这意味着它返回false,我不知道如何让它返回true。 @BBB:我的观点完全正确。那么除非你改变一些东西,否则你就没有成功的希望。如果您可以创建并发布一个小的可编译和可运行的程序,我们可以运行它并演示您的问题,这样我们就可以自己看到它,sscce。【参考方案2】:

可以使用“TAB”按钮在按钮和按键监听器之间切换。 我有一个带有一个按钮的程序,按下它后,按键监听器不起作用。 我意识到,如果你按下“TAB”按钮,程序的“注意”或“焦点”就会返回到关键监听器。

也许这会有所帮助:http://docstore.mik.ua/orelly/java-ent/jfc/ch03_08.htm

【讨论】:

以上是关于java keylistener 未调用的主要内容,如果未能解决你的问题,请参考以下文章

按下回车键时文本字段中的 KeyListener 未触发

如何在 KeyListener 中调用图形方法?

keyListener未检测到按键

如何在 Java 中正确使用 keyListener

改进我的键盘输入 (KeyListener) Java

Java KeyListener 与键绑定