presentacion swing(1)
TRANSCRIPT
CREANDO GUIs CON JFC/SWING
Programación en Java
Adolfo Rodríguez de Soto Carlos Testera González Conrado Andreu Capdevila
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
JFC
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Lo que necesitamos
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Antecedentes
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Problemas de AWT
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Swing - AWT
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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)).
Swing – ventajas e inconvenientes
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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
Cosas sueltas
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Hola Mundo en Swing
}
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(); } });
} }
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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).
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
MARCOS II
Veamos el código que genera el marco de la figura.
Como crear un marco
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
MARCOS III
Cuadro de contenido
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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
Modelo
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Controlador
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
¿Es necesario usarlo?
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
FlowLayout
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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).
BorderLayout
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
GridLayout
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Patrón Observer
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Ejemplo Evento “Interesting”
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Funcionamiento
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
EVENTOS IV Ejemplo de clic de un botón
utilizando una clase interna.
Clase principal
Clase para el frame
Clase para el panel que contiene el frame
Clase oyente INTERNA
Registro del oyente
Lo que ocurre al pulsar el botón
Clases internas
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Cases internas anónimas
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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 eventode 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.
Eventos de ventana
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Ojo, ahora ya no se implementa un interfaz, se hereda de una clase.
Por supuesto que con las clases adaptadoras pueden seguir usándose clases anónimas.
Clases adaptadoras
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Eventos semánticos y de bajo nivel
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Eventos de teclado
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Eventos del ratón
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
EVENTOS XI
Tabla resumen
INTERFAZ CLASE ADAPTADORA
MÉTODOS PARÁMETROS / ACCESORIOS
EVENTOS GENERADOS POR
ActionListener actionPerformed ActionEventgetActionCommandgetModifiers
AbstractButtonJComboBoxJTextFieldTimer
AdjustmentListener AdjustmentValueChanged AdjustmentEventgetAdjustablegetAdjustableTypegetValue
JScrollBar
ItemListener itemStateChanged ItemEventgetItemgetItemSelectablegetStateChange
AbstractButtonJComboBox
TextListener textValueChanged TextEvent
INTERFAZ CLASE ADAPTADORA
MÉTODOS PARÁMETROS / ACCESORIOS
EVENTOS GENERADOS POR
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
EVENTOS XIIINTERFAZ CLASE
ADAPTADORAMÉTODOS PARÁMETROS /
ACCESORIOSEVENTOS
GENERADOS POR
ContainerListener ContainerAdapter componentAddedcomponentRemoved
ContainerEventgetChildgetContainer
Container
FocusListener FocusAdapter focusGainedfocusLost
FocusEventisTemporary
Component
KeyListener KeyAdapter keyPressedkeyReleasedkeyTyped
KeyEventgetKeyChargetKeyCodegetKeyModifiersTextgetKeyTextisActionkey
Component
INTERFAZ CLASE ADAPTADORA
MÉTODOS PARÁMETROS / ACCESORIOS
EVENTOS GENERADOS POR
Tabla resumen
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
EVENTOS XIII
Tabla resumen
INTERFAZ CLASE ADAPTADORA
MÉTODOS PARÁMETROS / ACCESORIOS
EVENTOS GENERADOS POR
MouseMotionListener MouseMotionAdapter mouseDraggedmouseMoved
MouseEvent Component
MouseWheelListener mouseWheelMoved MouseWheelEventgetWheelRotationgetScrollAmount
Component
WindowListener WindowAdapter windowClosingwindowOpenedwindowIconifiedwindowDeiconifiedwindowClosedwindowActivatedwindowDeactivated
WindowEventgetWindow
Window
WindowFocusListener windowGainedFocuswindowLostFocus
WindowEventgetOppositeWindow
Window
INTERFAZ CLASE ADAPTADORA
MÉTODOS PARÁMETROS / ACCESORIOS
EVENTOS GENERADOS POR
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Métodos y pares nombre/valor
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Pulsaciones de teclas
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Mapas
Esto tiene que ser un “Object”. Usamos una cadena porque es lo más cómodo. Si se pone a null rompemos el enlace.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
ACCIONES V
Ejemplo
La clase principal y el marco que contiene el panel que tiene los botones a los que se asocian las acciones.
Este ejemplo muestra un panel con tres botones que cambian el color de dicho panel. Utilizamos acciones que nos ayudan a mostrar tooltips, a cambiar el color con los botones o con teclas.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
ACCIONES VI
Ejemplo
Mapa de entrada
Mapa de acción
Clase acción que establece los nombre, iconos y descripciones cortas. Además, con e l actionPerformed establecemos lo que realiza la acción (cambiar el color del panel).
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Introducción
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Entrada de texto
Campo de texto
Área de texto
Campo de contraseña
Etiqueta
JEditorPane
JTextPane
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
COMPONENTES SWING III Cuando tenemos que realizar una selección, dependiendo de
la necesidad podremos usar alguno de estos componentes: Casillas de verificación (JCheckBox): se usan para obtener una
entrada de tipo “sí” o “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 inicialmente no existe.
Existen otros como listas (JList), deslizadores (JSlider) y spinners (JSpinner).
SeleccionesEdi
tabl
e
No ed
itabl
e
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Menús
JMenuBar
JMenu
JMenuItem
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Cuadros de diálogo
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Cuadros de diálogo
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
COMPONENTES SWING VIII
Los selectores de ficheros y de colores son muy versátiles y con multitud de opciones. Consultar la API.
Cuadros de diálogo
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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
Cuadros de diálogo
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Mostrar datos
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.
Otros componentes
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Pintando en AWT y SWING
• Qué es y cómo se pinta• Callbacks• Clases importantes:
– Graphics
• Api Java 2D
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Pintar en un sistema de ventanas
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Peticiones del sistema: 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
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Peticiones de aplicación: 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
El método update
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Componentes pesadas y ligera
• 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
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Pintando en SWING
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Doble buffering
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Los métodos paint
• 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
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Opacidad
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Pintado optimizado
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
La clase Graphics
• 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
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Imágenes
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Carga de imágenes
BufferedImage img = null;
try {
img = ImageIO.read(
new File("strawberry.jpg"));
} catch (IOException e) {
}
Formatos admitidos: jpeg, png, gif bmp, wbmp
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Dibujando una imagen
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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Creando y dibujando una imagen
• 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.
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
Grabando una imagen
try {
BufferedImage bi = getMyImage(); // retrieve image
File outputfile = new File("saved.png");
ImageIO.write(bi, "png", outputfile);
} catch (IOException e) {
...
}
Creando GUIs con JFC/SWING
Adol
fo R
. de
Soto
Car
los
Test
era
Con
rado A
. Cap
dev
ila
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.