Codemaker Interfaces

Interfaces Tema 3

Eventos

Un evento es algo que hace el usuario: pulsar un botón, escribir, marcar una casilla, mover un deslizador… Un programa con ventanas no hace nada por sí solo: espera, y cuando llega un evento, ejecuta el código que le hayas preparado para él.

Un evento: el usuario pulsa el botón, Swing lo detecta, se ejecuta tu código y la ventana cambia

Reaccionar a un botón#

Para decirle a un botón qué hacer al pulsarlo se usa addActionListener:

Java
boton.addActionListener(e -> {
    // lo que pasa cada vez que se pulsa el botón
});

La flecha -> se lee «cuando pase, haz esto». Lo que va entre las llaves no se ejecuta ahora, sino cada vez que se pulse el botón. (Ese trozo de código se llama lambda, y la e trae información del evento, que de momento no necesitamos.)

Un contador de clics:

Java
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;

public class Contador {
    static int clics = 0;

    public static void main(String[] args) {
        FlatLightLaf.setup();
        SwingUtilities.invokeLater(() -> {
            JFrame ventana = new JFrame("Contador");
            ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel();
            JButton boton = new JButton("Púlsame");
            JLabel etiqueta = new JLabel("Has pulsado 0 veces");
            panel.add(boton);
            panel.add(etiqueta);

            boton.addActionListener(e -> {
                clics++;
                etiqueta.setText("Has pulsado " + clics + " veces");
            });

            ventana.add(panel);
            ventana.setSize(360, 120);
            ventana.setLocationRelativeTo(null);
            ventana.setVisible(true);
        });
    }
}

El contador después de pulsar tres veces: «Has pulsado 3 veces»

Nota

clics está fuera del main, como static int clics. Dentro de una lambda no se puede cambiar una variable local del main: Java da un error (lo tienes en la tabla del final).

Leer lo que ha escrito el usuario#

Lo normal es que el botón use lo que hay en otros componentes. Aquí, el saludo lee el campo de texto, y si está vacío avisa con una ventanita (JOptionPane):

Java
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;

public class Saludo {
    public static void main(String[] args) {
        FlatLightLaf.setup();
        SwingUtilities.invokeLater(() -> {
            JFrame ventana = new JFrame("Saludo");
            ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = new JPanel();
            JTextField nombre = new JTextField(12);
            JButton boton = new JButton("Saludar");
            JLabel respuesta = new JLabel(" ");
            panel.add(new JLabel("¿Cómo te llamas?"));
            panel.add(nombre);
            panel.add(boton);
            panel.add(respuesta);

            boton.addActionListener(e -> {
                String texto = nombre.getText().trim();
                if (texto.isEmpty()) {
                    JOptionPane.showMessageDialog(ventana, "Escribe tu nombre primero");
                } else {
                    respuesta.setText("¡Hola, " + texto + "!");
                }
            });

            ventana.add(panel);
            ventana.setSize(520, 120);
            ventana.setLocationRelativeTo(null);
            ventana.setVisible(true);
        });
    }
}

La ventana de saludo después de escribir «Lucía» y pulsar Saludar: «¡Hola, Lucía!»

Si se pulsa sin escribir nada:

Una ventanita de aviso: «Escribe tu nombre primero», con un botón OK

Ventanitas con JOptionPane#

Para…CódigoDevuelve
AvisarJOptionPane.showMessageDialog(ventana, "Guardado");Nada
Preguntar sí o noJOptionPane.showConfirmDialog(ventana, "¿Borrar?")JOptionPane.YES_OPTION si dice que sí
Pedir un textoJOptionPane.showInputDialog(ventana, "¿Tu nombre?")El texto, o null si cancela
Java
int respuesta = JOptionPane.showConfirmDialog(ventana, "¿Seguro que quieres borrarlo?");
if (respuesta == JOptionPane.YES_OPTION) {
    // borrar
}

Otros eventos#

ComponenteCuándo saltaCómo se escucha
JButtonAl pulsarloaddActionListener
JTextFieldAl pulsar Enter dentroaddActionListener
JCheckBox, JRadioButtonAl marcar o desmarcaraddActionListener
JComboBoxAl elegir otra opciónaddActionListener
JSlider, JSpinnerAl cambiar el valoraddChangeListener(e -> { … })

Errores frecuentes#

Mensaje o síntomaQué significaCómo se arregla
local variables referenced from a lambda expression must be final or effectively finalIntentas cambiar dentro de la lambda una variable creada en el mainSácala fuera del main, como static int clics = 0;
Pulsas el botón y no pasa nadaNo tiene addActionListener, o se lo has puesto a otro botónComprueba que el addActionListener es del botón que pulsas
NumberFormatException al pulsarHaces Integer.parseInt de un campo vacío o con letrasComprueba antes que no está vacío, y avisa con un JOptionPane
Exception in thread "AWT-EventQueue-0" en la consola, y la ventana sigue abiertaHa fallado el código de un evento. AWT-EventQueue-0 es el hilo de SwingLee la línea de debajo: dice qué error ha sido y en qué línea