1. 1
Elementos de Programación OO
con el Lenguaje Java
Manejo de Eventos en las
Interfaces Gráficas de Usuario
(GUIs)
Con base a los conceptos del curso de Sun Microsystems
“Lenguaje de Programación Java”
(Java Programming Language. SL275).
Luis Ernesto Rubio.
2. 2
Modelo de Delegación de Eventos
Un evento de define como una acción que está provocada por el usuario y que
supone un cambio de estado en algún componente, pulsación de un botón del
ratón o bien la pulsación de una tecla.
Los eventos permiten llevar a cabo la funcionalidad de las aplicaciones
basadas en GUI.
Por ejemplo el programa GUIapp.java de tu curso funciona bajo un esquema
lógico denominado Modelo de Delegación de Eventos.
Las principales características que han originado el modelo de delegación para
manejo de eventos en el AWT, son:
Que sea simple y fácil de aprender
Que soporte una clara separación entre el código de la aplicación y el
código del interfaz
Que facilite la creación de robustos controladores de eventos, con
menos posibilidad de generación de errores (chequeo más potente en
tiempo de compilación)
Suficientemente flexible para permitir el flujo y propagación de eventos
Para herramientas visuales, permitir en tiempo de ejecución ver cómo se
generan estos eventos y quien lo hace
Los eventos están organizados en jerarquías de clases de eventos.
El nuevo modelo hace uso de fuentes de eventos (Source) y auditores,
oyentes o receptores de eventos (Listener).
3. 3
Una fuente de eventos es un objeto que tiene la capacidad de detectar eventos
y notificar a los receptores de eventos que se han producido esos eventos.
Aunque el programador puede establecer el entorno en que se producen esas
notificaciones, siempre hay un escenario por defecto.
Un objeto receptor (oyente o auditor) de eventos es una clase (o una subclase
de una clase) que implementa un interfaz auditor específico. Hay definidos un
determinado número de interfaces auditoras, donde cada interfaz declara los
métodos adecuados al tratamiento de los eventos de su clase, llamados
métodos gestores (manejadores) de eventos (event handlers).
Luego, hay un emparejamiento natural entre clases de eventos y definiciones
de interfaces. Por ejemplo, hay una clase de eventos de ratón que incluye
muchos de los eventos asociados con las acciones del ratón, y hay un interfaz
que se utiliza para definir los receptores de esos eventos.
Un objeto auditor puede estar registrado con un objeto fuente para ser
notificado de la ocurrencia de todos los eventos de la clase para los que el
objeto receptor está diseñado.
Una vez que el objeto auditor está registrado para ser notificado de esos
eventos, el suceso de un evento en esta clase automáticamente invocará al
método sobreescrito del objeto receptor.
El código en el método sobreescrito debe estar diseñado por el programador
para realizar las acciones específicas que desee cuando suceda el evento.
Algunas clases de eventos, como los de ratón, involucran a un determinado
conjunto de eventos diferentes.
Una clase receptor que implemente el interfaz que recoja estos eventos debe
sobreescribir todos los métodos declarados en el interfaz.
Para prevenir esto, de forma que no sea tan tedioso y no haya que
sobreescribir métodos que no se van a utilizar, se han definido un conjunto de
clases intermedias, conocida como clases Adaptadoras (Adapter).
Estas clases Adaptadores implementan los interfaces receptor y sobreescriben
(override) todos los métodos del interfaz con métodos vacíos. Una clase
receptor puede estar definida como clase que extiende una clase Adapter en
lugar de una clase que implemente el interfaz.
Cuando se hace esto, la clase receptor solamente necesita sobreescribir
aquellos métodos que sean de interés para la aplicación, porque todos los otros
métodos serán resueltos por la clase Adapter
Uno de los objetos receptor que se implementan con mayor frecuencia son los
de la interfaz WindowListener en el manejo de ventanas, lo que haria
necesario sobreescribir los seis métodos de la interfaz.
4. 4
Por lo que la otra clase receptor que se extiende es la clase WindowAdapter
en vez de implementar la interfaz WindowListener.
La clase WindowAdapter sobrescribe los seis métodos de la interfaz con
métodos vacíos, por lo que la clase receptor no necesita sobreescribir esos
seis métodos solo el que necesita.
Gestión de Eventos
El paquete java.awt.event es el que contiene la mayor parte de las clases e
interfaces de eventos.
https://www.safaribooksonline.com/library/view/java-awt-reference/9781565922402/07_chapter-04.html
El modelo de delegación de eventos es un concepto que trabaja de la siguiente
manera:
5. 5
http://www.redeszone.net/content/uploads/curso_java_GUIX_generacionEventos.jpg
Una fuente genera un evento y lo envía a uno a más oyentes o auditores, que
han estado simplemente esperando hasta que reciben ese evento y una vez
recibido lo procesan y lo devuelven.
Una fuente es un objeto que genera un evento. Esto ocurre cuando cambia de
alguna manera el estado interno de ese objeto. Las fuentes pueden generar
más de un tipo de eventos.
Una fuente tiene que ir acompañada de auditores para que estos reciban las
notificaciones sobre el tipo específico de evento, cada tipo de evento tiene su
propio método de registro. La forma general es:
Por ejemplo el método que registra o acompaña a un auditor de evento de
teclado es addKeyListener( ). Cuando ocurre un evento, se notifica a todos los
auditores registrados, que reciben una copia del objeto evento. Esto es lo que
se conoce como multicasting del evento.
Una fuente también puede proporcionar un método que permita a un auditor
eliminar un registro en un tipo específico de evento y la forma general es:
Public void removeTypeListener(TypeListener el);
Aquí Type es el nombre del evento y el es una referencia al auditor. Por
ejemplo para borrar un auditor del teclado se llamaría removeKeyListener( ).
6. 6
Fuentes de Eventos
Todas las fuentes de eventos del AWT soportan el multienvío a receptores.
Esto significa que se pueden añadir o quitar múltiples receptores de una sola
fuente; en otras palabras, la notificación de que se ha producido un mismo
evento se puede enviar a uno o más objetos receptores simultáneamente.
El API de Java no garantiza el orden en que se enviarán los eventos a los
receptores que están registrados en un objeto fuente, para ser informados de
esos eventos.
En caso de que el orden en que se distribuyen los eventos sea un factor
importante en el programa, se deberían encadenar los receptores de un solo
objeto receptor registrado sobre el objeto fuente; el hecho de que los datos del
evento estén encapsulados en un solo objeto hace que la propagación del
evento sea extremadamente simple.
Como en el caso de los receptores, se puede hacer una distinción entre los
eventos de bajo nivel y los eventos de tipo semántico. Las fuentes de eventos
de bajo nivel serán las clases de elementos o componentes visuales del
interfaz gráfico (botones, barras de desplazamiento, cajas de selección, etc.),
porque cada componente de la pantalla generará sus eventos específicos.
El JDK permite registrar receptores sobre fuentes de eventos de los siguientes
tipos:
java.awt.Component
addComponentListener
addFocusListener
addKeyListener
addMouseListener
addMouseMotionListener
java.awt.Container
addContainerListener
java.awt.Dialog
addWindowListener
java.awt.Frame
addWindowListener
Para determinar todos los tipos de eventos que se pueden comunicar desde un
objeto fuente a un receptor, hay que tener en cuenta la herencia.
7. 7
Por ejemplo, un objeto puede detectar eventos del ratón sobre un objeto Frame
y notificar a un objeto MouseListener de la ocurrencia de estos eventos,
aunque en la lista anterior no se muestre un MouseListener sobre un Frame.
Esto es posible porque un objeto Frame extiende indirectamente la clase
Component y, MouseListener está definida en la clase Component.
Los receptores de eventos que se pueden registrar de tipo semántico sobre
objetos fuentes, generadores de eventos, en el JDK son:
java.awt.Button
addActionListener
java.awt.Choice
addItemListener
java.awt.Checkbox
addItemListener
java.awt.CheckboxMenuItem
addItemListener
java.awt.List
addActionListener
addItemListener
java.awt.MenuItem
addActionListener
java.awt.Scrollbar
addAdjustmentListener
java.awt.TextArea
addTextListener
java.awt.TextField
addActionListener
addTextListener
8. 8
Ejemplos de componentes que pueden generar eventos
Origen de
evento
Descripción
Button Genera eventos de acción (ActionEvent) cuando se
presiona el botón.
Checkbox Genera eventos de elementos (ItemEvent) cuando se
selecciona o deselecciona un checkbox.
Choice Genera eventos de elementos cuando se cambia de opción
choice.
List Genera eventos de acción cuando se hace doble click sobre
un elemento, genera eventos de elemento cuando se
selecciona o deselecciona un elemento.
Menu Item Generá eventos de acción cuando se selecciona un
elemento de menú; genera eventos de lemento cuando se
selecciona o se deselecciona un elemento de un menú de
opciones.
Scrollbar Genera eventos de ajuste (AdjustmentEvent) cuando se
manipula el scrollbar.
Text
components
Genera eventos de texto (TextEvent) cuando el usuario
introduce un carácter.
Window Genera eventos de ventana (WindowEvent) cuando una
ventana se activa, se cierra, se desactiva, se minimiza, se
maximiza, se abre o se sale de ella.
Public void addTypeListener(TypeListener el)
http://www3.ntu.edu.sg/home/ehchua/programming/java/j4a_gui.html
9. 9
Por ejemplo el programa GUIapp de tu curso, contiene diversas fuentes de
eventos:
El objeto referido
como space2 de la
clase ImagePanel es
una fuente de evento.
El método
addMouseListener
permite registrar a su
correspondiente
oyente o auditor.
El objeto referido
como space2 de la
clase ImagePanel es
una fuente de evento.
El método
addMouseListener
permite registrar a su
correspondiente
oyente o auditor.
El objeto referido
como frameGUI de la
clase FrameGUI es
una fuente de evento.
El método
addWindowListener
permite registrar a su
correspondiente
oyente o auditor.
10. 10
Este código indica que
los objetos de la clase
InternalButton serán
fuentes de evento.
El método
addActionListener
permite registrar a su
correspondiente
oyente o auditor.
Este código indica que
los objetos de la clase
InternalButton serán
fuentes de evento.
El método
addActionListener
permite registrar a su
correspondiente
oyente o auditor.
Las clases
WalkButton y
FlyButton
heredan de la súper
clase InternalButton y
por ello permitirán
crear objetos fuentes
de evento..
Las sub clases
WalkButton y
FlyButton
heredan de la súper
clase InternalButton y
por ello permitirán
crear objetos fuentes
de evento..
Aquí se definen las
referencias a objetos
de las clases
WalkButton y
FlyButton
Las objetos referidos
como: walkButton y
flyButton
son objetos fuentes
de evento.
11. 11
Auditores de eventos.
Un auditor es un objeto que es avisado cuando ocurre un evento.
Tiene dos requisitos principales:
Primero tiene que ser registrado o ir acompañado por una o más fuentes para
recibir notificaciones sobre los tipos específicos de eventos.
Segundo, tiene que implementar métodos para recibir y procesar notificaciones
(objetos evento). Estos métodos reciben el nombre de gestores de eventos
(event handlers).
Es en los métodos gestores de eventos, donde el programador escribe las
instrucciones para que la aplicación realice las acciones requeridas, es decir,
los gestores de eventos, alojan la lógica de programación de la GUI.
Clases de eventos principales en java.awt.event
Clase de evento Descripción
ActionEvent Se genera cuando se presiona un botón, se hace doble
clic en un elemento de una lista, o se selecciona un
elemento de tipo menú.
AdjustmentEvent Se genera cuando se manipula un scrollbar.
ComponentEvent Se genera cuando un componente se oculta, se
mueve, se cambia de tamaño o se hace visible.
ContainerEvent Se genera cuando se añade o se elimina un
componente de un contenedor.
FocusEvent Se genera cuando un componente gana o pierde el
foco.
InputEvent Superclase abstracta de cualquier clase de evento de
entrada de componente.
ItemEvent Se genera cuando se hace click en un checkbox o en
un elemento de una lista; tambien ocurre cuando se
hace una selección en una opción choice o cuando se
selecciona o deselecciona un elemento de un menú de
opciones.
KeyEvent Se genera cuando se recibe una entrada desde el
teclado.
MouseEvent Se genera cuando el ratón se arrastra, se mueve, se
hace clic, se presiona, o se libera; también se genera
cuando el ratón entra o sale de un componente.
TextEvent Se genera cuando se cambia el valor de un área de
texto o un campo de texto
WindowEvent Se genera cuando una ventana se activa, se cierra, se
desactiva, se minimiza, se maximiza, se abre, o se
sale de ella.
12. 12
http://www.redeszone.net/2011/11/21/curso-java-gui-volumen-x-gestion-de-eventos/
En el programa GUIapp.java de tu curso, asociados a cada fuente de evento,
son generados los objetos auditores responsables de las acciones de “volar,
caminar, o escalar”, que dan efectos a las imágenes en la aplicación:
El objeto generado a
partir de la clase
MouseStretch es un
objeto auditor, oyente
o recepetor
(Listener) de eventos.
13. 13
La clase
MouseStretch permite
crear objetos auditor,
oyente o recepetor
(Listener) de eventos.
Esta clase define al
método gestor de
eventos:
mousePressed que
permite escalar una
imagen del programa
GUIapp.java
El método gestor de
eventos:
mousePressed recibe
notificaciones, es
decir, captura objetos
de la clase
MouseEvent.
El objeto generado a
partir de la clase
WindowAdapter es
un objeto auditor,
oyente o recepetor
(Listener) de eventos.
.
El método gestor de eventos:
windowClosing recibe notificaciones,
es decir, captura objetos de la clase
WindowEvent, y en este caso, contiene
las instrucciones para cerrar la ventana
de la aplicación al oprimir el botón X.
14. 14
Las clases
WalkButton y
FlyButton
heredan de la súper
clase InternalButton y
por ello permitirán
crear objetos fuentes
de evento..
Las sub clases
WalkButton y
FlyButton
redefinen (override) al
método pushAction de
su súper clase
InternalButton, para
darle efectos a la
aplicación:
Este código indica que
los objetos de la clase
InternalButton serán
fuentes de evento.
El método
addActionListener
permite registrar a su
correspondiente
oyente o auditor.
La programación de la
clase InternalButton
hace que los objetos
creados a partir de ella
misma (this), operen
como objeto auditor,
oyente o recepetor
(Listener) de eventos.
El método gestor de eventos:
actionPerformed recibe
notificaciones, es decir, captura
objetos de la clase ActionEvent, y en
este caso, invoca al método
pushAction, diseñado para ser
sustitudo (override) en subclases.
15. 15
Interfaces Auditoras
Recuérdese objeto receptor (oyente o auditor) de eventos es una clase (o una
subclase de una clase) que implementa un interfaz auditor específico.
Por ello se han definido un determinado número de interfaces de auditor, donde
cada interfaz declara los métodos adecuados al tratamiento de los eventos de
su clase.
Entre las interfaces de auditor que más se utilizan están:
ActionListener
La interfaz tiene que definir el método:
void actionPerformed(ActionEvent e) el cual se invoca cuando ocurre un
evento de acción.
Esta interface está documentada en la API Java, en el paquete java.awt.event
como a continuación se ilustra:
16. 16
Por ejemplo, en el programa GUIapp.java de tu curso, se implementa esta
interface:
AdjustmentListener
La interfaz tiene que definir el método:
void adjustmentValueChanged(AdjustmetEvent ae) el cual se invoca cuando
ocurre un evento de ajuste.
ComponentListener
La interfaz tiene que definir los siguientes métodos:
void componentResized(ComponentEvent ce)
void componentMoved(ComponentEvent ce)
void componentShown(ComponentEvent ce)
void componentHiden(ComponentEvent ce)
Se invocan cuando a un componente se le cambia de tamaño, se mueve, se
muestra o se oculta.
ContainerListener
La interfaz tiene que definir los siguientes métodos:
void componentAdded(ContainerEvet ce)
void componentRemoved(ContainerEvet ce)
Se invocan cuando se añade un componente a un contenedor y cuando se
borra un componente de un contenedor.
FocusListener
La interfaz tiene que definir los siguientes métodos:
void focusGained(FocusEvent fe)
void focusLost(FocusEvent fe)
Se invocan cuando se gana el foco o se pierde el foco
Aquí se indica que la
clase InternalButton
implementa a la
intreface
ActionListener
Para implementar la intreface
ActionListener aquí se sobrescribe o
sustituye (override) el método gestor
de eventos: actionPerformed.
17. 17
ItemListener
La interfaz tiene que definir el siguiente método:
void itemStateChanged(ItemEvent ie)
Se invoca cuando cambia el estado de un elemento
KeyListener
La interfaz tiene que definir los siguientes métodos:
void keyPressed(KeyEvent ke)
void keyReleased(KeyEvent ke)
void keyTyped(KeyEvent ke)
Se invocan cuando se presiona, libera una tecla y cuando se introduce un
carácter.
MouseListener
La interfaz tiene que definir los siguientes métodos:
void mouseClicked(MouseEvent me)
void mouseEntered(MouseEvent me)
void mouseExited(MouseEvent me)
void mousePressed(MouseEvent me)
void mouseReleased(MouseEvent me)
Se invocan cuando se presiona, cuando entra a un componente, cuando sale,
cuando se presiona y se libera el ratón.
MouseMotionListener
La interfaz tiene que definir los siguientes métodos:
void mouseDragged(MouseEvent me)
void mouseMoved(MouseEvent me)
Se invocan cuando se arrastra y se mueve el ratón.
TextListener
La interfaz tiene que definir el siguiente método:
void textChanged(TextEvent te)
Se invoca cuando ha ocurrido un cambio en un área de texto o en un campo de
texto.
WindowListener
La interfaz tiene que definir los siguientes métodos:
void windowActivated(WindowEvent we) activa
void windowDeactivated(WindowEvent we) desactiva
void windowClosed(WindowEvent we) cierra
void windowClosing(WindowEvent we) petición de cerrar
void windowDeiconfied(WindowEvent we)
void windowIconfied(WindowEvent we) minimiza
void windowOpened(WindowEvent we) abre
Se invocan cuando se activa, se desactiva, se cierra una ventana, se esta
cerrando una ventana, se minimiza a un icono, cuando se abre a partir de un
icono y cuando se abre una ventana.
18. 18
Adaptadores
Muchos interfaces EventListener están diseñados para recibir múltiples clases
de eventos, por ejemplo, el interfaz MouseListener puede recibir eventos de
pulsación de botón, al soltar el botón, a la recepción del cursor, etc.
El interfaz declara un método para cada uno de estos subtipos. Cuando se
implementa un interfaz, es necesario redefinir todos los métodos que se
declaran en ese interfaz, incluso aunque se haga con métodos vacíos. En la
mayoría de las ocasiones, no es necesario redefinir todos los métodos
declarados en el interfaz porque no son útiles para la aplicación.
Por ello, el AWT proporciona un conjunto de clases abstractas adaptadores
(Adapter) que coinciden con las interfaces. Cada clase adaptador implementa
un interfaz y redefine todos los métodos declarados por el interfaz con métodos
vacíos, con lo cual se satisface ya el requerimiento de la redefinición de todos
los métodos.
https://www.safaribooksonline.com/library/view/java-awt-reference/9781565922402/07_chapter-04.html
Se pueden definir clases Auditoras u Oyentes (para crear objetos auditores)
extendiendo clases adaptadores, en vez de implementar el interfaz receptor
correspondiente. Esto proporciona libertad al programador para redefinir
19. 19
solamente aquellos métodos del interfaz que intervienen en la aplicación que
desarrolla.
De nuevo, hay que recordar que todos los métodos declarados en un interfaz
corresponden a los tipos de eventos individuales de la clase de eventos
correspondiente, y que el objeto Fuente notifica al Receptor la ocurrencia de un
evento de un tipo determinado invocando al método redefinido del interfaz.
Las clases Adaptadores que se definen en el JDK son las que se indican a
continuación:
java.awt.ComponentAdapter
java.awt.FocusAdapter
java.awt.KeyAdapter
java.awt.MouseAdapter
java.awt.MouseMotionAdapter
java.awt.WindowAdapter
Dentro del programa GUIapp.java de tu curso, se emplea esta la clase
WindowAdapter, para sobreescribir (override) el método gestor de eventos
windowClosing:
20. 20
Clases adaptadoras que se usan cuando no se requieren definir todos los
eventos de un elemento y son:
Clase Adaptadora Interfaz auditora
ComponentAdapter ComponentListen
ContainerAdapter ContainerListen
FocusAdapter FocusListener
KeyAdapter KeyListener
MouseAdapter MouseListener
MouseMotionAdapter MouseMotionListener
WindowAdapter WindowListener
Aquí se ilustra cómo
se emplea la clase
Adapatador:
WindowAdapter para
redefinir (override) al
método gestor de
eventos:
windowClosing