elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  Duda manejando eventos de teclado en Java
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Duda manejando eventos de teclado en Java  (Leído 2,340 veces)
niano

Desconectado Desconectado

Mensajes: 20


Ver Perfil
Duda manejando eventos de teclado en Java
« en: 11 Julio 2019, 12:26 pm »

Hola.

Soy algo novato en todo esto de las interfaces gráficas y animaciones y tengo algunas dudas con un código en Java que estoy confeccionando. Necesito crear una animación controlada por cuatro teclas del teclado que empiece o se detenga cuando se aprieta un botón con el ratón.

Para eso defino utilizo una clase a la que he llamado Panel:

Código
  1. public class Panel extends Canvas implements Runnable, KeyListener{
  2.  
  3.    //Atributos:
  4.    private int ancho, alto; //el alto y el ancho del panel
  5.    private boolean play=false;//Variable que nos indica si la animación ha comenzado o no.
  6.    //... Más atributos. En general, objetos que deben ser pintados. Y variables que indican lo que
  7.    //tienen que hacer esos objetos durante la animación
  8.  
  9.    //Constructor:
  10.    public Panel(int anch, int alt)
  11.    {
  12.         ancho=anch;
  13.         alto=alt;
  14.         play=false;
  15.         //Se construyen los demás atributos
  16.    }
  17.  
  18.    public void paint (Graphics G)
  19.    {
  20.         //Aquí se pintan algunos de los atributos del objeto utilizando técnicas de doble bouffering
  21.    }
  22.  
  23.    public void update (Graphics G)
  24.    {
  25.        paint (G);
  26.    }
  27.  
  28.    public void actualizar()
  29.    {
  30.        //Nada.. Aquí se actualiza la posición de los objetos (atributos de Panel) que deben ser
  31.        //pintados durante la animación
  32.    }
  33.  
  34.    public void run()
  35.    {
  36.        while (play)
  37.        {
  38.            actualizar();
  39.            repaint();
  40.            try
  41.            {
  42.                Thread.sleep((int)espera);
  43.            }
  44.            catch (InterruptedException E)
  45.            {}
  46.            //Y más cosas que no creo que vengan a cuento.
  47.        }
  48.    }
  49.    public void Iniciar()
  50.    {
  51.        play=true;
  52.        Thread hilo=new Thread(this);
  53.        hilo.start();
  54.    }
  55.    public void Detener()
  56.    {
  57.        play=false;
  58.    }
  59.    //Metodos de KeyListener
  60.    public void keyTyped(KeyEvent e) {
  61.    }
  62.    public void keyPressed(KeyEvent e)
  63.    {
  64.        if (e.getKeyChar()=='a')
  65.        {
  66.            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
  67.            //hacer cuando se pulsa una 'a'
  68.        }
  69.        if (e.getKeyChar()=='s')
  70.        {
  71.            //Lo mismo para la 's'
  72.        }
  73.        if (e.getKeyChar()=='l')
  74.        {
  75.            //...
  76.        }
  77.        if (e.getKeyChar()=='ñ')
  78.        {
  79.            //...
  80.        }
  81.    }
  82.  
  83.    @Override
  84.    public void keyReleased(KeyEvent e)
  85.    {
  86.        if (e.getKeyChar()=='a')
  87.        {
  88.            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
  89.            //hacer cuando se suelta la 'a'
  90.        }
  91.        if (e.getKeyChar()=='s')
  92.        {
  93.           //...
  94.        }
  95.        if (e.getKeyChar()=='l')
  96.        {
  97.           //...
  98.        }
  99.        if (e.getKeyChar()=='ñ')
  100.        {
  101.            //...
  102.        }
  103.    }
  104.  
  105. }
  106.  

Y otra clase, la clase Juego2:

Código
  1. public class Juego2 extends JFrame implements ActionListener
  2. {
  3.    private Panel P;
  4.    private JButton boton;
  5.    private boolean play=false;
  6.    private int anchoP=900, altoP=700;
  7.  
  8.    //El constructor. No creo que tenga mucho interés para lo de mi duda pero lo pongo por si
  9.    //acaso:
  10.    public Juego2()
  11.    {
  12.        P=new Panel (anchoP,altoP);
  13.        boton=new JButton("play");
  14.        setBackground(new Color(240,240,240));
  15.        setLayout(null);        
  16.        boton.addActionListener(this);
  17.  
  18.        getContentPane().add(boton);
  19.        boton.setBounds(20,330,250,30);
  20.  
  21.        getContentPane().add(P);
  22.        P.setBounds(300, 30, anchoP, altoP);
  23.        P.setVisible(true);
  24.  
  25.        addWindowListener(new WindowAdapter(){
  26.            public void windowClosing(WindowEvent e){
  27.                System.exit(0);
  28.            }
  29.        });
  30.    }
  31.  
  32.    //el main
  33.    public static void main(String[] args) {
  34.        final Juego2 F = new Juego2();
  35.        F.setBounds(0, 0, 1300, 800);
  36.        F.setVisible(true);
  37.    }
  38.  
  39.    //El actionPerformed de la clase ActionListener
  40.    public void actionPerformed(ActionEvent e) {
  41.        if (e.getSource()==boton)
  42.        {
  43.            if (play)
  44.            {
  45.                play=false;
  46.                boton.setText("play");
  47.                P.Detener();
  48.            }
  49.            else
  50.            {
  51.                play=true;
  52.                boton.setText("pause");
  53.                P.Iniciar();
  54.            }
  55.        }
  56.    }
  57. }
  58.  

A continuación explicaré el fenómeno que me crea dudas.Cuando el código está listo hago lo siguiente:

1) Ejecuto el código. La cosa va bien, todo se construye y se visualiza correctamente.
2) Le doy al play. Y la animación comienza correctamente.
3) Le doy a una de las teclas controladoras y no ocurre nada. ¡Nada de nada!
4) Hago un 'click' de ratón sobre el panel y desde entonces ya sí funciona todo bien. El 'click' tiene que ser sobre el panel, si lo hago sobre otro punto de la ventana o fuera de ella las teclas controladoras siguen inactivas.

¿Alguien sabe por qué pasa esto y cómo puedo solucionarlo? Es decir, me gustaría que las teclas controladoras funcionasen desde que le doy al play, que no fuese necesario hacer ese 'click'.

Muchas gracias de antemano por vuestro tiempo. Un saludo.


En línea

rub'n


Desconectado Desconectado

Mensajes: 1.217


(e -> λ("live now")); tatuar -> λ("α");


Ver Perfil WWW
Re: Duda manejando eventos de teclado en Java
« Respuesta #1 en: 11 Julio 2019, 16:08 pm »

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  :xD



Por ningun lado vi a

Código
  1. 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

Código
  1. requestFocus();

quedando

Código
  1. public class Panel extends Canvas implements Runnable, KeyListener, ShowData {
  2.  
  3.    //Atributos:
  4.    private int ancho, alto; //el alto y el ancho del panel
  5.    private boolean play = false;//Variable que nos indica si la animación ha comenzado o no.
  6.    //... Más atributos. En general, objetos que deben ser pintados. Y variables que indican lo que
  7.    //tienen que hacer esos objetos durante la animación
  8.    private int espera = 1000;
  9.  
  10.    //Constructor:
  11.    public Panel(int anch, int alt) {
  12.        ancho = anch;
  13.        alto = alt;
  14.        play = false;
  15.        //Se construyen los demás atributos
  16.        setBackground(Color.BLUE);
  17.  
  18.    }
  19.  
  20.    public void paint(Graphics G) {
  21.        //Aquí se pintan algunos de los atributos del objeto utilizando técnicas de doble bouffering
  22.    }
  23.  
  24.    public void update(Graphics G) {
  25.        paint(G);
  26.    }
  27.  
  28.    public void actualizar() {
  29.        //Nada.. Aquí se actualiza la posición de los objetos (atributos de Panel) que deben ser
  30.        //pintados durante la animación
  31.    }
  32.  
  33.    @Override
  34.    public void run() {
  35.        while (play) {
  36.            actualizar();
  37.            repaint();
  38.            try {
  39.                Thread.sleep(espera);
  40.            } catch (InterruptedException E) {
  41.            }
  42.            //Y más cosas que no creo que vengan a cuento.
  43.        }
  44.    }
  45.  
  46.    public void iniciar() {
  47.        play = true;
  48.        addKeyListener(this);
  49.        requestFocus();
  50.        Thread hilo = new Thread(this);
  51.        hilo.start();
  52.    }
  53.  
  54.    public void detener() {
  55.        play = false;
  56.        removeKeyListener(this);
  57.    }
  58.  
  59.    //Metodos de KeyListener
  60.    public void keyTyped(KeyEvent e) {
  61.    }
  62.  
  63.    public void keyPressed(KeyEvent e) {
  64.        if (e.getKeyChar() == 'a') {
  65.            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
  66.            //hacer cuando se pulsa una 'a'
  67.            info("Letra A");
  68.        }
  69.        if (e.getKeyChar() == 's') {
  70.            //Lo mismo para la 's'
  71.            info("Letra S");
  72.        }
  73.        if (e.getKeyChar() == 'l') {
  74.            //...
  75.            info("Letra L");
  76.        }
  77.        if (e.getKeyChar() == 'ñ') {
  78.            //...
  79.            info("Letra Ñ");
  80.        }
  81.    }
  82.  
  83.    @Override
  84.    public void keyReleased(KeyEvent e) {
  85.        if (e.getKeyChar() == 'a') {
  86.            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
  87.            //hacer cuando se suelta la 'a'
  88.            info("Letra A soltada");
  89.        }
  90.        if (e.getKeyChar() == 's') {
  91.            //...
  92.            info("Letra s soltada");
  93.        }
  94.        if (e.getKeyChar() == 'l') {
  95.            //...
  96.            info("Letra l soltada");
  97.        }
  98.        if (e.getKeyChar() == 'ñ') {
  99.            //...
  100.            info("Letra ñ soltada");
  101.        }
  102.    }
  103.  
  104. }

Juego2

Código
  1. public class Juego2 extends JFrame implements ActionListener {
  2.  
  3.    private Panel panel;
  4.    private JButton boton;
  5.    private boolean play = false;
  6.    private int anchoP = 900, altoP = 700;
  7.  
  8.    //El constructor. No creo que tenga mucho interés para lo de mi duda pero lo pongo por si
  9.    //acaso:
  10.    public Juego2() {
  11.        panel = new Panel(anchoP, altoP);
  12.        boton = new JButton("play");
  13.  
  14.        setBackground(new Color(240, 240, 240));
  15.        setLayout(null);
  16.        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  17.        setBounds(0, 0, 1300, 800);
  18.        setVisible(true);
  19.  
  20.        boton.addActionListener(this);
  21.  
  22.        getContentPane().add(boton);
  23.        boton.setBounds(20, 330, 250, 30);
  24.  
  25.        getContentPane().add(panel);
  26.        panel.setBounds(300, 30, anchoP, altoP);
  27.        panel.setVisible(true);
  28.  
  29.        addWindowListener(new WindowAdapter() {
  30.            @Override
  31.            public void windowClosing(WindowEvent e) {
  32.                final int opc = JOptionPane.showConfirmDialog(null,
  33.                        "Información",
  34.                        "Desea salir?",
  35.                        0);
  36.                if(opc == 0) {
  37.                    System.exit(0);
  38.                }
  39.            }
  40.        });
  41.  
  42.    }
  43.  
  44.    //el main
  45.    public static void main(String[] args) {
  46.        new Thread(Juego2::new).start();
  47.    }
  48.  
  49.    //El actionPerformed de la clase ActionListener
  50.    public void actionPerformed(ActionEvent e) {
  51.        if (e.getSource() == boton) {
  52.            if (play) {
  53.                play = false;
  54.                boton.setText("play");
  55.                panel.detener();
  56.            } else {
  57.                play = true;
  58.                boton.setText("pause");
  59.                panel.iniciar();
  60.            }
  61.        }
  62.    }
  63. }
  64.  

Y una interface para los logs

Código
  1. /**
  2.  * logs
  3.  */
  4. public interface ShowData {
  5.  
  6.    default Logger getLogger() {
  7.        return LoggerFactory.getLogger(getClass().getSimpleName());
  8.    }
  9.  
  10.    default <T> void info(final T s) {
  11.        getLogger().info(s.toString());
  12.    }
  13.  
  14.    default <T> void error(final T s) {
  15.        getLogger().warn(s.toString());
  16.    }
  17. }


« Última modificación: 11 Julio 2019, 21:24 pm por rub'n » En línea

rubn0x52.com KNOWLEDGE  SHOULD BE FREE.
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen king
niano

Desconectado Desconectado

Mensajes: 20


Ver Perfil
Re: Duda manejando eventos de teclado en Java
« Respuesta #2 en: 11 Julio 2019, 19:04 pm »

Hola rub'n.

Antes de nada muchas gracias por tu respuesta, me ha sido muy útil. He hecho los cambios que me has indicado y ya funciona todo perfectamente. No obstante, me gustaría hacer un par de preguntas y observaciones si no te importa.


Tu Panel extiende de Canvas, debería ser de JPanel, ambos se aplica lo mismo para obtener el foco, cuando haces click obtienes el focu del panel que contiene los eventos del KeyListener dog.


¿Te importaría indicarme, aunque sea por encima, qué ventajas tiene la clase JPanel sobre la Canvas? Según tengo entendido la clase JPanel es más nueva y todo eso. Además, es cierto que con la Canvas sigue sin funcionar el asunto. Lo que sucede es que la clase JPanel creo que no la controlo demasiado. Tampoco sé lo que es un dog  :huh:

En otro ejercicio que me planteé parecido a este, si utilizaba la clase JPanel me empezaban a salir componentes como botones y cuadros de texto sobre el panel si hacía algo con ellos, cuando en un principio debían estar fuera. ¿Qué te parece?¿Sabrías decirme por qué me podía estar pasando eso? Con la Canvas no me pasaba y por eso renegué de la clase JPanel. Leeré algo más sobre la JPanel a ver si me familiarizo un poco más con ella.

Por ningun lado vi a

Código
  1. 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

Código
  1. requestFocus();

Sí, tienes toda la razón, se me olvidó lo del addKeyListener cuando escribí el mensaje, aunque sí que lo tenía en mi código, dentro del constructor de la clase Panel.

Supongo que la clave para solucionar el problema está en lo del requestFocus(). No conocía ese método. Si lo quito los métodos de la KeyListener no se activan, por muchos 'clicks' que haga. Sin embargo, si utilizo una Canvas, es indiferente ponerlo o no ponerlo. Para que se ejecuten los métodos del KeyListener hay que hacer 'click'. ¿Sabes por qué? ¿O sabes dónde puedo encontrar información sobre todo esto? Me temo que el material que tengo es bastante corto para responderme a todas las preguntas que me surgen cuando pongo las cosas en práctica.

Por otro lado, dentro del detener:
.
Código
  1. public void detener() {
  2.    play = false;
  3.    removeKeyListener(this);
  4. }
  5.  

¿Qué hace ese removeKeyListener? ¿Es necesario? No lo había visto nunca, en mi corta experiencia en estos asuntos.

Y para finalizar, añadir que me has dado una buena idea con la modificación del windowClosing para que el programa confirme que realmente se quiere salir. Empiezo ahora también con los cuadros de diálogo. A ver si poco a poco me voy aclarando.

Y eso, que muchísimas gracias por todo, en serio. Un saludo.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Keylogger sin Eventos del teclado
Programación Visual Basic
hackper 1 2,210 Último mensaje 14 Diciembre 2005, 21:48 pm
por Slasher-K
Ayuda, eventos de Teclado no es escuchado en JPANEL
Java
DarkSorcerer 5 8,322 Último mensaje 6 Mayo 2013, 17:02 pm
por sapito169
Diferenciar eventos según teclado C#
.NET (C#, VB.NET, ASP)
kondrag_X1 3 3,458 Último mensaje 22 Abril 2015, 15:50 pm
por kondrag_X1
Ayuda con eventos del teclado
Java
sebast345 3 2,569 Último mensaje 18 Noviembre 2016, 13:22 pm
por Orubatosu
Comparar eventos de teclado con strings (C#)
.NET (C#, VB.NET, ASP)
Alejovsq 3 2,964 Último mensaje 9 Agosto 2019, 01:34 am
por Alejovsq
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines