Soporte Java para el desarrollo de GUIs ... - fdi.ucm.es · de JDK 1.1) es mediante un mecanismo...

11
Interfaces gráficas de usuario (2): Swing Programación Orientada a Objetos Facultad de Informática Juan Pavón Mestras Dep. Sistemas Informáticos y Programación Universidad Complutense Madrid Juan Pavón Mestras Facultad de Informática UCM, 2004 Java Swing 2 Soporte Java para el desarrollo de GUIs Swing AWT Soporte nativo para GUIs Swing utiliza el modelo de eventos basado en delegación de AWT (definido a partir de Java 1.1) Juan Pavón Mestras Facultad de Informática UCM, 2004 Java Swing 3 Una aplicación Swing sencilla ! El comportamiento deseado para esta aplicación es: ! Cuando el usuario pulsa en el botón Dí Hola, en el campo de texto la aplicación ha de poner 'Hola' ! Cuando el usuario pulsa en el botón Dí Adios, en el campo de texto la aplicación ha de poner 'Adios' ! Cuando el usuario cierra la ventana, la aplicación ha de terminar Juan Pavón Mestras Facultad de Informática UCM, 2004 Java Swing 4 Una aplicación Swing sencilla ! El diseño de toda interfaz conlleva, a grandes rasgos, los siguientes pasos: ! Decidir la estructura de la interfaz Qué componentes gráficos se van a utilizar, y cómo se van a relacionar estos componentes) ! Decidir la disposición (layout) de los componentes Existen dos tipos de componentes: contenedores y componentes atómicos Los contenedores sirven para organizar los componentes contenidos en los mismos. Esta organización se denomina disposición (o layout) ! Decidir el comportamiento de la interfaz: gestión de eventos Algunos componentes son controles: permiten reaccionar ante eventos del usuario. El comportamiento se especifica programando las respuestas a dichos eventos. Normalmente, dichas respuestas supondrán invocar funcionalidades de la lógica de la aplicación Conviene mantener la interfaz y la lógica lo más independientes posibles (veremos patrones que permiten lograr esto)

Transcript of Soporte Java para el desarrollo de GUIs ... - fdi.ucm.es · de JDK 1.1) es mediante un mecanismo...

Interfaces gráficas de usuario (2): Swing

Programación Orientada a ObjetosFacultad de Informática

Juan Pavón MestrasDep. Sistemas Informáticos y Programación

Universidad Complutense Madrid

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 2

Soporte Java para el desarrollo de GUIs

Swing

AWT

Soporte nativo para GUIs

Swing utiliza el modelo de eventos basado en delegación de AWT (definido a partir de Java 1.1)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 3

Una aplicación Swing sencilla

! El comportamiento deseado para esta aplicación es:! Cuando el usuario pulsa en el botón Dí Hola, en el campo de

texto la aplicación ha de poner 'Hola'! Cuando el usuario pulsa en el botón Dí Adios, en el campo de

texto la aplicación ha de poner 'Adios'! Cuando el usuario cierra la ventana, la aplicación ha de

terminar

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 4

Una aplicación Swing sencilla

! El diseño de toda interfaz conlleva, a grandes rasgos, los siguientes pasos:! Decidir la estructura de la interfaz

• Qué componentes gráficos se van a utilizar, y cómo se van a relacionar estos componentes)

! Decidir la disposición (layout) de los componentes• Existen dos tipos de componentes: contenedores y componentes

atómicos• Los contenedores sirven para organizar los componentes

contenidos en los mismos. Esta organización se denomina disposición (o layout)

! Decidir el comportamiento de la interfaz: gestión de eventos• Algunos componentes son controles: permiten reaccionar ante

eventos del usuario. El comportamiento se especifica programando las respuestas a dichos eventos. Normalmente, dichas respuestas supondrán invocar funcionalidades de la lógica de la aplicación

• Conviene mantener la interfaz y la lógica lo más independientes posibles (veremos patrones que permiten lograr esto)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 5

Una aplicación Swing sencilla: estructura

Loro (JFrame)

Panel Principal (JSplitPane)

Botonera (JPanel)

Hola (JButon) Adios (JButon)

Eco (JTextField)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 6

Una aplicación Swing sencilla: estructura

import javax.swing.*;

public class Loro extends JFrame {private JTextField eco;

public Loro() {setTitle("Loro");

JComponent botonera = creaBotonera();JComponent eco = creaEco();// Crea panel con botonera y ecoJSplitPane panelPrincipal =

new JSplitPane(JSplitPane.VERTICAL_SPLIT,botonera,eco);// Añade el panel a la ventana principalgetContentPane().add(panelPrincipal);// Se 'redimensiona' toda la interfaz gráfica en la ventanapack();// Y hace visible la ventana, con sus componentessetVisible(true);

} // ...

import javax.swing.*;

public class Loro extends JFrame {private JTextField eco;

public Loro() {setTitle("Loro");

JComponent botonera = creaBotonera();JComponent eco = creaEco();// Crea panel con botonera y ecoJSplitPane panelPrincipal =

new JSplitPane(JSplitPane.VERTICAL_SPLIT,botonera,eco);// Añade el panel a la ventana principalgetContentPane().add(panelPrincipal);// Se 'redimensiona' toda la interfaz gráfica en la ventanapack();// Y hace visible la ventana, con sus componentessetVisible(true);

} // ...

Ordena la redimensión y la disposición de toda la jerarquía de componentes en la ventana

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 7

Una aplicación Swing sencilla: estructura

private JComponent creaBotonera() {JPanel botonera = new JPanel(); // Se crean los botones ...JButton hola = new JButton("Dí Hola");JButton adios = new JButton("Dí Adios");// .. y se añaden al panelbotonera.add(hola);botonera.add(adios); return botonera;

}

private JComponent creaEco() {// Se crea el campo de texto donde poner el eco

eco = new JTextField("Pulsa un botón");return eco;

} // ...

private JComponent creaBotonera() {JPanel botonera = new JPanel(); // Se crean los botones ...JButton hola = new JButton("Dí Hola");JButton adios = new JButton("Dí Adios");// .. y se añaden al panelbotonera.add(hola);botonera.add(adios); return botonera;

}

private JComponent creaEco() {// Se crea el campo de texto donde poner el eco

eco = new JTextField("Pulsa un botón");return eco;

} // ...

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 8

Una aplicación Swing sencilla: estructura

public static void main(String[] args) {Loro loro = new Loro();//... aquí termina la ejecución del 'hilo principal', // ... pero queda pendiente la ejecución del hilo de // ... tratamiento de eventos... A partir de ahora toda la // ... ejecución es gobernada por la interacción con el usuario.

}}

public static void main(String[] args) {Loro loro = new Loro();//... aquí termina la ejecución del 'hilo principal', // ... pero queda pendiente la ejecución del hilo de // ... tratamiento de eventos... A partir de ahora toda la // ... ejecución es gobernada por la interacción con el usuario.

}}

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 9

Una aplicación Swing sencilla: comportamiento

! Los controles señalizan eventos! Diferentes tipos de eventos, dependiendo de los controles! La forma de tratar eventos en Swing (y en AWT, a partir

de JDK 1.1) es mediante un mecanismo denominado delegación:! Por cada tipo de evento notificado por un control, el control

acepta un oyente de dicho evento (métodos addXXXListener)! Dicho oyente ha de implementar una interfaz adecuada

(XXXListener)! Cuando se produce un evento, el control invoca un método

apropiado del oyente. Es en este método donde se trata el evento

! Estas clases están declaradas en el paquete java.awt.event

import java.awt.event.*;

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 10

Una aplicación Swing sencilla: comportamiento

OyenteHolaactionPerformed

(ActionEvent ev)

OyenteAdiosactionPerformed

(ActionEvent ev)

OyenteVentanawindowClosing

(WindowEvent ev)

Escribir hola en el campo de texto

Escribir adios en el campo de texto

Terminar laejecución

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 11

Una aplicación Swing sencilla: comportamiento asociado a los botones

private JComponent creaBotonera() {JPanel botonera = new JPanel(); // Panel para contener los botones// Se crean los botones ...JButton hola = new JButton("Dí Hola");hola.addActionListener(

new ActionListener() {public void actionPerformed(ActionEvent ev) {

eco.setText("Hola!");}});

JButton adios = new JButton("Dí Adios");adios.addActionListener(

new ActionListener() {public void actionPerformed(ActionEvent ev) {

eco.setText("Adios!");}});

// .. y se añaden al panelbotonera.add(hola);botonera.add(adios); return botonera;

}

private JComponent creaBotonera() {JPanel botonera = new JPanel(); // Panel para contener los botones// Se crean los botones ...JButton hola = new JButton("Dí Hola");hola.addActionListener(

new ActionListener() {public void actionPerformed(ActionEvent ev) {

eco.setText("Hola!");}});

JButton adios = new JButton("Dí Adios");adios.addActionListener(

new ActionListener() {public void actionPerformed(ActionEvent ev) {

eco.setText("Adios!");}});

// .. y se añaden al panelbotonera.add(hola);botonera.add(adios); return botonera;

} Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 12

Una aplicación Swing sencilla: comportamiento asociado a la ventana principal

public Loro() {setTitle("Loro");

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent ev) {// Se termina la ejecución de la aplicación

System.exit(0);}

});// ...

public Loro() {setTitle("Loro");

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent ev) {// Se termina la ejecución de la aplicación

System.exit(0);}

});// ...

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 13

Funcionamiento de las aplicaciones con GUI en Java

! Java es, por diseño, un lenguaje multiproceso: en un programa Java pueden existir (y de hecho existen) simultáneamente múltiples hilos de ejecución (threads) concurrentes

! Uno de estos hilos es el hilo de tratamiento de eventos! En las aplicaciones con GUI, el hilo principal se limita a construir

la estructura de la GUI, a asociar los oyentes adecuados con loscontroles y, hecho esto, termina …

! … pero la aplicación en sí no termina, puesto que todavía queda, al menos, un hilo con vida: el de tratamiento de eventos! Este hilo se encarga de tratar automáticamente eventos rutinarios

(p.ej. redibujar una ventana cuando ésta pasa a primer plano, o cuando se quita una ventana que la ocultaba parcialmente, actualizar la presentación como resultado de cambios ordenados por la aplicación, etc.)

! … y también se encarga de tratar los eventos de usuario, invocando a los oyentes previamente registrados

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 14

Funcionamiento de las aplicaciones con GUI en Java

! Consecuencias del funcionamiento:! La aplicación avanza guiada por los eventos del usuario! Cuando, desde el código de la aplicación, se realizan cambios sobre

la interfaz (p.ej. cambiar el texto de una etiqueta, dibujar algo, limpiar un cuadro de texto, etc.) tales cambios no son inmediatos, sino que se encolan (en estructuras internas del frameworkAWT/Swing) para ser procesados por el hilo de tratamiento de eventos una vez que termine la ejecución del código del oyente que ha provocado los cambios

• La ejecución de métodos que cambian la presentación de componentes no debe interpretarse como ejecuciones, sino como promesas de ejecuciones (que se realizarán cuando sea posible)

! El tratamiento de los eventos debe ser rápido • La ejecución de los oyentes se lleva a cabo en el hilo de tratamiento de

eventos: si tal ejecución tarda mucho, o se bloquea, bloquea a dicho hilo, que no puede tratar el resto de eventos rutinarios, por lo que la aplicación en sí se bloquea, y no responderá

• Si un tratamiento de un evento necesita mucho tiempo para ser realizado, una solución puede ser crear otro hilo que lo lleve a cabo (no es sencillo porque aparecen los problemas de sincronización de hilos)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 15

JFrame

! Toda aplicación Swing tiene, al menos, un contenedor raíz (una ventana)

! La clase JFrame proporciona ventanas al uso (aunque puede haber otro tipo de ventanas)

! A su vez, JFrame incluye una serie de elementos:• Los contenidos se

añaden en el panel de contenidos (contentpane) accesible a través del método getContentPane (por defecto, un objeto de tipo Jpane, aunque puede cambiarse con setContentPane).

• La barra de menúpuede fijarse con setJMenuBar

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 16

JFrame

import java.awt.Color;import java.awt.Dimension;import java.awt.BorderLayout;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JMenuBar;

public class TopLevelDemo {public static void main(String s[]) {

JFrame frame = new JFrame("TopLevelDemo");

frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {

System.exit(0);}

});

//...

import java.awt.Color;import java.awt.Dimension;import java.awt.BorderLayout;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JMenuBar;

public class TopLevelDemo {public static void main(String s[]) {

JFrame frame = new JFrame("TopLevelDemo");

frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {

System.exit(0);}

});

//...

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 17

JFrame

JLabel yellowLabel = new JLabel("");yellowLabel.setOpaque(true);yellowLabel.setBackground(Color.yellow);yellowLabel.setPreferredSize(new Dimension(200, 180));

JMenuBar cyanMenuBar = new JMenuBar();cyanMenuBar.setOpaque(true);cyanMenuBar.setBackground(Color.cyan);cyanMenuBar.setPreferredSize(new Dimension(200, 20));

frame.setJMenuBar(cyanMenuBar);frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);

frame.pack();frame.setVisible(true);

}

JLabel yellowLabel = new JLabel("");yellowLabel.setOpaque(true);yellowLabel.setBackground(Color.yellow);yellowLabel.setPreferredSize(new Dimension(200, 180));

JMenuBar cyanMenuBar = new JMenuBar();cyanMenuBar.setOpaque(true);cyanMenuBar.setBackground(Color.cyan);cyanMenuBar.setPreferredSize(new Dimension(200, 20));

frame.setJMenuBar(cyanMenuBar);frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);

frame.pack();frame.setVisible(true);

}Para añadir componentes a un JFrame se añaden componentes a su panel de contenidos

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 18

JSplitPane y Box: Haciendo layout fácil en Swing

! El control de la disposición en Swing (y en AWT) se delega en objetos especiales, denominados gestores de disposición (layout managers)! En AWT vimos diversos tipos de gestores de disposición, que ofrecen

mecanismos más o menos sofisticados para organizar los contenidos en un contenedor

! Swing ofrece además dos componentes que facilitan la realización del layout: ! JSplitPane permite dividir una región en dos subregiones, y asignar

a cada una de ellas un peso determinado (que dictará la forma en cómo se repartirá el espacio extra en cada subregión cuando el contenedor crezca)

! Box permite organizar vertical u horizontalmente componentes, asícomo especificar espaciado fijo entre ellos, y componentes de glue(componentes invisibles que crecen cuando la caja crece, dejando el resto de los componentes adecuadamente situados)

• Combinando JSplitPane y Box es posible especificar layouts complicados, sin necesidad de vérselas con las complejidades de más bajo nivel de los layout managers

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 19

JSplitPane y Box: Haciendo layout fácil en Swing

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 20

JSplitPane y Box: Haciendo layout fácil en Swing

peso=1

peso=0

0 1

1 0

glue glue

JSplitPane

JSplitPane

JSplitPane

Box

Box

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 21

JSplitPane y Box: Haciendo layout fácil en Swing

public class LayoutDemo {public static void main(String s[]) {

JButton b1 = new JButton("Botón 1");JButton b2 = new JButton("Botón 2");JButton b3 = new JButton("Botón 3");

Box cajaBotones = Box.createVerticalBox();cajaBotones.add(b1);cajaBotones.add(b2);cajaBotones.add(b3);cajaBotones.add(Box.createVerticalGlue());

public class LayoutDemo {public static void main(String s[]) {

JButton b1 = new JButton("Botón 1");JButton b2 = new JButton("Botón 2");JButton b3 = new JButton("Botón 3");

Box cajaBotones = Box.createVerticalBox();cajaBotones.add(b1);cajaBotones.add(b2);cajaBotones.add(b3);cajaBotones.add(Box.createVerticalGlue());

Las cajas se crean con los métodos estáticos createHorizontalBox y createVerticalBox de Box.

El glue se crea con los métodos estáticos de Box createVerticalBox y createHorizontalBox. Con createHorizontalStrut y createVerticalStrut puede introducirse espacios fijos entre los componentes

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 22

JSplitPane y Box: Haciendo layout fácil en Swing

JLabel e1 = new JLabel("Etiqueta 1");JLabel e2 = new JLabel("Etiqueta 2"); Box cajaEtiquetas = Box.createVerticalBox();cajaEtiquetas.add(e1);cajaEtiquetas.add(e2);cajaEtiquetas.add(Box.createVerticalGlue());

JSplitPane panelSecundario1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,

new JPanel(),cajaEtiquetas);

panelSecundario1.setDividerSize(1); panelSecundario1.setResizeWeight(1);

JSplitPane panelSecundario2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,

cajaBotones,panelSecundario1);

panelSecundario2.setDividerSize(1);

JLabel e1 = new JLabel("Etiqueta 1");JLabel e2 = new JLabel("Etiqueta 2"); Box cajaEtiquetas = Box.createVerticalBox();cajaEtiquetas.add(e1);cajaEtiquetas.add(e2);cajaEtiquetas.add(Box.createVerticalGlue());

JSplitPane panelSecundario1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,

new JPanel(),cajaEtiquetas);

panelSecundario1.setDividerSize(1); panelSecundario1.setResizeWeight(1);

JSplitPane panelSecundario2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,

cajaBotones,panelSecundario1);

panelSecundario2.setDividerSize(1);

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 23

JSplitPane y Box: Haciendo layout fácil en Swing

JSplitPane panelPrincipal = new JSplitPane(JSplitPane.VERTICAL_SPLIT,

panelSecundario2,new JPanel());

panelPrincipal.setDividerSize(1); panelPrincipal.setResizeWeight(1);

JFrame frame = new JFrame("LayoutDemo");

frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {

System.exit(0);}

});

frame.setContentPane(panelPrincipal);frame.pack();frame.setVisible(true);

}

}

JSplitPane panelPrincipal = new JSplitPane(JSplitPane.VERTICAL_SPLIT,

panelSecundario2,new JPanel());

panelPrincipal.setDividerSize(1); panelPrincipal.setResizeWeight(1);

JFrame frame = new JFrame("LayoutDemo");

frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {

System.exit(0);}

});

frame.setContentPane(panelPrincipal);frame.pack();frame.setVisible(true);

}

}

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 24

Botones

! Los botones, junto con los menús, son los controles más típicos en una GUI

! Existen diferentes tipos (especializaciones de AbstractButton)! JButton: Botón aislado. Puede pulsarse, pero su estado no cambia! JToggleButton : Botón seleccionable. Cuando se pulsa el botón, su

estado pasa a seleccionado, hasta que se pulsa de nuevo (entonces se deselecciona)

• isSelected() permite chequear su estado

! JCheckBox : Especialización de JToggleButton que implementa una casilla de verificación. Botón con estado interno, que cambia de apariencia de forma adecuada según si está o no está seleccionado

! JRadioButton: Especialización de JToggleButton que tiene sentido dentro de un mismo grupo de botones (ButtonGroup) que controla que sólamente uno de ellos está seleccionado

• Nota: ButtonGroup es únicamente un controlador, no un componente)

! El evento semántico más común anunciado por los botones es ActionEvent

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 25

Botones

Box caja = Box.createHorizontalBox();caja.add(new JButton("Un botón normal"));caja.add(new JToggleButton("Un botón seleccionable"));caja.add(new JToggleButton("Otro botón seleccionable",true));caja.add(new JCheckBox("Cine"));caja.add(new JCheckBox("Teatro"));caja.add(new JCheckBox("Música"));ButtonGroup grupo = new ButtonGroup();JRadioButton r1 = new JRadioButton("Hombre");JRadioButton r2 = new JRadioButton("Mujer");JRadioButton r3 = new JRadioButton("Asexuado");

Box caja = Box.createHorizontalBox();caja.add(new JButton("Un botón normal"));caja.add(new JToggleButton("Un botón seleccionable"));caja.add(new JToggleButton("Otro botón seleccionable",true));caja.add(new JCheckBox("Cine"));caja.add(new JCheckBox("Teatro"));caja.add(new JCheckBox("Música"));ButtonGroup grupo = new ButtonGroup();JRadioButton r1 = new JRadioButton("Hombre");JRadioButton r2 = new JRadioButton("Mujer");JRadioButton r3 = new JRadioButton("Asexuado");

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 26

Botones

grupo.add(r1);grupo.add(r2);grupo.add(r3);caja.add(r1);caja.add(r2);caja.add(r3);

grupo.add(r1);grupo.add(r2);grupo.add(r3);caja.add(r1);caja.add(r2);caja.add(r3);

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 27

Menús

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 28

Menús

• La creación de una barra de menús básica supone:• Crear un objeto de tipo JMenuBar.• Para cada entrada, crear un objeto de tipo JMenu.• Incluir objetos de tipo JMenuItem en el menú. Esto puede incluir

menús anidados.• Asociar a los items acciones apropiadas (notifican eventos

semánticos de tipo ActionEvent, ya que, en realidad, especializan a AbstractButton).

• Con setJMenuBar es posible añadir una barra de menús a una ventana (JFrame).

• Importante: En una GUI, muchas veces existen controles ligados a la misma acción (eg. un botón que hace lo mismo que un itemde un menú). En este caso ambos controles pueden compartir el mismo oyente (y es aconsejable hacerlo así).

• Más importante aún: El diseño de una barra de menús debe ser consistente (poner opciones semánticamente relacionadas juntas).

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 29

Menús

public class PruebaMenu extends JFrame {public void ejecuta() {

JMenuBar barra = new JMenuBar();JMenu menu1 = new JMenu("Menú 1");menu1.add(new JMenuItem("Una opción de texto"));menu1.add(new JSeparator());ButtonGroup grupo = new ButtonGroup();JRadioButtonMenuItem r1 = new JRadioButtonMenuItem("Opción 1");JRadioButtonMenuItem r2 = new JRadioButtonMenuItem("Opción 2");grupo.add(r1);grupo.add(r2);menu1.add(r1);menu1.add(r2);menu1.add(new JSeparator());menu1.add(new JCheckBoxMenuItem("Selección 1",true));menu1.add(new JCheckBoxMenuItem("Selección 2"));

public class PruebaMenu extends JFrame {public void ejecuta() {

JMenuBar barra = new JMenuBar();JMenu menu1 = new JMenu("Menú 1");menu1.add(new JMenuItem("Una opción de texto"));menu1.add(new JSeparator());ButtonGroup grupo = new ButtonGroup();JRadioButtonMenuItem r1 = new JRadioButtonMenuItem("Opción 1");JRadioButtonMenuItem r2 = new JRadioButtonMenuItem("Opción 2");grupo.add(r1);grupo.add(r2);menu1.add(r1);menu1.add(r2);menu1.add(new JSeparator());menu1.add(new JCheckBoxMenuItem("Selección 1",true));menu1.add(new JCheckBoxMenuItem("Selección 2"));

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 30

Menús

JMenu menu11 = new JMenu("Submenú");menu11.add(new JMenuItem("Opción 1"));menu11.add(new JMenuItem("Opción 2")); menu1.add(menu11);barra.add(menu1);barra.add(new JMenu("Menú 2"));setJMenuBar(barra);pack();setVisible(true);

}public static void main(String[] args) {

new PruebaMenu().ejecuta();}}

JMenu menu11 = new JMenu("Submenú");menu11.add(new JMenuItem("Opción 1"));menu11.add(new JMenuItem("Opción 2")); menu1.add(menu11);barra.add(menu1);barra.add(new JMenu("Menú 2"));setJMenuBar(barra);pack();setVisible(true);

}public static void main(String[] args) {

new PruebaMenu().ejecuta();}}

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 31

Interacción modal

! Muchas veces surge la necesidad de lanzar, esporádicamente, ventanas secundarias para indicar algún hecho, o pedir algún dato al usuario: cuadros de diálogo

! La mayor parte de estas interacciones suelen ser modales (es decir, la ejecución del programa se interrumpe hasta que el usuario cierra el cuadro de diálogo)

! Swing ofrece la posibilidad de crear diálogos a medida…! …pero (afortunadamente), también ofrece la posibilidad de

crear/configurar diálogos prefabricados que son útiles en muchas situaciones

! ¿Cómo funciona la interacción modal?: Swing lanza un hilo adicional para manejar dichas interacciones (y el resto de los eventos rutinarios). El hilo de tratamiento de eventos se sincroniza (espera) la finalización de dicho hilo de interacción modal

! Importante: Un abuso de la interacción modal conduce a interfaces poco usables (en el límite, a interacciones tipo consola)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 32

Interacción modal

! La clase JOptionPane ofrece un conjunto de métodos estáticos que lanzan diferentes tipos de diálogos (estos métodos están sobrecargados para poder crear diálogos con diferentes grados de fineza):! showMessageDialog : Muestra un diálogo de mensaje! showConfirmDialog : Muestra un diálogo de confirmación.

Permite determinar la opción elegida por el usuario de forma modal (yes, no, cancel)

! showInputDialog: Muestra un diálogo en el que se solicita, de forma modal, una entrada al usuario. Dependiendo de la versión de método utilizada, el usuario puede teclear la entrada, o bien seleccionarla de una lista de entradas disponibles

! showOptionDialog: Muestra un diálogo que puede personalizarse con botones (en general, con componentes) a medida

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 33

Interacción modal

JOptionPane.showMessageDialog(this, // La ventana padre."Error deconocido!: Lo llevas muy mal!", //El mensaje."Error", // El título de la ventana de diálogo.JOptionPane.ERROR_MESSAGE // El tipo de mensaje

);

JOptionPane.showMessageDialog(this, // La ventana padre."Error deconocido!: Lo llevas muy mal!", //El mensaje."Error", // El título de la ventana de diálogo.JOptionPane.ERROR_MESSAGE // El tipo de mensaje

);

JOptionPane.showMessageDialog(this,"Te informo de que lo llevas fatal", "Info",JOptionPane.INFORMATION_MESSAGE);JOptionPane.showMessageDialog(this,"Te informo de que lo llevas fatal", "Info",JOptionPane.INFORMATION_MESSAGE);

JOptionPane.showMessageDialog(this,"Te aviso de que lo llevas fatal", "Aviso",JOptionPane.WARNING_MESSAGE);

JOptionPane.showMessageDialog(this,"Te aviso de que lo llevas fatal", "Aviso",JOptionPane.WARNING_MESSAGE);

JOptionPane.showMessageDialog(this, Este mensaje es para tí, majete!", "Mensaje",

JOptionPane.PLAIN_MESSAGE);JOptionPane.showMessageDialog(this,

Este mensaje es para tí, majete!", "Mensaje", JOptionPane.PLAIN_MESSAGE);

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 34

Interacción modal

int seleccionada = JOptionPane.showConfirmDialog(this, "Lo aceptas?", "Aviso",JOptionPane.YES_NO_OPTION, // Configuración del mensajeJOptionPane.INFORMATION_MESSAGE);

switch(seleccionada) {case JOptionPane.YES_OPTION: ... // tratar SIcase JOptionPane.NO_OPTION: .. // tratar NOcase JOptionPane.CLOSED_OPTION: .. // tratar ventana cerradadefault: ... // esta opción nunca debería alcanzarse

}

int seleccionada = JOptionPane.showConfirmDialog(this, "Lo aceptas?", "Aviso",JOptionPane.YES_NO_OPTION, // Configuración del mensajeJOptionPane.INFORMATION_MESSAGE);

switch(seleccionada) {case JOptionPane.YES_OPTION: ... // tratar SIcase JOptionPane.NO_OPTION: .. // tratar NOcase JOptionPane.CLOSED_OPTION: .. // tratar ventana cerradadefault: ... // esta opción nunca debería alcanzarse

}

int seleccionada = JOptionPane.showConfirmDialog(this,

"Lo aceptas?","Aviso",JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);

... // los posibles valores devueltos son los anteriores y

... // JOptionPane.CANCEL_OPTION

int seleccionada = JOptionPane.showConfirmDialog(this,

"Lo aceptas?","Aviso",JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);

... // los posibles valores devueltos son los anteriores y

... // JOptionPane.CANCEL_OPTION

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 35

Interacción modal

String[] colores = {"rojo","negro","amarillo","azul","majenta"};

Object opcion = JOptionPane.showInputDialog(this,"Selecciona un color, resalao!", "Petición",JOptionPane.QUESTION_MESSAGE, null, //icono. no hay.colores, // opciones. Se le podría pasar un array de

// objetos arbitrarioscolores[0] //opción inicial

);// ...procesar opción...

String[] colores = {"rojo","negro","amarillo","azul","majenta"};

Object opcion = JOptionPane.showInputDialog(this,"Selecciona un color, resalao!", "Petición",JOptionPane.QUESTION_MESSAGE, null, //icono. no hay.colores, // opciones. Se le podría pasar un array de

// objetos arbitrarioscolores[0] //opción inicial

);// ...procesar opción...

String nombre = JOptionPane.showInputDialog(this,"Cómo te llamas, majete?","Petición", JOptionPane.QUESTION_MESSAGE

);// ... procesar entrada

String nombre = JOptionPane.showInputDialog(this,"Cómo te llamas, majete?","Petición", JOptionPane.QUESTION_MESSAGE

);// ... procesar entrada

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 36

Interacción modal

String[] sexo = {"hetero","homo","bi","auto"};int opcion =

JOptionPane.showOptionDialog(this, "Y tú qué eres?", "Petición", -1, // opciones->quedan fijadas por el array de opcionesJOptionPane.QUESTION_MESSAGE, null,//icono. no hay.sexo, // array de opcionessexo[0] // opcion inicial

);... // procesamiento de la opcion ...

String[] sexo = {"hetero","homo","bi","auto"};int opcion =

JOptionPane.showOptionDialog(this, "Y tú qué eres?", "Petición", -1, // opciones->quedan fijadas por el array de opcionesJOptionPane.QUESTION_MESSAGE, null,//icono. no hay.sexo, // array de opcionessexo[0] // opcion inicial

);... // procesamiento de la opcion ...

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 37

Interacción modal: selección de archivos

! Los diálogos de tipo JFileChooser facilitan esta tarea! La forma habitual de trabajar con JFileChooser es:

! Crear una instancia de JFileChooser.! Configurar dicha instancia de forma adecuada. Dicha configuración,

normalmente, se limita a poner filtros sobre lo que puede seleccionarse con el selector de ficheros, así como a fijar la carpeta actual (con setCurrentDirectory):

• Con setFileSelectionMode.• Con setFileFilter : Aquí debe añadirse una instancia de una subclase

adecuada de FileFilter.

! Mostrar un selector de ficheros utilizando alguno de los siguientes métodos:

• showDialog : Selector a medida.• showOpenDialog : Selector para abrir un fichero.• showSaveDialog : Selector para salvar un fichero.

! La interacción es modal: los métodos show devuelven el estado de la operación. Si todo ha ido bien, el método getSelectedFile devuelve un objeto de tipo File, que debe ser tratado de forma adecuada

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 38

Interacción modal: selección de archivos

! Creación y configuración de un selectorselector = new JFileChooser(); selector.setFileFilter(new FiltroTexto()); selector.setFileSelectionMode(JFileChooser.FILES_ONLY);selector.setCurrentDirectory(new File(System.getProperty("user.dir")));

! Un filtro de ficheros

class FiltroTexto extends FileFilter {public boolean accept(File f) {

String nombre = f.getName(); return nombre.substring(Math.max(nombre.length()-4,0)).equals(".txt");

}public String getDescription() {

return "Ficheros de tipo texto";}

}

class FiltroTexto extends FileFilter {public boolean accept(File f) {

String nombre = f.getName(); return nombre.substring(Math.max(nombre.length()-4,0)).equals(".txt");

}public String getDescription() {

return "Ficheros de tipo texto";}

}

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 39

Interacción modal: selección de archivos

! El mismo selector permite crear diferentes diálogos de selección

selector.showOpenDialog(this)

selector.showSaveDialog(this)

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 40

Interacción modal: selección de archivos

if ( selector.showOpenDialog(this) == JFileChooser.APPROVE_OPTION ) {

File f = selector.getSelectedFile();// Hacer lo que sea pertinente con el fichero ...

}

Uso habitual de un diálogo creado a través de un FileChooser

Juan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 41

Otros contenedores Swing

! JPanel. Un contenedor intermedio genérico! Se utiliza para poner otros componentes ! FlowLayout por defecto (los componentes se colocan uno

detrás de otro)

! JScrollPane. Un panel con barras de scroll! JTabbedPane. Un panel con diferentes vistas

! JToolBar. Una barra de herramientas! Puede cambiarse de situación por los bordes de su

contenedor e incluso llevarse fuera! Las herramientas suelen ser (aunque no obligatoriamente)

botonesJuan Pavón MestrasFacultad de Informática UCM, 2004 Java Swing 42

Otros componentes atómicos Swing

! JLabel. Etiquetas! JTextField. Entrada de una línea de texto! JTextArea. Entradas de varias líneas de texto! JSlider. Una barra de selección en una escala! JList. Una lista de elementos seleccionables! JComboBox. Una lista de elementos desplegable! JPopupMenu. Un menú desplegable