Tu Panel extiende de Canvas, debería ser de JPanel, ambos se aplica lo mismo para obtener el foco, cuando haces click obtienes el foco del panel que contiene los eventos del KeyListener dog.
Aqui la parte azul representa a ese Pseudo Panel que tienes
Por ningun lado vi a addKeyListener(this);
lo añadí en el método iniciar, entonces al darle click se habilita el KeyListener y el foco de ese Panel con requestFocus();
quedando
//Atributos:
private int ancho, alto; //el alto y el ancho del panel
private boolean play = false;//Variable que nos indica si la animación ha comenzado o no.
//... Más atributos. En general, objetos que deben ser pintados. Y variables que indican lo que
//tienen que hacer esos objetos durante la animación
private int espera = 1000;
//Constructor:
public Panel(int anch,
int alt
) { ancho = anch;
alto = alt;
play = false;
//Se construyen los demás atributos
setBackground
(Color.
BLUE);
}
//Aquí se pintan algunos de los atributos del objeto utilizando técnicas de doble bouffering
}
paint(G);
}
public void actualizar() {
//Nada.. Aquí se actualiza la posición de los objetos (atributos de Panel) que deben ser
//pintados durante la animación
}
@Override
public void run() {
while (play) {
actualizar();
repaint();
try {
}
//Y más cosas que no creo que vengan a cuento.
}
}
public void iniciar() {
play = true;
addKeyListener(this);
requestFocus();
hilo.start();
}
public void detener() {
play = false;
removeKeyListener(this);
}
//Metodos de KeyListener
}
if (e.getKeyChar() == 'a') {
//Se modifican los atributos necesarios para que la animación haga lo que tiene que
//hacer cuando se pulsa una 'a'
info("Letra A");
}
if (e.getKeyChar() == 's') {
//Lo mismo para la 's'
info("Letra S");
}
if (e.getKeyChar() == 'l') {
//...
info("Letra L");
}
if (e.getKeyChar() == 'ñ') {
//...
info("Letra Ñ");
}
}
@Override
if (e.getKeyChar() == 'a') {
//Se modifican los atributos necesarios para que la animación haga lo que tiene que
//hacer cuando se suelta la 'a'
info("Letra A soltada");
}
if (e.getKeyChar() == 's') {
//...
info("Letra s soltada");
}
if (e.getKeyChar() == 'l') {
//...
info("Letra l soltada");
}
if (e.getKeyChar() == 'ñ') {
//...
info("Letra ñ soltada");
}
}
}
Juego2
private boolean play = false;
private int anchoP = 900, altoP = 700;
//El constructor. No creo que tenga mucho interés para lo de mi duda pero lo pongo por si
//acaso:
public Juego2() {
panel
= new Panel(anchoP, altoP
);
setBackground
(new Color(240,
240,
240)); setLayout(null);
setDefaultCloseOperation
(JFrame.
DO_NOTHING_ON_CLOSE); setBounds(0, 0, 1300, 800);
setVisible(true);
boton.addActionListener(this);
getContentPane().add(boton);
boton.setBounds(20, 330, 250, 30);
getContentPane().add(panel);
panel.setBounds(300, 30, anchoP, altoP);
panel.setVisible(true);
@Override
"Información",
"Desea salir?",
0);
if(opc == 0) {
}
}
});
}
//el main
public static void main
(String[] args
) { new Thread(Juego2
::new).
start(); }
//El actionPerformed de la clase ActionListener
if (e.getSource() == boton) {
if (play) {
play = false;
boton.setText("play");
panel.detener();
} else {
play = true;
boton.setText("pause");
panel.iniciar();
}
}
}
}
Y una interface para los logs
/**
* logs
*/
public interface ShowData {
default Logger getLogger() {
return LoggerFactory.getLogger(getClass().getSimpleName());
}
default <T> void info(final T s) {
getLogger().info(s.toString());
}
default <T> void error(final T s) {
getLogger().warn(s.toString());
}
}