简体   繁体   中英

KeyAdapter doesn't work in JPanel class but works in JFrame class

Background
I am building a game library to make game development faster, and so far it is going fairly smoothly.

I have the following:

  • Main entry class public static void main(String[] args)
    • this class then initiates a class from my library called Game
    • then sets the window size and adds a Room to the JFrame
  • When an extendable Room (Room is a game level) class is created it it starts a thread from the room to draw all the objects added to it.
    • Objects can have events added to them (the part I am stuck on)

So above is what the main idea entails.

Here is the entry class (very simple).

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
    }
}

Room1 extends Room . Within Room1 all of the game object that are associated with that room are added to it.

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

So lets say we create a room:

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

Note: These objects are not added to the window with addGameObjectAt they are simply added to an ArrayList and then in the thread in Room are painted to the screen.

Now that we added Ship to the room it can be drawn on the screen using paintComponent() . This all works fine!

Here is where things start to stop working. Now that we have a Ship class added, I would like to add some key events, currently I have to add Main for them to work, but I don't want to add them there, because it gets messy, I would like to add them to Ship , since that is what the events will effect in the end.

This code doesn't attach the 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){
        }
    }
}

This doesn't work, pressing a key does not print out here , but if I move the AL class and the addKeyListener() to the Game class it works, but I don't want it in the Game class I want it in the Ship class.

// 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{

}

I have been trying to figure this out for at least a week now, and I can't seem figure out how can I get this so that it works in the Ship class?

JPanel is not a focusable component so cannot interact with KeyEvents .

In Swing, the preferred approach is to use Key Bindings . You can map an Action to a KeyStroke even when a component doesn't have focus.

See this example

I think you need to make the JPanel focusable. Try ship.setFocusable(true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM