Interfaces gráficas de usuario (2): Swing Soporte Java para el

Anuncio
Soporte Java para el desarrollo de GUIs
Interfaces gráficas de usuario (2): Swing
Swing
Programación Orientada a Objetos
Facultad de Informática
AWT
Soporte nativo para GUIs
Juan Pavón Mestras
Dep. Sistemas Informáticos y Programación
Universidad Complutense Madrid
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Una aplicación Swing sencilla
!
!
!
Cuando el usuario
texto la aplicación
Cuando el usuario
texto la aplicación
Cuando el usuario
terminar
Java Swing
2
Una aplicación Swing sencilla
El comportamiento deseado para esta aplicación es:
!
Swing utiliza el
modelo de
eventos basado
en delegación de
AWT (definido a
partir de Java 1.1)
!
pulsa en el botón Dí Hola, en el campo de
ha de poner 'Hola'
pulsa en el botón Dí Adios, en el campo de
ha de poner 'Adios'
cierra la ventana, la aplicación ha de
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 Mestras
Facultad de Informática UCM, 2004
Java Swing
3
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
4
Una aplicación Swing sencilla: estructura
Una aplicación Swing sencilla: estructura
import
importjavax.swing.*;
javax.swing.*;
Loro (JFrame)
public
publicclass
classLoro
Loroextends
extendsJFrame
JFrame{{
private
privateJTextField
JTextFieldeco;
eco;
public
publicLoro()
Loro(){{
setTitle("Loro");
setTitle("Loro");
Panel Principal
(JSplitPane)
Botonera (JPanel)
Hola (JButon)
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Ordena la
redimensión y
la disposición
de toda la
jerarquía de
componentes
en la ventana
Eco (JTextField)
Adios (JButon)
Java Swing
5
Una aplicación Swing sencilla: estructura
Facultad de Informática UCM, 2004
Java Swing
6
Una aplicación Swing sencilla: estructura
private
privateJComponent
JComponentcreaBotonera()
creaBotonera(){{
JPanel
JPanelbotonera
botonera==new
newJPanel();
JPanel();
////Se
Secrean
creanlos
losbotones
botones......
JButton
JButtonhola
hola==new
newJButton("Dí
JButton("DíHola");
Hola");
JButton
JButtonadios
adios==new
newJButton("Dí
JButton("DíAdios");
Adios");
////....yyseseañaden
añadenalalpanel
panel
botonera.add(hola);
botonera.add(hola);
botonera.add(adios);
botonera.add(adios);
return
returnbotonera;
botonera;
}}
////......
}}
////......
Juan Pavón Mestras
JComponent
JComponentbotonera
botonera==creaBotonera();
creaBotonera();
JComponent
JComponenteco
eco==creaEco();
creaEco();
////Crea
Creapanel
panelcon
conbotonera
botonerayyeco
eco
JSplitPane
JSplitPanepanelPrincipal
panelPrincipal==
new
JSplitPane(JSplitPane.VERTICAL_SPLIT,botonera,eco);
new JSplitPane(JSplitPane.VERTICAL_SPLIT,botonera,eco);
////Añade
Añadeelelpanel
panelaalalaventana
ventanaprincipal
principal
getContentPane().add(panelPrincipal);
getContentPane().add(panelPrincipal);
////Se
'redimensiona'
toda
la
interfaz
Se 'redimensiona' toda la interfazgráfica
gráficaen
enlalaventana
ventana
pack();
pack();
////YYhace
hacevisible
visiblelalaventana,
ventana,con
consus
suscomponentes
componentes
setVisible(true);
setVisible(true);
}}
public
publicstatic
staticvoid
voidmain(String[]
main(String[]args)
args){{
Loro
Loroloro
loro==new
newLoro();
Loro();
//...
//...aquí
aquítermina
terminalalaejecución
ejecucióndel
del'hilo
'hiloprincipal',
principal',
////......pero
peroqueda
quedapendiente
pendientelalaejecución
ejecucióndel
delhilo
hilode
de
////......tratamiento
tratamientode
deeventos...
eventos...AApartir
partirde
deahora
ahoratoda
todalala
////......ejecución
ejecuciónesesgobernada
gobernadapor
porlalainteracción
interaccióncon
conelelusuario.
usuario.
}}
private
privateJComponent
JComponentcreaEco()
creaEco(){{
////Se
Secrea
creaelelcampo
campode
detexto
textodonde
dondeponer
ponereleleco
eco
eco
=
new
JTextField("Pulsa
eco = new JTextField("Pulsaun
unbotón");
botón");
return
returneco;
eco;
}}
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
7
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
8
Una aplicación Swing sencilla: comportamiento
!
!
!
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:
!
!
!
!
OyenteHola
actionPerformed
(ActionEvent ev)
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
OyenteAdios
actionPerformed
(ActionEvent ev)
OyenteVentana
Estas clases están declaradas en el paquete java.awt.event
windowClosing
(WindowEvent ev)
import java.awt.event.*;
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
9
Una aplicación Swing sencilla: comportamiento
asociado a los botones
Java Swing
10
addWindowListener(
addWindowListener(
new
newWindowAdapter()
WindowAdapter(){{
public
publicvoid
voidwindowClosing(WindowEvent
windowClosing(WindowEventev)
ev){{
////Se
Setermina
terminalalaejecución
ejecuciónde
delalaaplicación
aplicación
System.exit(0);
System.exit(0);
}}
});
});
////......
////....yyseseañaden
añadenalalpanel
panel
botonera.add(hola);
botonera.add(hola);
botonera.add(adios);
botonera.add(adios);
return
returnbotonera;
botonera;
Java Swing
Terminar la
ejecución
public
publicLoro()
Loro(){{
setTitle("Loro");
setTitle("Loro");
JButton
JButtonadios
adios==new
newJButton("Dí
JButton("DíAdios");
Adios");
adios.addActionListener(
adios.addActionListener(
new
newActionListener()
ActionListener(){{
public
publicvoid
voidactionPerformed(ActionEvent
actionPerformed(ActionEventev)
ev){{
eco.setText("Adios!");
eco.setText("Adios!");
}});
}});
}}
Escribir adios en
el campo de texto
Una aplicación Swing sencilla: comportamiento
asociado a la ventana principal
private
privateJComponent
JComponentcreaBotonera()
creaBotonera(){{
JPanel
JPanelbotonera
botonera==new
newJPanel();
JPanel();////Panel
Panelpara
paracontener
contenerlos
losbotones
botones
////Se
crean
los
botones
...
Se crean los botones ...
JButton
JButtonhola
hola==new
newJButton("Dí
JButton("DíHola");
Hola");
hola.addActionListener(
hola.addActionListener(
new
newActionListener()
ActionListener(){{
public
publicvoid
voidactionPerformed(ActionEvent
actionPerformed(ActionEventev)
ev){{
eco.setText("Hola!");
eco.setText("Hola!");
}});
}});
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Escribir hola en
el campo de texto
11
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
12
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 los
controles 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
!
!
!
!
!
!
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
14
JFrame
import
importjava.awt.Color;
java.awt.Color;
import
importjava.awt.Dimension;
java.awt.Dimension;
import
importjava.awt.BorderLayout;
java.awt.BorderLayout;
import
importjava.awt.event.WindowAdapter;
java.awt.event.WindowAdapter;
import
importjava.awt.event.WindowEvent;
java.awt.event.WindowEvent;
import
importjavax.swing.JFrame;
javax.swing.JFrame;
import
importjavax.swing.JLabel;
javax.swing.JLabel;
import
importjavax.swing.JMenuBar;
javax.swing.JMenuBar;
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:
•
•
Juan Pavón Mestras
Facultad de Informática UCM, 2004
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)
JFrame
!
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 framework
AWT/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)
13
Java Swing
Consecuencias del funcionamiento:
!
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 Mestras
Facultad de Informática UCM, 2004
!
Funcionamiento de las aplicaciones con GUI en Java
Java Swing
Los contenidos se
añaden en el panel de
contenidos (content
pane) 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
public
publicclass
classTopLevelDemo
TopLevelDemo{{
public
publicstatic
staticvoid
voidmain(String
main(Strings[])
s[]){{
JFrame
frame
=
new
JFrame("TopLevelDemo");
JFrame frame = new JFrame("TopLevelDemo");
frame.addWindowListener(new
frame.addWindowListener(newWindowAdapter()
WindowAdapter(){{
public
void
windowClosing(WindowEvent
public void windowClosing(WindowEvente)e){{
System.exit(0);
System.exit(0);
}}
});
});
15
//...
//...
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
16
JFrame
JSplitPane y Box: Haciendo layout fácil en Swing
JLabel
JLabelyellowLabel
yellowLabel==new
newJLabel("");
JLabel("");
yellowLabel.setOpaque(true);
yellowLabel.setOpaque(true);
yellowLabel.setBackground(Color.yellow);
yellowLabel.setBackground(Color.yellow);
yellowLabel.setPreferredSize(new
yellowLabel.setPreferredSize(newDimension(200,
Dimension(200,180));
180));
!
El control de la disposición en Swing (y en AWT) se delega en
objetos especiales, denominados gestores de disposición (layout
managers)
!
JMenuBar
JMenuBarcyanMenuBar
cyanMenuBar==new
newJMenuBar();
JMenuBar();
cyanMenuBar.setOpaque(true);
cyanMenuBar.setOpaque(true);
cyanMenuBar.setBackground(Color.cyan);
cyanMenuBar.setBackground(Color.cyan);
cyanMenuBar.setPreferredSize(new
cyanMenuBar.setPreferredSize(newDimension(200,
Dimension(200,20));
20));
!
Swing ofrece además dos componentes que facilitan la
realización del layout:
!
frame.setJMenuBar(cyanMenuBar);
frame.setJMenuBar(cyanMenuBar);
frame.getContentPane().add(yellowLabel,
frame.getContentPane().add(yellowLabel,BorderLayout.CENTER);
BorderLayout.CENTER);
!
}}
frame.pack();
frame.pack();
frame.setVisible(true);
frame.setVisible(true);
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Para añadir componentes a un
JFrame se añaden
componentes a su panel de
contenidos
Java Swing
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
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
17
JSplitPane y Box: Haciendo layout fácil en Swing
Juan Pavón Mestras
Facultad de Informática UCM, 2004
18
Java Swing
JSplitPane y Box: Haciendo layout fácil en Swing
JSplitPane
peso=1
peso=0
JSplitPane
0 1
JSplitPane
1
Box
0
Box
glue
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
19
Juan Pavón Mestras
Facultad de Informática UCM, 2004
glue
Java Swing
20
JSplitPane y Box: Haciendo layout fácil en Swing
JSplitPane y Box: Haciendo layout fácil en Swing
public class
class LayoutDemo
LayoutDemo {{
public
public static
static void
void main(String
main(String s[])
s[]) {{
public
JButton b1
b1 == new
new JButton("Botón
JButton("Botón 1");
1");
JButton
JButton b2
b2 == new
new JButton("Botón
JButton("Botón 2");
2");
JButton
JButton b3
b3 == new
new JButton("Botón
JButton("Botón 3");
3");
JButton
JLabel e1
e1 == new
new JLabel("Etiqueta
JLabel("Etiqueta 1");
1");
JLabel
JLabel e2
e2 == new
new JLabel("Etiqueta
JLabel("Etiqueta 2");
2");
JLabel
Box cajaEtiquetas
cajaEtiquetas == Box.createVerticalBox();
Box.createVerticalBox();
Box
cajaEtiquetas.add(e1);
cajaEtiquetas.add(e1);
cajaEtiquetas.add(e2);
cajaEtiquetas.add(e2);
cajaEtiquetas.add(Box.createVerticalGlue());
cajaEtiquetas.add(Box.createVerticalGlue());
Box cajaBotones
cajaBotones == Box.createVerticalBox();
Box.createVerticalBox();
Box
cajaBotones.add(b1);
cajaBotones.add(b1);
cajaBotones.add(b2);
cajaBotones.add(b2);
cajaBotones.add(b3);
cajaBotones.add(b3);
cajaBotones.add(Box.createVerticalGlue());
cajaBotones.add(Box.createVerticalGlue());
Las cajas se crean con los
métodos estáticos
createHorizontalBox y
createVerticalBox de Box.
JSplitPane panelSecundario1
panelSecundario1 ==
JSplitPane
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
new
new JPanel(),
JPanel(),
new
cajaEtiquetas);
cajaEtiquetas);
panelSecundario1.setDividerSize(1);
panelSecundario1.setDividerSize(1);
panelSecundario1.setResizeWeight(1);
panelSecundario1.setResizeWeight(1);
JSplitPane panelSecundario2
panelSecundario2 ==
JSplitPane
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
new
cajaBotones,
cajaBotones,
panelSecundario1);
panelSecundario1);
panelSecundario2.setDividerSize(1);
panelSecundario2.setDividerSize(1);
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 Mestras
Facultad de Informática UCM, 2004
Java Swing
21
JSplitPane y Box: Haciendo layout fácil en Swing
Juan Pavón Mestras
Facultad de Informática UCM, 2004
22
Botones
!
JSplitPane panelPrincipal
panelPrincipal ==
JSplitPane
new JSplitPane(JSplitPane.VERTICAL_SPLIT,
JSplitPane(JSplitPane.VERTICAL_SPLIT,
new
panelSecundario2,
panelSecundario2,
new JPanel());
JPanel());
new
panelPrincipal.setDividerSize(1);
panelPrincipal.setDividerSize(1);
panelPrincipal.setResizeWeight(1);
panelPrincipal.setResizeWeight(1);
!
Los botones, junto con los menús, son los controles más típicos
en una GUI
Existen diferentes tipos (especializaciones de AbstractButton)
!
!
JFrame frame
frame == new
new JFrame("LayoutDemo");
JFrame("LayoutDemo");
JFrame
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
frame.addWindowListener(new WindowAdapter()
WindowAdapter() {{
frame.addWindowListener(new
public void
void windowClosing(WindowEvent
windowClosing(WindowEvent e)
e) {{
public
System.exit(0);
System.exit(0);
}}
});
});
!
!
frame.setContentPane(panelPrincipal);
frame.setContentPane(panelPrincipal);
frame.pack();
frame.pack();
frame.setVisible(true);
frame.setVisible(true);
}}
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)
!
}}
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
Java Swing
23
El evento semántico más común anunciado por los botones es
ActionEvent
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
24
Botones
Botones
Box caja
caja == Box.createHorizontalBox();
Box.createHorizontalBox();
Box
caja.add(new JButton("Un
JButton("Un botón
botón normal"));
normal"));
caja.add(new
caja.add(new
JToggleButton("Un
botón seleccionable"));
seleccionable"));
caja.add(new JToggleButton("Un botón
caja.add(new JToggleButton("Otro
JToggleButton("Otro botón
botón seleccionable",true));
seleccionable",true));
caja.add(new
caja.add(new JCheckBox("Cine"));
JCheckBox("Cine"));
caja.add(new
caja.add(new JCheckBox("Teatro"));
JCheckBox("Teatro"));
caja.add(new
caja.add(new JCheckBox("Música"));
JCheckBox("Música"));
caja.add(new
ButtonGroup
grupo
new ButtonGroup();
ButtonGroup();
ButtonGroup grupo == new
JRadioButton r1
r1 == new
new JRadioButton("Hombre");
JRadioButton("Hombre");
JRadioButton
JRadioButton r2
r2 == new
new JRadioButton("Mujer");
JRadioButton("Mujer");
JRadioButton
JRadioButton r3
r3 == new
new JRadioButton("Asexuado");
JRadioButton("Asexuado");
JRadioButton
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
25
Menús
grupo.add(r1);
grupo.add(r1);
grupo.add(r2);
grupo.add(r2);
grupo.add(r3);
grupo.add(r3);
caja.add(r1);
caja.add(r1);
caja.add(r2);
caja.add(r2);
caja.add(r3);
caja.add(r3);
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
26
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 item
de 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 Mestras
Facultad de Informática UCM, 2004
Java Swing
27
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
28
Menús
Menús
JMenu menu11
menu11 == new
new JMenu("Submenú");
JMenu("Submenú");
JMenu
menu11.add(new JMenuItem("Opción
JMenuItem("Opción 1"));
1"));
menu11.add(new
menu11.add(new JMenuItem("Opción
JMenuItem("Opción 2"));
2"));
menu11.add(new
menu1.add(menu11);
menu1.add(menu11);
barra.add(menu1);
barra.add(menu1);
barra.add(new JMenu("Menú
JMenu("Menú 2"));
2"));
barra.add(new
setJMenuBar(barra);
setJMenuBar(barra);
pack();
pack();
setVisible(true);
setVisible(true);
public class
class PruebaMenu
PruebaMenu extends
extends JFrame
JFrame {{
public
public void
void ejecuta()
ejecuta() {{
public
JMenuBar barra
barra == new
new JMenuBar();
JMenuBar();
JMenuBar
JMenu menu1
menu1 == new
new JMenu("Menú
JMenu("Menú 1");
1");
JMenu
menu1.add(new JMenuItem("Una
JMenuItem("Una opción
opción de
de texto"));
texto"));
menu1.add(new
menu1.add(new JSeparator());
JSeparator());
menu1.add(new
ButtonGroup grupo
grupo == new
new ButtonGroup();
ButtonGroup();
ButtonGroup
JRadioButtonMenuItem r1
r1 == new
new JRadioButtonMenuItem("Opción
JRadioButtonMenuItem("Opción 1");
1");
JRadioButtonMenuItem
JRadioButtonMenuItem r2
r2 == new
new JRadioButtonMenuItem("Opción
JRadioButtonMenuItem("Opción 2");
2");
JRadioButtonMenuItem
grupo.add(r1);
grupo.add(r1);
grupo.add(r2);
grupo.add(r2);
menu1.add(r1);
menu1.add(r1);
menu1.add(r2);
menu1.add(r2);
menu1.add(new JSeparator());
JSeparator());
menu1.add(new
menu1.add(new JCheckBoxMenuItem("Selección
JCheckBoxMenuItem("Selección 1",true));
1",true));
menu1.add(new
menu1.add(new JCheckBoxMenuItem("Selección
JCheckBoxMenuItem("Selección 2"));
2"));
menu1.add(new
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
}}
public static
static void
void main(String[]
main(String[] args)
args) {{
public
new PruebaMenu().ejecuta();
PruebaMenu().ejecuta();
new
}}
}}
29
Interacción modal
!
!
!
!
!
!
Java Swing
30
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 Mestras
Facultad de Informática UCM, 2004
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
!
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):
!
!
!
!
31
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 Mestras
Facultad de Informática UCM, 2004
Java Swing
32
Interacción modal
Interacción modal
JOptionPane.showMessageDialog(this, //
// La
La ventana
ventana padre.
padre.
JOptionPane.showMessageDialog(this,
"Error deconocido!:
deconocido!: Lo
Lo llevas
llevas muy
muy mal!",
mal!", //El
//El mensaje.
mensaje.
"Error
"Error", //
// El
El título
título de
de la
la ventana
ventana de
de diálogo.
diálogo.
"Error",
JOptionPane.ERROR_MESSAGE //
// El
El tipo
tipo de
de mensaje
mensaje
JOptionPane.ERROR_MESSAGE
);
);
int seleccionada
seleccionada ==
int
JOptionPane.showConfirmDialog(this,
JOptionPane.showConfirmDialog(this,
"Lo aceptas?",
aceptas?", "Aviso",
"Aviso",
"Lo
JOptionPane.YES_NO_OPTION, //
// Configuración
Configuración del
del mensaje
mensaje
JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE);
JOptionPane.INFORMATION_MESSAGE);
switch(seleccionada) {{
switch(seleccionada)
case JOptionPane.YES_OPTION:
JOptionPane.YES_OPTION: ...
... //
// tratar
tratar SI
SI
case
case JOptionPane.NO_OPTION:
JOptionPane.NO_OPTION: ..
.. //
// tratar
tratar NO
NO
case
case JOptionPane.CLOSED_OPTION:
JOptionPane.CLOSED_OPTION: ..
.. //
// tratar
tratar ventana
ventana cerrada
cerrada
case
default: ...
... //
// esta
esta opción
opción nunca
nunca debería
debería alcanzarse
alcanzarse
default:
}}
JOptionPane.showMessageDialog(this,
JOptionPane.showMessageDialog(this,
"Te informo
informo de
de que
que lo
lo llevas
llevas fatal",
fatal", "Info",
"Info",
"Te
JOptionPane.INFORMATION_MESSAGE);
JOptionPane.INFORMATION_MESSAGE);
int seleccionada
seleccionada ==
int
JOptionPane.showConfirmDialog(this,
JOptionPane.showConfirmDialog(this,
"Lo aceptas?","Aviso",
aceptas?","Aviso",
"Lo
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
JOptionPane.WARNING_MESSAGE);
... //
// los
los posibles
posibles valores
valores devueltos
devueltos son
son los
los anteriores
anteriores yy
...
... //
// JOptionPane.CANCEL_OPTION
JOptionPane.CANCEL_OPTION
...
JOptionPane.showMessageDialog(this,
JOptionPane.showMessageDialog(this,
"Te aviso
aviso de
de que
que lo
lo llevas
llevas fatal",
fatal", "Aviso",
"Aviso",
"Te
JOptionPane.WARNING_MESSAGE);
JOptionPane.WARNING_MESSAGE);
JOptionPane.showMessageDialog(this,
JOptionPane.showMessageDialog(this,
Este mensaje
mensaje es
es para
para tí,
tí, majete!",
majete!", "Mensaje",
"Mensaje",
Este
JOptionPane.PLAIN_MESSAGE);
JOptionPane.PLAIN_MESSAGE);
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
33
Interacción modal
Java Swing
34
Interacción modal
String nombre
nombre == JOptionPane.showInputDialog(this,
JOptionPane.showInputDialog(this,
String
"Cómo te
te llamas,
llamas, majete?",
majete?",
"Cómo
"Petición", JOptionPane.QUESTION_MESSAGE
JOptionPane.QUESTION_MESSAGE
"Petición",
);
);
// ...
... procesar
procesar entrada
entrada
//
String[] sexo
sexo == {"hetero","homo","bi","auto"};
{"hetero","homo","bi","auto"};
String[]
int opcion
opcion ==
int
JOptionPane.showOptionDialog(this,
JOptionPane.showOptionDialog(this,
"Y tú
tú qué
qué eres?",
eres?", "Petición",
"Petición",
"Y
-1, //
// opciones->quedan
opciones->quedan fijadas
fijadas por
por el
el array
array de
de opciones
opciones
-1,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.QUESTION_MESSAGE,
null,//icono. no
no hay.
hay.
null,//icono.
sexo, //
// array
array de
de opciones
opciones
sexo,
sexo[0] //
// opcion
opcion inicial
inicial
sexo[0]
);
);
... //
// procesamiento
procesamiento de
de la
la opcion
opcion ...
...
...
String[] colores
colores == {"rojo","negro","amarillo",
{"rojo","negro","amarillo",
String[]
"azul","majenta"};
"azul","majenta"};
Object opcion
opcion ==
Object
JOptionPane.showInputDialog(this,
JOptionPane.showInputDialog(this,
"Selecciona un
un color,
color, resalao!",
resalao!", "Petición",
"Petición",
"Selecciona
JOptionPane.QUESTION_MESSAGE,
JOptionPane.QUESTION_MESSAGE,
null, //icono.
//icono. no
no hay.
hay.
null,
colores, //
// opciones.
opciones. Se
Se le
le podría
podría pasar
pasar un
un array
array de
de
colores,
// objetos
objetos arbitrarios
arbitrarios
//
colores[0] //opción
//opción inicial
inicial
colores[0]
);
);
// ...procesar
...procesar opción...
opción...
//
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
35
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
36
Interacción modal: selección de archivos
!
!
Interacción modal: selección de archivos
Los diálogos de tipo JFileChooser facilitan esta tarea
La forma habitual de trabajar con JFileChooser es:
!
!
!
selector = new JFileChooser();
selector.setFileFilter(new FiltroTexto());
selector.setFileSelectionMode(JFileChooser.FILES_ONLY);
selector.setCurrentDirectory(new File(System.getProperty("user.dir")));
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.
!
!
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 Mestras
Facultad de Informática UCM, 2004
Java Swing
37
Interacción modal: selección de archivos
!
Un filtro de ficheros
class
classFiltroTexto
FiltroTextoextends
extendsFileFilter
FileFilter{{
public
publicboolean
booleanaccept(File
accept(Filef)f){{
String
Stringnombre
nombre==f.getName();
f.getName();
return
nombre.substring(Math.max(nombre.length()-4,0)).equals(".txt");
return nombre.substring(Math.max(nombre.length()-4,0)).equals(".txt");
}}
public
publicString
StringgetDescription()
getDescription(){{
return
return"Ficheros
"Ficherosde
detipo
tipotexto";
texto";
}}
}}
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.
!
Creación y configuración de un selector
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
38
Interacción modal: selección de archivos
El mismo selector permite crear diferentes diálogos de
selección
Uso habitual de un diálogo creado a través de un
FileChooser
selector.showOpenDialog(this)
if ( selector.showOpenDialog(this) == JFileChooser.APPROVE_OPTION )
{
File f = selector.getSelectedFile();
// Hacer lo que sea pertinente con el fichero ...
}
selector.showSaveDialog(this)
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
39
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
40
Otros contenedores Swing
!
JPanel. Un contenedor intermedio genérico
!
!
!
!
Otros componentes atómicos Swing
!
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
!
!
!
!
!
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
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)
botones
Juan Pavón Mestras
!
Facultad de Informática UCM, 2004
Java Swing
41
Juan Pavón Mestras
Facultad de Informática UCM, 2004
Java Swing
42
Descargar