Programación en Java
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).
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).
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).
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.
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.
Adolfo R. de Soto
Carlos Testera
MVC V
Cuando utilicemos Swing generalmente no habrá
que preocuparse del MVC.
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.
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.
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.
Adolfo R. de Soto
Carlos Testera
LAYOUT MANAGERS IV
El BorderLayout organiza los componentes en
cinco zonas.
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.
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.
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.
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
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.
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.
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
Adolfo R. de Soto
Carlos Testera
EVENTOS XII
INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS
ADAPTADORA ACCESORIOS GENERADOS POR
Adolfo R. de Soto
Carlos Testera
EVENTOS XIII
INTERFAZ CLASE MÉTODOS PARÁMETROS / EVENTOS
ADAPTADORA ACCESORIOS GENERADOS POR
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.
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.
Adolfo R. de Soto
Carlos Testera
ACCIONES III
Para asociar pulsaciones de teclas a las acciones
hay que generar objetos de la clase KeyStroke.
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.
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
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.
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
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
inicialmente no existe.
b
ta
i
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.
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.
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) {
}
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.