Mostrar imágenes al pulsar botones en una ventana JFrame que implementa la interfaz ActionListener, detectar la pulsación del botón como un evento de acción (ActionEvent) y llamar a la acción prevista con el método actionPerformed,en Java
Introducción: responder a las acciones del usuario
Las aplicaciones han de responder a las acciones que realiza el usuario, por ejemplo: cerrar la ventana al pulsar un botón. Es necesario poder detectar las acciones de usuario y convertirlas en acciones de programa. Java dispone de varias formas de implementar este funcionamiento. En este ejercicio se mostrarán algunas de ellas. Todas se basan en el uso de Interfaces. Las Interfaces son clases “prefabricadas” con propósitos definidos
Cada Interface contiene declaraciones de métodos (nombre del método, lista de argumentos y tipo de retorno) pero estos métodos no están implementados (carecen de cuerpo) y deben ser desarrollados. Todos los métodos de las Interfaces son public. Las Interfaces también pueden declarar constantes (public final static).
En Java no existe la herencia múltiple como tal: una clase no puede heredar (extends) de más de una clase. Pero una clase puede implementar más de una Interface, ésta es una manera de tener herencia múltiple. En la clase que implementa una Interface han de ser sobrescritos (override) todos los métodos declarados en la Interface.
Respecto a la interfaz ActionListener:
- ActionListener es una Interface del grupo de los Listeners
- ActionListener tiene un sólo método: void actionPerformed(ActionEvent e)
- ActionListener se usa para detectar y manejar eventos de acción (ActionEvent) que son los que tienen lugar cuando se produce una acción sobre un elemento del programa.
Un evento ActionEvent se produce:
- al pulsar un botón (Button)
- al hacer doble clic en un elemento de lista (List)
- al pulsar INTRO en una caja de texto (TextField)
- al elegir un menú (MenuItem).
Los distintos elementos del programa (botones, etc.) están vigilados por Listeners que detectan las acciones que tienen lugar sobre el elemento supervisado. De manera que cuando el usuario pulsa un botón:
- el botón sobre el que se produce una acción y genera un evento (event source, este dato se puede obtener con el método getSource) ha de estar previamente registrado con algún objeto que gestione el evento (ActionListener en este caso) mediante el método:
Button.addActionListener(this) // o tambien Button.addActionListener(ActionListener nombre_de_actionListener)
el botón genera un ActionEvent (clase del paquete java.awt.event)
ActionEvent invoca al método actionPerformed que realiza las acciones programadas
si la clase implementa ActionListener, ha de ser sobrescrito (override) el método public void actionPerformed(ActionEvent e).
Código principal del programa
Hay que importar estos paquetes e instanciar la clase principal:
import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.awt.Color; import java.net.URL; // CLASE PRINCIPAL public class Botones_fotos extends JFrame implements ActionListener
Un objeto JPanel derivado de la clase Container va a contener el resto de objetos de la ventana. Container es un componente genérico AWT que puede contener otros componentes AWT. Swing proporciona 2 contenedores de primer nivel: JFrame y JDialog, cada uno de ellos contiene un panel principal o raíz (JRootPane) con varios elementos:
- panel de contenido (contentPane): los componentes visibles del contenedor de primer nivel, excepto barra de menú; por defecto tienen BorderLayout()
- barra de menú (menuBar): es opcional, fuera de contentPane
- panel de cristal (glassPane): por encima de menuBar y contentPane, oculto por defecto, se encarga de interceptar acciones del usuario para JRootPane.
No se pueden agregar elementos directamente a JRootPane. Hay que agregarlos al contentPane de rootPane con el método getContentPane():
rootPane.add(elemento); // NO rootPane.getContentPane().add(elemento); // SI
Para agregar elementos a un Frame:
Frame.getContentPane().add(elemento);
El método getContentPane() devuelve un objeto Container, no un objeto JComponent, por ello es conveniente crear un componente personalizado para usar como contentPane. Para usar un componente como contentPane hay que:
// crear un panel y agregar componentes JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(elegirBorde); panel.add(unComponente, BorderLayout.CENTER); panel.add(otroComponente, BorderLayout.PAGE_END); // hacer que panel sea contentPane de un contenedor de nivel superior panel.setOpaque(true); topLevelContainer.setContentPane(panel);
Se crean los diferentes paneles contenedores.
// panel1 es el contenedor de todos los elementos de la ventana private JPanel panel1 = new JPanel(new BorderLayout()); // panel para la etiqueta rutaLabel y pBotones private JPanel panelSup = new JPanel(new GridLayout(2,0)); // panel que agrupa los botones superiores private JPanel pBotones = new JPanel(new GridLayout(1,0)); // panel para la etiqueta rutaLabel private JPanel pLabel = new JPanel(); // panel para los botones inferiores private JPanel pBotones2 = new JPanel(new GridLayout(1,0));
Se crean botones y etiquetas y se configura el tipo de letra.
// Array de botones con el nombre de la imagen en cada uno de ellos private JButton[] strBotones = {new JButton("Pelosas"), new JButton("Tux"), new JButton("Ctr"), new JButton("Gato"), new JButton("Milu")}; // fuente para botones y etiqueta Font letra = new Font("Verdana", Font.BOLD, 12); // etiqueta para mostrar las imagenes JPG private JLabel imgLabel = new JLabel(); // etiqueta para mostrar la ruta a los archivos private JLabel rutaLabel = new JLabel(); // botones de la parte inferior private JButton Codigo = new JButton("Archivo fuente java"); private JButton Salir = new JButton("Salir del programa"); // Cadena para usar en setLabelPicture(), coincide con el nombre de la imagen JPG y con el texto del boton private String nombreFoto;
Métodos de entrada al programa y creación de la interfaz gráfica.
// METODO DE ENTRADA AL PROGRAMA public static void main(String[] args) { // instancia de la clase principal, hereda de JFrame new Botones_fotos(); } // METODO CONSTRUCTOR QUE CREA Y MUESTRA LA INTERFAZ public Botones_fotos() { // la variable especial this se usa en metodos de instancia para hacer referencia // al objeto que contiene al metodo, aqui equivale a JFrame // lo que pasa al cerrar la ventana: salir del programa this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
Mostrar los botones, configurar la fuente y enlazarlos con addActionListener.
// mostrar los botones inferiores, configurar la fuente y enlazarlos con addActionListener Codigo.setActionCommand ("Codigo"); Codigo.addActionListener(this); Salir.setActionCommand ("Salir"); Salir.addActionListener(this); // mostrar los botones superiores, configurar la fuente y enlazarlos con addActionListener for(int i = 0; i < strBotones.length; i++) { pBotones.add(strBotones[i]); strBotones[i].setFont(letra); strBotones[i].addActionListener(this); }
El aspecto de las etiquetas también se puede configurar.
// configurar la etiqueta imgLabel imgLabel.setHorizontalAlignment(JLabel.CENTER); imgLabel.setOpaque(true); imgLabel.setBackground(Color.gray);
Rellenar los paneles contenedores.
// colocar elementos en los paneles, panel1 es contentPane del JFrame panel1.setOpaque(true); this.setContentPane(panel1); panel1.add(panelSup, BorderLayout.NORTH); panelSup.add(pBotones); panelSup.add(pLabel); panel1.add(imgLabel, BorderLayout.CENTER); panel1.add(pBotones2, BorderLayout.SOUTH); pBotones2.add(Codigo); pBotones2.add(Salir); pLabel.add(rutaLabel); // mostrar la ventana this.setTitle("Botones y Fotos"); this.setSize(new Dimension(720,582)); // ajustar el marco a sus contenedores //this.pack(); // centrar el formulario en la pantalla this.setLocationRelativeTo(null); this.setResizable(false); this.setVisible(true);
Método setLabelPicture. Carga la imagen cuyo nombre coincide con el texto del botón y muestra la ruta quitando los caracteres %20 que Java coloca en lugar de los espacios en blanco.
// MOSTRAR LA IMAGEN EN LA ETIQUETA private void setLabelPicture() { imgLabel.setText(""); // texto del boton con extension jpg = nombre del archivo JPG String nombreCompleto = "/img/" + nombreFoto + ".jpg"; // buscar el archivo JPG dentro del archivo JAR, // para poder usar la clase URL hay que importar el paquete java.net.URL URL url = this.getClass().getResource( nombreCompleto ); String urlS = url.toString(); // Java coloca los caracteres %20 en lugar de los espacios en blanco de la ruta, se quitan para mejorar su aspecto urlS = urlS.replace("%20"," "); // informar de la ruta a la imagen seleccionada, para ver la presentacion de URL rutaLabel.setText("" + urlS); // informar tambien con cuadro de mensaje //JOptionPane.showMessageDialog(null, "Ruta a la imagen seleccionada: " + urlS, "URL de la imagen", JOptionPane.PLAIN_MESSAGE); // JLabel.setIcon(Icon) define el icono mostrado en la etiqueta, centrado en horizontal y en vertical imgLabel.setIcon(new ImageIcon(url)); }
Si se desea que el programa arranque con una de las imágenes visible, se llama al método durante la carga del programa, Si se prefiere que arranque en blanco, se comentan estas 2 líneas.
// llamar al metodo setLabelPicture() si se prefiere que el programa arranque ya con imagen cargada // comentar las 2 lineas si se prefiere que arranque vacio sin imagen cargada nombreFoto = "Milu"; // imagen que aparece al arrancar el programa setLabelPicture();
Al pulsar en el botón Codigo se muestra la segunda ventana en la que se ha añadido un objeto JEditorPane al que se le pasa el texto del archivo .html con el código Java de la ventana principal, con la sintaxis coloreada. Al pulsar el botón Salir se sale del programa. A l pulsar cualquier otro botón se desencadena el evento que lleva al método que muestra las fotos.
// LO QUE SUCEDE AL PULSAR UNO DE LOS BOTONES public void actionPerformed(ActionEvent e) { // si se ha pulsado en el boton con el texto Archivo fuente Java // (si ActionCommand es Codigo) mostrar la ventana con codigo Java if ("Codigo".equals(e.getActionCommand())) { // mostrar un objeto Botones_fotos_code, es el marco para la segunda ventana Botones_fotos_code codeForm = new Botones_fotos_code(); //codeForm.show(); } --> obsoleto codeForm.setVisible(true); } // si se ha pulsado en el boton Salir (si ActionCommand es Salir) else if ("Salir".equals(e.getActionCommand())) { System.exit(0); } // si se ha pulsado en cualquier otro boton else { // e.getActionCommand() equivale al texto del boton // para pasarle al metodo e.getActionCommand() el nombre de la imagen // que es el texto del boton on extension jpg nombreFoto = e.getActionCommand(); setLabelPicture(); } }
Crear el archivo JAR
Es necesario incorporar al archivo todos los elementos: las clases como se hace habitualmente, las imágenes de la carpeta img y el archivo .html de la carpeta code.
Código fuente de ambas clases: java1 y java2.
Programa completo en zip.