KeyAdapter在JPanel类中不起作用,但在JFrame类中起作用

Get*_*awn 4 java swing

背景
我正在建立一个游戏库,以使游戏开发更快,到目前为止,它进展相当顺利.

我有以下内容:

  • 主要入门课程 public static void main(String[] args)
    • 这个类然后从我的库中启动一个类来调用 Game
    • 然后设置窗口大小,并增加了RoomJFrame
  • 当创建一个可扩展Room(Room是游戏关卡)类时,它会从房间开始一个线程来绘制添加到它的所有对象.
    • 对象可以添加事件(我被卡住的部分)

所以上面是主要想法所需要的.

这是入门课(非常简单).

package test;

import JGame.Game.Game;
import JGame.Room.Room;
import javax.swing.JFrame;
import test.Rooms.Room1;

public class Main extends JFrame{

    public static void main(String[] args){
        Game game = new Game("Test Game"); // This sets the window title
        game.start(800, 600); // This sets the size of the window

        Room room1 = new Room1();
        game.setRoom(room1);  // adds the JPanel to the main frame
    }
}
Run Code Online (Sandbox Code Playgroud)

Room1延伸Room.在Room1与该房间相关联的所有游戏对象中添加了该对象.

public class Room extends JPanel implements Runnable{
    ArrayList<GameObject> gameObjects = new ArrayList<>();
    @Override
    public void run(){
        try{
            while(true){
                this.repaint();
                Thread.sleep(5);
            }
        }
    }
    public void addGameObjectAt(GameObject gameObject, int x, int y){
        // Sets private variables in GameObject
        // These are then grabbed in the paintComponent to draw at that location
        gameObject.setX(x); 
        gameObject.setY(y);
        gameObjects.add(gameObject);
    }
    @Override
    public void paintComponent(Graphics g){
        g.drawImage(bg, 0, 0, this);
        for(int i = 0; i < gameObjects.size(); i++){
            GameObject go = gameObjects.get(i);
            g.drawImage(go.getSprite(), go.getX(), go.getY(), this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我们说我们创建一个房间:

public class Room1 extends Room{
    public Room1(){
        this.createShip();
    }
    public void createShip(){
        Ship = new Ship();
        // Add an object to a list setting its x,y to 10,10
        this.addGameObjectAt(ship, 10, 10);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这些对象不会添加到窗口中,addGameObjectAt只是将它们添加到一个ArrayList然后在Room中的线程中绘制到屏幕上.

现在我们添加Ship到房间,它可以在屏幕上使用paintComponent().一切正常!

这是事情开始停止工作的地方.现在我们已经Ship添加了一个类,我想添加一些关键事件,目前我必须添加Main它们才能工作,但我不想在那里添加它们,因为它变得混乱,我想将它们添加到Ship因为这是事件最终会产生的影响.

此代码不附加keylistener

// GameObject extends JPanel
public class Ship extends GameObject{
    public Ship(){
        this.addKeyListener(new AL());
    }

    public class AL extends KeyAdapter{

        @Override
        public void keyPressed(KeyEvent evt){
            System.out.println("here");
        }

        @Override
        public void keyReleased(KeyEvent evt){
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,按下一个键不会在这里打印出来,但是如果我将AL类和它移动addKeyListener()Game类它可以工作,但我不希望它在Game类中我想要它在Ship类中.

// This class just sets up the size of the application window
// It also holds an int list of all the game rooms
public class Game extends JFrame{

}
Run Code Online (Sandbox Code Playgroud)

我一直试图解决这个问题至少一个星期了,我似乎无法弄清楚我怎么能得到它以便它在Ship课堂上有效?

Rei*_*eus 5

JPanel不是一个可聚焦的组件,因此无法与之交互KeyEvents.

在Swing中,首选方法是使用Key Bindings.即使组件没有焦点,您也可以将Action映射到KeyStroke.

看这个例子

  • @RyanNaddy:我的第二个建议(1+) - 使用键绑定.如果它不能按照您的意愿工作,请告诉我们并告诉我们更多信息,我们可以提供帮助. (2认同)
  • @RyanNaddy如果我理解正确的话你应该使用各种各样的标志,例如布尔标志按下按键时的标记,或者不检查这些布尔值将允许你看看是否同时按下了2个按键(当然不要忘记根据需要重置标志)请看这里的例子:http://stackoverflow.com/questions/13825515/java-rectangle-collision-detection-confusion/13827649#13827649 (2认同)