Está en la página 1de 72

CREANDO GUIs CON JFC/SWING

Programación en Java

Adolfo Rodríguez de Soto


Carlos Testera González
Conrado Andreu Capdevila
Conrado A. Capdevila
Creando GUIs con JFC/SWING
JFC

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN I
 JFC  Java Foundation Classes.
 JFC abarca varias características para dotar
de funcionalidad gráfica a Java.
 Componentes GUI Swing.
 Soporte de aspecto (look-and-feel).
 API de accesibilidad.
 API 2D.
 Soporte de arrastrar y soltar.
 Internacionalización.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Lo que necesitamos

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN II
 De la JFC, veremos los componentes Swing
y los aspectos relacionados (no exclusivos
de Swing) para poder manejarlos, como:
 Eventos.
 Acciones.
 Clases internas y anónimas.
 Interfaces y clases adaptadoras.
 Administradores de diseño.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Antecedentes

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN III
 ANTECEDENTES
 Java 1.0 utilizaba AWT (Abstract Window
Toolkit).
 AWT delega la creación de elementos de
interfaz de usuario a las herramientas nativas de
la GUI de la plataforma de destino (Windows,
Solaris, Macintosh, etc).
 En teoría solo sería necesario especificar
localización y comportamiento de los
componentes y se podrían ejecutar en cualquier
plataforma con el aspecto de esa plataforma.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Problemas de AWT

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN IV
 PROBLEMAS DEL AWT
 El mismo elemento de interfaz de usuario tiene
sutiles diferencias de comportamiento según la
plataforma.
 Ciertos entornos gráficos no tienen una
colección de componentes gráficos tan rica
como por ejemplo Windows o Macintosh.
 Esto reduce la biblioteca portable al “máximo común
denominador” que suele ser muy pequeño.
 El resultado fueron interfaces gráficas poco
atractivas, con menor funcionalidad de la
requerida y con fallos al cambiar de plataforma.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Swing - AWT

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN V
 Swing no reemplaza a AWT. Ofrece al
usuario componentes de interfaz más
capaces y completos.
 AWT abarca muchas funcionalidades
necesarias:
 Eventos.
 Aspectos.
 Administradores de diseño.
 Los elementos de interfaz AWT siguen
existiendo, pero no se me ocurre ninguna
situación donde sean necesarios.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Swing – ventajas

Adolfo R. de Soto
e inconvenientes

Carlos Testera
INTRODUCCIÓN VI
 Los componentes Swing se dibujan sobre ventanas
en blanco, de forma que los elementos tienen el
mismo aspecto y comportamiento en todas las
plataformas.
 Swing aporta numerosas ventajas …
 Conjunto de elementos de interfaz mucho más extenso y
útil que AWT.
 No depende de la plataforma para mostrar los elementos
(se reducen mucho los errores por migración).
 El manejo de los elementos no varía con la plataforma.
 … y algún inconveniente:
 Algo más lento que AWT.
 El uso de la aplicación no se adapta a la plataforma
(resuelto con los aspectos (look-and-feel)).
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cosas sueltas

Adolfo R. de Soto
Carlos Testera
INTRODUCCIÓN VII
 Otros aspectos interesantes:
 Las clases Swing se encuentran en el paquete javax.swing
 No es recomendable mezclar elementos Swing con
elementos AWT.
 Usaremos por defecto el aspecto Metal, un aspecto creado
por Sun independiente de la plataforma.
 Ya existen entornos visuales muy potentes y elaborados
para el diseño de interfaces gráficas (NetBeans, VisualAge,
Jdeveloper …). Tener cuidado con el código generado por
cada uno de ellos y por la biblioteca requerida.
– Obligatorio: leer
http://docs.oracle.com/javase/tutorial/uiswing/
– excepto NetBeans, concurrencia, otros rasgos de Swing,
drag and drop, sonido, applets, javaFX, modo full-
screen
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Hola Mundo en Swing

Carlos Testera
Import javax.swing.*;
public class HolaMundoSwing {
private static void crearYMostrarGUI() {
//Crear la ventana principal
JFrame frame = new JFrame("HolaMundoSwing");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
//Añadir la etiqueta
JLabel label = new JLabel("Hola Mundo");
frame.getContentPane().add(label);
//Visualizar la ventana
frame.setVisible(true); }
public static void main(String[] args) {
//Planificar la aplicación para ejecutar el hilo de evento
javax.swing.SwingUtilities.invokeLater( }
new Runnable() { public void run() { crearYMostrarGUI(); } });
}}
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
MARCOS I
 Toda componente para ser visualizada debe ser parte de una
jerarquía de componentes.
 Cada componente sólo puede estar contenida en una
componente.
 Un marco es una ventana del nivel más alto (no está
contenida en otra). JDialog, JApplet.
 La clase Swing para generar marcos es JFrame.
 Es una de las pocas clases Swing que no se dibujan en un
lienzo, sino que las dibuja el sistema de ventanas de la
plataforma destino.
 Los marcos son ejemplos de contenedores (contiene otros
elementos de la interfaz de usuario).
 Algunos aspectos útiles:
 Inicialmente su tamaño es de 0 x 0 píxeles (hay que darle
tamaño).
 Su posición inicial es la coordenada (0,0), la esquina superior
izquierda de la pantalla (hay que posicionarlo).
 Inicialmente es invisible (hay que hacerlo visible).
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Como crear un marco

Adolfo R. de Soto
Carlos Testera
MARCOS II
 Veamos el código que genera el marco de
la figura.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cuadro de contenido

Adolfo R. de Soto
Carlos Testera
MARCOS III
 La estructura de un JFrame es muy compleja. Una de sus
partes es lo que se conoce como cuadro de contenido, un
contenedor donde se añadirán los componentes (nunca se
añaden directamente al frame).

 Los métodos utilizados con los marcos (y con cualquier otra


clase) no tienen por qué ser de dicha clase. Puede haberlos
heredado de las clases de las que desciende. Aquí se
muestra la jerarquía de clases de JFrame. Es solo un
ejemplo. Para otros componentes podéis consultar la API.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
MVC I
 Todos los componentes Swing tienen tres
características:
 Su contenido, como el estado de un botón (pulsado o
no), o el texto de un campo de texto.
 Su aspecto visual (color, tamaño, etc).
 Su comportamiento (la reacción a los eventos).

 El aspecto visual puede variar sin que ello afecte al


contenido, o dicho estado podrá modificarse según
el comportamiento, pero tampoco modificará el
contenido del componente.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
MVC II
 Para recoger dicho comportamiento, Swing utiliza
un patrón de diseño de software denominado
Patrón Modelo-Vista-Controlador (MVC – Model-
View-Controller).

 Este patrón implementa tres clases separadas:


 El modelo, que guarda el contenido.
 La vista, que muestra el contenido.
 El controlador, que manipula la entrada del usuario.

 El patrón especifica como interactúan estos tres


objetos.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Modelo

Adolfo R. de Soto
Carlos Testera
MVC III
 El modelo guarda el contenido y no tiene interfaz
de usuario.
 Por ej, para un campo de texto, el modelo es una
cadena de caracteres que contiene el texto actual.
Esto no es lo mismo que la vista del contenido; si el
contenido es mayor que el campo, el usuario solo
verá parte del texto.
 El modelo debe implementar métodos para cambiar
el contenido y devolver los contenidos. Por ej, un
modelo de texto tiene métodos para añadir o quitar
caracteres y devolver el texto como una cadena.

Modelo  “El veloz zorro marrón salta sobre el perezoso perro.”

Vista 
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Controlador

Adolfo R. de Soto
Carlos Testera
MVC IV
 El controlador manipula los eventos de las
entradas del usuario, como los clicks de ratón y las
pulsaciones de teclado. Decide entonces si traduce
estos eventos en cambios en el modelo o en la
vista.

 En el ej, del campo de texto, si el usuario pulsa un


carácter, el controlador llama al comando
“insertar_caracter” del modelo (y el modelo le dice a
la vista que se actualice).

 Si el usuario pulsa una tecla de flecha, el


controlador le dice a la vista que se desplace. Esto
no tiene efecto en el texto, por lo que el modelo no
sabrá nunca que este evento ha ocurrido.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
¿Es necesario usarlo?

Adolfo R. de Soto
Carlos Testera
MVC V
 Cuando utilicemos Swing generalmente no habrá
que preocuparse del MVC.

 Cada elemento tiene una clase envolvente


(JButton, JTextField, etc) que guarda el modelo y la
vista. Cuando se quiera saber cual es el contenido,
la clase envolvente se lo pedirá al modelo.

 En otras ocasiones si será necesaria su utilización,


sobre todo trabajar directamente con el modelo
(tablas), y casi nunca con la vista.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS I
 Los componentes Swing necesitan organizarse de alguna manera
dentro del contenedor en el que vayan a estar, ya sea un marco, un
panel, etc.

 Para permitir esto, Java utiliza lo que se conoce como


administradores de diseño.

 Existen varios administradores de diseño que organizan los


componentes de forma diferente en un contenedor. Aunque la
siguiente lista muestra unos cuantos, nosotros solo veremos y
usaremos tres (los tres primeros).
 FlowLayout.
 BorderLayout.
 GridLayout.
 GridBagLayout.
 BoxLayout.
 CardLayout.
 SpringLayout.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS II
 El uso básico de los layouts es bastante simple. La clase
java.awt.Container de la cual derivan todos los contenedores
(marcos, paneles, etc), tiene un método llamado setLayout que
establece el layout manager para dicho contenedor.

 El siguiente código muestra un JFrame al que le asignamos un


BorderLayout y un panel al que le asignamos un GridLayout.

 Luego solamente hay que añadir los componentes conforme al


layout que estemos utilizando en el contenedor.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
FlowLayout

Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS III
 El FlowLayout alinea los componentes
horizontalmente hasta que no hay más espacio y
entonces comienza una nueva fila.

 Podemos hacer que los componentes estén


centrados, alineados a la izquierda o a la derecha.
 Podemos establecer los huecos horizontales y
verticales entre los componentes (o solaparlos).
 Los componentes aparecen en el orden en el que
se añaden.
 Para saber como hacer todo esto hay que consultar
la API.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
BorderLayout

Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS IV
 El BorderLayout organiza los componentes en
cinco zonas.

 Es el layout por defecto en los frames.


 No se suelen añadir componentes directamente
(ocupan toda la zona), sino paneles con otra
organización interna.
 El componente se añade especificando la zona (por
tanto no importa el orden de agregación).
Conrado A. Capdevila
Creando GUIs con JFC/SWING
GridLayout

Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS V
 El GridLayout es una disposición en cuadrícula. Al
especificarlo en el contenedor se indican las filas y
columnas que lo forman.

 Al añadir los componentes se añaden en orden por


filas y columnas.
 También pueden especificarse huecos horizontales
y verticales.
 Todos los componentes de la rejilla tienen el mismo
tamaño.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
EVENTOS I
 Un entorno GUI monitoriza eventos como las
pulsaciones del teclado o los clics de ratón y la
aplicación responde de una forma determinada a
estos eventos. Programación Orientada a Eventos.

 En el sistema de eventos de AWT se controla la


forma en la que los eventos se transmiten desde los
orígenes de eventos (botones o barras de
desplazamiento) a los oyentes de eventos, que
puede ser cualquier objeto.

 Este modelo se conoce como modelo de


delegación de eventos. Patrón Observador.
Creando GUIs con JFC/SWING

Patrón Observer

Adolfo R. de Soto
Carlos Testera
Conrado A. Capdevila
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
EVENTOS II
 Los orígenes de eventos tienen métodos que permiten
registrar oyentes de eventos. Cuando un evento ocurre en el
origen, este envía una notificación del evento a todos los
oyentes que se registraron para ese evento.

 La información de un evento se encapsula en un objeto de


tipo evento.

 Todos los eventos derivan de la clase java.util.EventObject,


aunque obviamente hay subclases para cada tipo de evento,
tales como ActionEvent o WindowEvent.

 Diferentes orígenes de eventos producen diferentes tipos de


eventos. Por ej, un botón envía objetos ActionEvent, mientras
que una ventana envía objetos WindowEvent.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Ejemplo Evento “Interesting”

Carlos Testera
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Funcionamiento

Adolfo R. de Soto
Carlos Testera
EVENTOS III
 Un resumen de funcionamiento podría ser:
 Un objeto oyente es una instancia de una clase que implementa
una interfaz especial llamada interfaz oyente.
 Un origen de eventos es un objeto que puede registrar objetos
oyentes y enviarles objetos de eventos. La sintaxis para el
registro suele tener la forma siguiente:
objetoOrigenEvento.add<Evento>Listener(objetoOyenteEvento);
 El origen de eventos envía objetos de eventos a todos los
oyentes registrados cuando ocurre ese evento.
 Los objetos oyente usarán la información del objeto evento para
determinar su reacción al evento.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Clases internas

Adolfo R. de Soto
Carlos Testera
EVENTOS IV
 Ejemplo de clic de un botón
Clase para el panel que
utilizando una clase interna. contiene el frame

Clase principal

Registro del oyente

Clase para el frame

Clase oyente INTERNA

Lo que ocurre al
pulsar el botón
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cases internas anónimas

Adolfo R. de Soto
Carlos Testera
EVENTOS V
 Modificación del ejemplo anterior para utilizar clases
anónimas.

En el ej anterior aquí
teníamos una instancia de
una clase oyente interna.

Ahora no hemos definido ninguna clase.


Usamos una CLASE INTERNA ANÓNIMA (una
clase sin nombre). En este caso es una
clase que implementa el interfaz
ActionListener y por lo tanto hay que
escribir el método actionPerformed.

Obviamente, estas clases solo pueden utilizarse


cuando se necesita un único objeto de dicha clase.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Eventos de ventana

Adolfo R. de Soto
Carlos Testera
EVENTOS VI
 Captura de los eventos de ventana.
 Un objeto JFrame es el origen de un WindowEvent. Para
capturar este evento hay que tener un oyente apropiado y
registrarlo como oyente de la ventana.
 Dicho oyente ha de ser una clase que implemente el interfaz
WindowListener.

 En ese interfaz hay siete métodos para dotar de funcionalidad a


los siete eventos que pueden ocurrir.
 Si queremos capturar el evento
de cerrar ventana, dotaremos
de funcionalidad a este y
dejaremos al resto vacíos
(recordar que hay que poner
todos los métodos del interfaz).

La verdad es que esto no es


muy elegante.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Clases adaptadoras

Adolfo R. de Soto
Carlos Testera
EVENTOS VII
 Para arreglar el desastre del ejemplo anterior se utilizan lo
que se conocen como clases adaptadoras.
 Cada interfaz del oyente del AWT que tiene más de un
método viene con una clase compañera adaptadora que
implementa todos los métodos de la interfaz pero que no hace
nada con ellos.
 Para los eventos de ventana, tenemos la clase
WindowAdapter, que tiene siete métodos que no hacen
nada.
Por supuesto que con las clases
Ojo, ahora ya no se adaptadoras pueden segui r
implementa un interfaz, usándose clases anónimas.
se hereda de una clase.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Eventos semánticos

Adolfo R. de Soto
y de bajo nivel

Carlos Testera
EVENTOS VIII
 AWT distingue dos tipos de eventos:
 Semánticos: expresan lo que el usuario está haciendo (pulsar un botón, cambiar
el texto).
 De bajo nivel: hacen posibles los eventos semánticos. En el caso de pulsar el
botón sería el hecho de pulsar el ratón, controlar sus movimientos, su liberación
(pero solo si está dentro del área del botón, etc).
 Hay cuatro clases de eventos semánticos:
 ActionEvent: para un clic de ratón, una selección de menú, seleccionar un
elemento de una lista o pulsar intro en un campo de texto.
 AdjustmentEvent: ajustar una barra de desplazamiento.
 ItemEvent: selección desde un conjunto de casillas de verificación o elementos
de una lista.
 TextEvent: cambiar el contenido de un campo o área de texto.
 Hay siete clases de eventos de bajo nivel:
 ComponentEvent: cambiar el tamaño o posición de un componente (es la clase
base de todos los eventos de bajo nivel).
 KeyEvent: se ha pulsado o liberado una tecla.
 MouseEvent: el botón del ratón se ha pulsado, se ha soltado, se ha movido el
ratón o se ha arrastrado.
 MouseWheelEvent: ha girado la rueda del ratón.
 FocusEvent: un componente obtiene o pierde el foco.
 WindowEvent: el estado de la ventana a cambiado.
 ContainerEvent: se ha añadido o eliminado un componente.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Eventos de teclado

Adolfo R. de Soto
Carlos Testera
EVENTOS IX
 En un evento de teclado, cuando un usuario pulsa una tecla se
genera un evento keyPressed KeyEvent. Cuando se suelta se
genera un keyRelease KeyEvent. El método keyTyped agrupa los
dos anteriores e informa sobre el carácter que se ha generado.
 Estos tres métodos se encuentran en el interfaz KeyListener.
 Java distingue entre caracteres y códigos virtuales de tecla, que se
corresponden con las teclas del teclado. Empiezan con el prefijo
VK_, como VK_A o VK_SHIFT. Por ej, VK_A indica la tecla A (tanto
mayúscula como minúscula, solo hay una tecla para ambas. En el
método keyTyped y con getChar se puede obtener el carácter).
Consultar la clase KeyEvent en la API para ver los códigos.
 Para controlar el estado de las teclas Mayús, Ctrl, Alt y Meta se
pueden controlar VK_SHIFT, VK_CONTROL, VK_ALT y VK_META,
pero es más cómodo usar los métodos isShiftDown, isControlDown,
isAltDown e isMetaDown.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Eventos del ratón

Adolfo R. de Soto
Carlos Testera
EVENTOS X
 Cuando el usuario hace clic con un botón del ratón llama a tres
métodos oyentes: mousePressed (al pulsar), mouseReleased (al
soltar) y mouseClicked (engloba los dos, solo clics completos). A
todos se les llama con un evento de tipo MouseEvent.
 Se utiliza getClickCount para contar el número de clics y diferenciar
entre un clic, doble clic, etc.
 Si se mueve el ratón mientras se pulsa un botón, se llama al método
mouseDragged.
 Para escuchar los eventos del ratón se usan los interfaces
MouseListener y MouseMotionListener (para los eventos que
implican movimiento).
 Hay más métodos, como mouseEntered, mouseExited y
mouseMoved. Consultar la API y la tabla siguiente para más
información.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Tabla resumen

Adolfo R. de Soto
Carlos Testera
EVENTOS XI
INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS
ADAPTADORA ACCESORIOS GENERADOS POR
ActionListener actionPerformed ActionEvent AbstractButton
getActionCommand JComboBox
getModifiers JTextField
Timer

AdjustmentListener AdjustmentValueChanged AdjustmentEvent JScrollBar


getAdjustable
getAdjustableType
getValue

ItemListener itemStateChanged ItemEvent AbstractButton


getItem JComboBox
getItemSelectable
getStateChange

TextListener textValueChanged TextEvent

INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS


ADAPTADORA ACCESORIOS GENERADOS POR
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Tabla resumen

Adolfo R. de Soto
Carlos Testera
EVENTOS XII
INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS
ADAPTADORA ACCESORIOS GENERADOS POR

ContainerListener ContainerAdapter componentAdded ContainerEvent Container


componentRemoved getChild
getContainer

FocusListener FocusAdapter focusGained FocusEvent Component


focusLost isTemporary

KeyListener KeyAdapter keyPressed KeyEvent Component


keyReleased getKeyChar
keyTyped getKeyCode
getKeyModifiersText
getKeyText
isActionkey

INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS


ADAPTADORA ACCESORIOS GENERADOS POR
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Tabla resumen

Adolfo R. de Soto
Carlos Testera
EVENTOS XIII
INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS
ADAPTADORA ACCESORIOS GENERADOS POR

MouseMotionListener MouseMotionAdapter mouseDragged MouseEvent Component


mouseMoved

MouseWheelListener mouseWheelMoved MouseWheelEvent Component


getWheelRotation
getScrollAmount

WindowListener WindowAdapter windowClosing WindowEvent Window


windowOpened getWindow
windowIconified
windowDeiconified
windowClosed
windowActivated
windowDeactivated

WindowFocusListener windowGainedFocus WindowEvent Window


windowLostFocus getOppositeWindow

INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS


ADAPTADORA ACCESORIOS GENERADOS POR
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
ACCIONES I
 El objetivo de las acciones es proporcionar un mecanismo para
activar de varias formas un mismo comando. Por ej, a través de un
menú, el teclado o un botón de una barra de herramientas. Las
acciones evitan tener que enlazar todos los eventos al mismo
oyente.

 Para poder utilizar las acciones, Swing proporciona la interfaz


Action, la cual tiene los siguientes métodos:
 void actionPerfomed(ActionEvent evento)
 void setEnabled(boolean b)
 boolean isEnabled()
 void putValue(String key, Object value)
 Object getValue(String key)
 void addPropertyChangeListener(PropertyChangeListener listener)
 void removePropertyChangeListener(PropertyChangeListener listener)

 La interfaz Action deriva de la interfaz ActionListener (ver que


comparten el método actionPerformed). Por tanto, podemos utilizar
un objeto Action donde se espere un objeto ActionListener.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Métodos y pares nombre/valor

Adolfo R. de Soto
Carlos Testera
ACCIONES II
 Los métodos setEnabled y isEnabled permiten activar o desactivar la
acción (muy útil porque atenúan los componentes que usan dicha
acción) y comprobar si la acción está activa respectivamente.

 Los métodos putValue y getValue permiten guardar y recuperar pares


arbitrarios nombre/valor en el objeto acción. Aquí se muestran
algunos nombres útiles y su función:
 NAME: el nombre de la acción. Se muestra en botones y opciones de menú.
 SMALL_ICON: guarda un icono pequeño. Se muestra en un botón, opción de
menú o barra de herramientas.
 SHORT_DESCRIPTION: descripción corta. Se muestra como tooltip al
mantener el ratón sobre el componente.
 MNEMONIC_KEY: método abreviado de teclado. Lo veremos cuando veamos
menús.

 Existe una “especie” de clase adaptadora para la interfaz Action que es


AbstracAction. No es propiamente una clase adaptadora porque
implementa todos los métodos menos el actionPerformed. Además, hace
más cosas ya gestiona los pares nombre/valor y los oyentes de propiedad
de cambio. Esto último está relacionado con los dos últimos métodos de
la interfaz y no lo vamos a ver. Es más importante en JavaBeans.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Pulsaciones de teclas

Adolfo R. de Soto
Carlos Testera
ACCIONES III
 Para asociar pulsaciones de teclas a las acciones
hay que generar objetos de la clase KeyStroke.

 Para crear un objeto de este tipo no se llama a un


constructor, sino que se llama al método estático
getKeyStroke de la clase, que recibe el código
virtual de la tecla y los modificadores o una cadena.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Mapas

Adolfo R. de Soto
Carlos Testera
ACCIONES IV
 Ahora hay que enlazar los objetos KeyStroke a las acciones. Esto se
hace con tres mapas de entrada y un mapa de acción que tienen
todos los objetos JComponent.
 Cada mapa de entrada se corresponde con una condición diferente.
 WHEN_FOCUSED: cuando el componente tiene el foco del teclado.
 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: cuando el
componente contiene el componente que tiene el foco del teclado.
 WHEN_IN_FOCUSED_WINDOW: cuando el componente está contenido
en la misma ventana que el componente que tiene el foco del teclado.
 Un mapa de entrada (clase InputMap) se obtiene con el método
getInputMap del componente, y un mapa de acción (clase
ActionMap) se obtiene con el método getActionMap.

Esto tiene que ser un


“Object”. Usamos un a
cadena porque es lo más
cómodo. Si se pone a null
rompemos el enlace.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Ejemplo

Adolfo R. de Soto
Carlos Testera
ACCIONES V
Este ejemplo muestra un panel con
tres botones que cambian el color
de dicho panel. Utilizamo s
acciones que nos ayudan a mostrar
tooltips, a cambiar el color con
los botones o con teclas.

La clase principal y el
marco que contiene el panel
que tiene los botones a los
que se asocian las acciones.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Ejemplo

Adolfo R. de Soto
Carlos Testera
ACCIONES VI

Mapa de Clase acción que establece los


entrada nombre, iconos y descripciones
cortas. Además, con el
actionPerformed establecemos lo
que realiza la acción (cambiar
el color del panel).

Mapa de
acción
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Introducción

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING I
 Veamos ahora unos cuantos componentes Swing, teniendo
en cuenta alguna cosa:
 No vamos a verlos todos (ni mucho menos), sino los más
representativos para una determinada función.
 Los analizaremos someramente y explicando para que sirven.
No se verán a fondo ni estudiaremos sus métodos o
propiedades (para eso está la API).
 Haremos algún ejemplo intermedio que demuestre su
funcionamiento, pero agrupando varios componentes.

 Algunos no los veremos aunque se usan constantemente


(contenedores como marcos y paneles, botones, etc). Con los
ejemplos de las secciones anteriores debería ser suficiente
para manejarlos más o menos.

 Es importante que durante esta sección tengáis a mano la API


y para cada clase consultéis sus constructores, constantes,
un vistazo a los métodos, etc.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Entrada de texto

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING II
 Hay varios componentes útiles a la hora de trabajar con texto:
 Etiquetas (JLabel): texto estático.
 Campos de texto (JTextField): permite la entrada de texto al usuario.
 Campos de contraseñas (JPasswordField): igual que el anterior pero
con el texto oculto para poder introducir texto “delicado” como
contraseñas.
 Áreas de texto (JTextArea): para introducir grandes cantidades de texto.
 Hay otros componentes más avanzados y muy útiles, con otras
funcionalidades (soportan estilos, permiten objetos embebidos, etc),
como los JEditorPane o JTextPane.

Campo de texto JEditorPane


Etiqueta

Campo de
contraseña

JTextPane
Área de texto
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Selecciones

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING III
 Cuando tenemos que realizar una selección, dependiendo de
la necesidad podremos usar alguno de estos componentes:
e
bl
ita

 Casillas de verificación (JCheckBox): se usan para obtener una


ed

entrada de tipo “sí” o “no”.


No

 Botones de radio (JRadioButton): se usan para que el usuario


seleccione una sola opción de varias disponibles. Se agrupan en
objetos de tipo ButtonGroup.
 Cuadros combinados (JComboBox): misma finalidad que los
radio buttons pero para ofrecer más opciones. Además ofrecen
la opción de hacerlas editables y seleccionar una opción que
le

inicialmente no existe.
b
ta
i

Existen otros como listas (JList), deslizadores (JSlider) y


Ed


spinners (JSpinner).
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Menús

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING IV
 La construcción de menús, aunque puede llegar a ser muy
elaborada, precisa de tres clases básicas:
 Barra de menú (JMenuBar): en ella se sitúa el menú.
 Menús (JMenu): Son los elementos principales, de los que
“cuelgan” items.
 Elementos o items de menú (JMenuItem): son los elementos
finales, los que se seleccionan.
 A los menús se les pueden añadir items que sean checkboxes
o radio buttons, así como iconos, métodos abreviados, teclas
aceleradoras, etc. Es muy útil gestionarlos con acciones.

JMenuBar

JMenuItem

JMenu
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cuadros de diálogo

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING V
 Vamos a realizar dos clasificaciones de los cuadros
de diálogo:
 Cuadros de diálogo predefinidos: la API nos proporciona
clases y métodos para generar cuadros de diálogo
predefinidos muy útiles en la mayoría de las ocasiones.
 Clase JOptionPane: cuadros de diálogo para mensajes,
confirmaciones, opciones básicas y obtención de
información también muy básica.
 Selectores de ficheros (JFileChooser): para entrada/salida
con el sistema de ficheros.
 Selectores de color (JColorChooser): para elegir colores.
Muestra paletas y configuraciones de colores.
 Cuadros de diálogo creados por el programador (clase
JDialog): permiten al programador generar sus propios
diálogos personalizados con todos los elementos que
sean necesarios. Hay dos tipos:
 Modales: bloquean el resto de ventanas hasta que se
cierran.
 No modales: permiten seguir trabajando con el resto de
ventanas aún cuando están abiertos.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cuadros de diálogo

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING VI
 La clase JOptionPane ofrece cuatro métodos para generar
cuadros de diálogo predefinidos:
 showMessageDialog: muestra un mensaje y espera a que el
usuario pulse OK.
 showConfirmDialog: muestra un mensaje y obtiene
confirmación (del estilo OK/Cancel).
 showOptionDialog: muestra un mensaje y obtiene una opción
de una serie de opciones.
 showInputDialog: muestra un mensaje y obtiene una línea de
entrada del usuario.

 Estos cuadros de diálogo tienen un icono, un mensaje, uno o


más botones de opciones y opcionalmente (dependiendo
del tipo), un cuadro de texto para la entrada de información.

 El mensaje puede ser una cadena, un icono, un componente


o cualquier otro objeto.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cuadros de diálogo

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING VIII
 Los selectores de ficheros y de colores son muy
versátiles y con multitud de opciones. Consultar la API.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Cuadros de diálogo

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING IX
 Podemos crear nuestros propios cuadros de diálogo
personalizados. Para ello tendremos que derivar de la clase
JDialog.

 Para crear un cuadro de diálogo, solo tendremos que indicarle


cual es su marco propietario (puede ser null), su título y si es
modal o no modal.

 Por lo demás su funcionamiento es muy similar a un JFrame.

 Una de las cosas más importantes es controlar bien el


intercambio de datos con los cuadros de diálogo
(normalmente para eso se utilizan). Para esto se suele
implementar en la clase del diálogo un método que muestra el
cuadro de diálogo y devuelve el estado de una variable
booleana que indica si el cuadro se ha aceptado (hay que
recoger los datos) o se ha cancelado (no se hace nada).
Ver ejemplo IntercambioDatos.java
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Mostrar datos

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING X
 Hay varios componentes para mostrar datos de diferentes
tipos. Los dos más utilizados son las tablas y los árboles.
 Ambos son componentes avanzados. Nos obligan a trabajar
directamente con su modelo (recordar el MVC).
 Las tablas (JTable) nos sirven para mostrar datos en una
rejilla y, opcionalmente, permitir al usuario modificar los datos.
Un objeto de esta clase no contiene datos, solo nos sirve
como vista de los datos, los cuales gestionaremos a través de
su modelo.
 Los árboles (JTree) nos sirven para mostrar datos
jerárquicos. Un objeto de esta clase no contiene datos, solo
nos sirve como vista de los datos, los cuales gestionaremos a
través de su modelo.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Otros componentes

Adolfo R. de Soto
Carlos Testera
COMPONENTES SWING XI
 Aún hay otros cuantos componentes Swing interesantes cuyo
funcionamiento podéis consultar en la API y en el tutorial de
Java de Sun:
 Marcos internos: para escribir aplicaciones tipo MDI Windows.
(Ver ej, libreria.java).
 Barras de herramientas: permiten colecciones de botones con
iconos para tener acceso rápido a determinadas opciones
(tendréis que utilizarlas vosotros en un ejemplo).
 Barras de progreso: para indicar progresos en determinadas
acciones.
 Paneles de desplazamiento: añaden barras de desplazamiento
a los componentes. Los veremos en numerosos ejemplos.
 Separadores: nos permiten dividir un contendor en partes y
añadir componentes a cada parte.
 Paneles tabulados: permiten crear varios paneles ocupando el
mismo espacio que pueden seleccionarse mediante pestañas.
 Bordes: permiten añadir bordes a paneles y otros contenedores.
 Iconos e imágenes: no se si hay mucho que explicar.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Pintando en AWT y SWING

Carlos Testera
• Qué es y cómo se pinta
• Callbacks
• Clases importantes:
– Graphics
• Api Java 2D
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Pintar en un sistema de ventanas

Carlos Testera
• Pintar es renderizar un conjunto de bits a una pantalla
u otro dispositivo.
• Lo importante es pintar lo correcto en el momento
justo.
• Hay dos tipos de peticiones de pintar:
– Peticiones por parte del sistema a una componente:
• La primera vez que se visualiza.
• El componente se redimensiona.
• El componente se ha deteriorado (estaba oculto).
– Peticiones por parte de la aplicación: el estado
interno de la componente ha cambiado.
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Peticiones del sistema:

Adolfo R. de Soto
Carlos Testera
el método paint
Public void paint (Graphics g)
• Es un método callback, el programador lo redefine
pero es llamado por el sistema. Está en Component.
• Cuando el sistema llama a paint, el objeto g se
configura para contener el estado adecuado para
pintar la componente: color, font, translation
(coordenadas), clip Rectangulo (zona a pintar), ...
• La operación toma lugar en dos pasos:
– Determinar la zona a pintar.
– Provocar que el hilo de despacho de eventos
invoque paint()
• Ejemplo PaintDemo
Conrado A. Capdevila
Creando GUIs con JFC/SWING
Peticiones de aplicación:

Adolfo R. de Soto
Carlos Testera
el método repaint
Public void repaint ()
Public void repaint (int x, int y, int
width, int height)
...
• Es el método que el programador debe
invocar para provocar un pintado. No debe
llamar directamente a paint().
• En repintados complejos debería evitarse el
repintado completo y definir la zona a repintar.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
El método update

Carlos Testera
• El repintado por parte de la aplicación
requiere de 4 pasos:
– Determinar por parte de la aplicación la zona a
repintar.
– Invocar a repaint().
– El hilo de despacho de eventos invoca a
update().
– Si no se ha redefinido update(), su efecto es
borrar el fondo de la comp. y llamar a paint().
• Puede redefinirse update() y aprovechar esa
llamada intermedia.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Componentes pesadas y ligera

Carlos Testera
• Componentes pesadas: disponen de ventana propia.
• Componentes ligeras: no disponen de ventana propia. Usan
la de su ancestro.
• Desde el punto de vista del programador casi no hay
diferencias a la hora de repintar unas u otras.
• Las componentes pesadas que se deben repintar lanzan
paints a todos sus decendientes ligeros.
• Si una clase desciende de Container y redefine paint(),
debe invocar como última llamada: super.paint().
• Las componentes ligeras soportan transparencia.
• Las componentes pesadas soportan repintado incremental
Ejemplo LightweightDemo
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Pintando en SWING

Carlos Testera
• Usa el modelo básico de AWT.
• Añade doble buffering.
• Gestión de borders y delegación de
interfaz de usuario.
• Facilita un RepaintManager.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Doble buffering

Carlos Testera
• Consiste en pintar en memoria primero y enviar
posteriormente a pantalla. Evita el excesivo repintado en
pantalla.
• SWING lo soporta directamente mediante la propiedad
doubleBuffered en javax.swing.JComponent.
public boolean isDoubleBuffered()
public void setDoubleBuffered(boolean o)
• Cuando se activa en una componente, se activa en todos
sus descendientes ligeros.
• Por defecto está asignada a true para todas las
componentes Swing.
• No requiere ningún trabajo adicional por parte del
programador.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Los métodos paint

Carlos Testera
• En Swing el método paint se factoriza en tres
llamadas:
protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)
• El programador debería redefinir
paintComponent en vez de paint().
• Eso soluciona el problema de llamar a
super.paint()
• Ejemplo SwingPaintDemo
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Opacidad

Carlos Testera
• Propiedad de Jcomponent:
public boolean isOpaque()
public void setOpaque(boolean o)
True: el componente pinta todos los bits contenidos en sus
límites.
• False: no garantiza pintar todos sus bits.
• El valor por defecto depende del look and feel IU, pero
es true para la mayoría.
• Permite determinar al sistema si componentes
antecesoras deberán ser repintadas.
• Permite transparencias, pero es más costosa
computacionalmente.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Pintado optimizado

Carlos Testera
• Una componente puede ser solapada por otra
que no es una antecesora suya (una sobrina,
prima o tía)
• Si Swing tuviese que recorrer todo el árbol de
componentes relacionadas con una que debe
ser repientada sería muy ineficiente.
• La propiedad
isOptimizedDrawingEnabled
• le indica a Swing (si es true) que ninguna
componente solapa a la que tiene que ser
repintada.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
La clase Graphics

Carlos Testera
• Contiene métodos para dibujar y rellenar
formas básicas, (líneas, rectángulos, óvalos)
texto e imágenes.
• Contiene atributos que afectan a como se
dibuja y rellenan objetos. (color, pen, relleno,
font, composición, transformación ...)
• La clase Component tiene un método
getGraphics que crea un contexto gráfico para
la componente.
• Ver api de Java o tutorial Java 2D
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Imágenes

Carlos Testera
• Clase para manejar imágenes:
java.awt.image.BufferedImage
• Se pueden crear imágenes desde el
programa, dibujar imágenes en
pantalla, cargar imágenes de ficheros
y salvar imágenes a ficheros.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Carga de imágenes

Carlos Testera
BufferedImage img = null;
try {
img = ImageIO.read(
new File("strawberry.jpg"));
} catch (IOException e) {
}

Formatos admitidos: jpeg, png, gif bmp, wbmp


Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Dibujando una imagen

Carlos Testera
boolean
Graphics.drawImage(Image img,
int x, int y,
ImageObserver observer);
x, y da la posición (esquina sup-izq) de la imagen.
• Observer es para cargar imágenes
asíncronamente. Poner a null.
• DrawImage está sobrecargado con muchos otros
métodos que posibilitan dibujar parte de la
imagen, escalar, cubrir parte, o filtrar la imagen.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Creando y dibujando una imagen

Carlos Testera
• Usar los constructores de BufferedImage.
• Usar los métods de la clase Component
como createImage u otros. Estos métodos
analizan la resolución de la pantalla para un
componente y crear una imagen apropiada.
• Usando createGraphics() de
BufferedImage. Permite usar una imagen
como una superficie de dibujo.
• Java 2D permite acceder a la aceleración
hardware para imágenes en memoria.
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Grabando una imagen

Carlos Testera
try {
BufferedImage bi = getMyImage(); // retrieve image
File outputfile = new File("saved.png");
ImageIO.write(bi, "png", outputfile);
} catch (IOException e) {
...
}
Conrado A. Capdevila
Creando GUIs con JFC/SWING

Adolfo R. de Soto
Carlos Testera
REFERENCIAS
 http://java.sun.com
 The Java tutorial: Swing, Java 2D
 Java 2. Volumes I and II. Prentice Hall
and Sun Microsystems.
 JavaDoc y API Java 5.0
 Painting in AWT and SWING. SDN
network.

También podría gustarte