Why is my Key Listener not working within the code below?

import javax.swing.*;
import javax.swing.plaf.basic.BasicTreeUI;
import java.awt.*;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GamePanel extends JPanel implements Runnable, KeyListener{
    final int originTileSize = 16; //The Size of the tiles, or grids
    final int scale = 3;
    final int tileSize = originTileSize * scale;
    final int screenCol = 10;
    final int screenRow = 12;
    final int screenHeight = screenCol * tileSize; //480 pixels
    final int screenWidth = screenRow * tileSize; //576 pixels
    int FPS = 60;
    boolean upPressed = false, downPressed = false, rightPressed = false, leftPressed = false;

    Thread gameThread;


    int playerX = 100;
    int playerY = 100;
    int playerSpeed = 4;

    public GamePanel(){
        this.setPreferredSize(new Dimension(screenWidth, screenHeight));
        this.setBackground(Color.black);
        this.setDoubleBuffered(true);
        this.addKeyListener(this);
        this.setFocusable(true);
        this.requestFocus();

        //Changes the frame so the panel comes out like this

    }

    public void startGameThread(){
        gameThread = new Thread(this);
        //Puts everything in the Class into the thread
        gameThread.start();
        //automatically calls the run method
    }


    @Override
    public void run() {


        double drawInterval = 1000000000/FPS; //0.1666 seconds
        double nextDrawTime = System.nanoTime() + drawInterval;

        while(gameThread != null){
            update();

            repaint();

            try {
                double remainingTime = nextDrawTime - System.nanoTime();
                remainingTime = remainingTime/1000000;

                if(remainingTime < 0){
                    remainingTime = 0;
                }

                Thread.sleep((long) remainingTime);

                nextDrawTime += drawInterval;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
//While this game loop is here it will keep running whatever is inside

    }
    private void update() {

        if(upPressed){
            playerY -= playerSpeed;
        }
        else if(downPressed){
            playerY += playerSpeed;
        }
        else if(rightPressed){
            playerX += playerSpeed;
        }
        else if(leftPressed){
            playerX -= playerSpeed;
        }
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D)g;

        g2.setColor(Color.white);

        g2.fillRect(playerX, playerY, tileSize, tileSize);

        g2.dispose();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Pressed W");
        int code = e.getKeyCode();
        if(code == KeyEvent.VK_W){
            System.out.println("Press W");
            upPressed = true;
        }
        else if(code == KeyEvent.VK_A) {
            System.out.println("Pressed A");
            downPressed = true;
        }
        else if(code == KeyEvent.VK_D) {
            System.out.println("Pressed D");
            rightPressed = true;
        }
        else if(code == KeyEvent.VK_S) {
            System.out.println("Pressed S");
            downPressed = true;
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {
        int code = e.getKeyCode();
        System.out.println(code);
        if(code == KeyEvent.VK_W) {
            upPressed = false;
        }
        else if(code == KeyEvent.VK_A) {
            downPressed = false;
        }
        else if(code == KeyEvent.VK_D) {
            rightPressed = false;
        }
        else if(code == KeyEvent.VK_S) {
            downPressed = false;
        }

    }
    //This is where we will keep a game loop. A thread is where it'll always keep running and so a game loop will always be running in here unless closed.
}