Post on 10-Oct-2014
transcript
1
Interfaces Gráficas de Usuario
Introducción Programación basada en eventos
POO - EPS - UAM 2
Desarrollo de interfaces de usuario
Generalización del ⇒ Importancia creciente uso del ordenador de la facilidad de uso
La interfaz de usuario no añade funcionalidad a una
aplicación Sin embargo es un aspecto decisivo en el éxito de un producto
Desarrollo muy costoso Normalmente, 50% del esfuerzo se dedica al desarrollo de la interfaz
Herramientas que ayudan al desarrollo de interfaces
2
POO - EPS - UAM 3
Herramientas: software para el desarrollo de interfaces (I)
Basadas en una categorización, modelización de formas de
interfaz
Facilitan el desarrollo
Proporcionan parte del código
Ayudan a organizar/estructurar el código escrito por el programador
Limitan (condicionan) las características de las interfaces
que se pueden desarrollar
Alternativa: pintar en la pantalla, seguir movimiento e input
del ratón
POO - EPS - UAM 4
Herramientas: software para el desarrollo de interfaces (II)
Sistemas de ventanas / toolkits: Microsoft Windows, X-Window + Motif, Mac/OS, OS/2 PM, etc.
Interfaz al sistema operativo
Librería para el desarrollo de interfaces gráficas
Bajo nivel, máxima expresividad, dificultad de uso
Librerías de objetos: Java AWT, Swing, Microsoft MFC, Borland OWL, etc. Código más fácil de producir y mantener
Normalmente acompañadas de un constructor gráfico de interfaces
Constructores gráficos de interfaces: MS-Visual Studio, Netbeans, etc. Programación visual
Gran facilidad de uso, utilidad limitada
Otras herramientas avanzadas: campo de investigación
3
POO - EPS - UAM 5
Nivel de las herramientas
Facilidad de desarrollo
Rango de interfaces generadas
POO - EPS - UAM 6
¿Qué tienen que ver las interfaces con POO?
El usuario ve objetos en la pantalla El usuario puede manipular los objetos Los objetos tienen comportamiento propio: distintas
formas de responder a una acción del usuario: Por ejemplo: pulsar el ratón sobre un objeto gráfico
4
POO - EPS - UAM 7
¿Qué tienen que ver las interfaces con POO?
No existe una función "pulsar ratón" que sepa lo que debe hacer según el elemento sobre el que actúa
Cada elemento gráfico contiene la funcionalidad correspondiente a la acción de pulsar el ratón (la responsabilidad reside en el objeto)
Programación basada en eventos (mensajes)
POO - EPS - UAM 8
Un nuevo modelo de programación
Programación basada en eventos
Main
f (x)
f(arg)
g()
g()
control, flujo ejecución
Main
f(arg)
g()
ejecuta
pregunta / respuesta
termina
no hay orden estrictro
5
POO - EPS - UAM 9
Programación basada en eventos (I)
El modo de operación de una interfaz de usuario no se ajusta
a un control de flujo estrictamente secuencial
El usuario tiene un alto grado de libertad en todo momento:
normalmente dispone de un amplio conjunto de acciones
posibles
Es muy difícil representar todos los caminos posibles con un
modelo de programación tradicional
POO - EPS - UAM 10
Programación basada en eventos (II)
Modelo utilizado en las interfaces de usuario actuales basadas en ventanas
La iniciativa no la lleva el programa sino el usuario El programa se divide en subprogramas asociados a ventanas o
componentes gráficas Las componentes están a la espera de las acciones del usuario Las acciones del usuario generan eventos que se acumulan en una cola El sistema de eventos extrae eventos de la cola y los envía a los
programas Los programas procesan los eventos recibidos respondiendo según el
tipo de evento Cada tipo de componente se caracteriza por una forma propia de
respuesta a los eventos
6
POO - EPS - UAM 11
evento 1
evento 2
...
event n
...
Despachador
Programación basada en eventos (III)
eventos (acciones) de usuario
Interfaz
Cola de eventos
Componentes de la interfaz
mensajes
POO - EPS - UAM 12
La base: el sistema de ventanas Funciones de dibujo de primitivas gráficas: formas geométricas, texto, etc.
Generación de mensajes (eventos)
La ventana recibe eventos sin diferenciar
Respuesta de ventanas a eventos:
Repintar
Cambiar apariencia y repintar
Ejecutar una función (acción)
Usuario Acción del usuario Sistema
de ventanas (p.e. Windows)
Mensaje
Ventana
7
POO - EPS - UAM 13
Ventanas
Área rectangular de la pantalla en la que tiene lugar una
interacción (intercambio de input y output) con el usuario
Recibe input del usuario (ratón y teclado), muestra output
por intermedio del sistema de ventanas, mediante envío de
mensajes
Ventana marco: ventana principal asociada a una aplicación
Ventanas hijas: subáreas que procesan sus propios eventos
POO - EPS - UAM 14
Ejemplo de programa con Java AWT
import java.awt.*; import java.awt.event.*;
public class Ventana extends Frame implements WindowListener { public static void main (String args[]) { Ventana v = new Ventana (); v.setSize (300, 200); v.addWindowListener (v); v.setVisible (true); } public void paint (Graphics g) { g.drawString("Hola a todos!", 100, 100); } public void windowClosing (WindowEvent e) { dispose (); } public void windowClosed (WindowEvent e) {} public void windowActivated (WindowEvent e) {} public void windowDeactivated (WindowEvent e) {} public void windowIconified (WindowEvent e) {} public void windowDeiconified (WindowEvent e) {} public void windowOpened (WindowEvent e) {} }
8
POO - EPS - UAM 15
Resultado...
POO - EPS - UAM 16
Java Abstract Window Toolkit (AWT)
Las componentes son objetos A cada tipo de evento corresponde un
método de la componente La respuesta a eventos se define
implementando métodos
Acción del usuario
Sistema de ventanas
Mensaje
Componentes AWT
Sistema AWT
Invocación a método
Usuario
9
POO - EPS - UAM 17
Interfaces orientadas a objetos
Objetos gráficos con: Estado: variables de la clase
Propiedades visuales: color, posición, tamaño Valores visualizados: string, bitmap, etc. Valores internos
Presencia en la pantalla: método paint () Mantiene un dibujo en la pantalla Depende del estado: controlar la apariencia a través del estado
Comportamiento: respuesta a eventos Cambios de estado o apariencia Ejecución de funciones (acción) Emisión de eventos
POO - EPS - UAM 18
Objetos gráficos
Objetos del programa
Presentación en la pantalla
10
Abstract Window Toolkit (AWT)
1ra. Parte: Introducción
POO - EPS - UAM 20
La biblioteca AWT: java.awt, java.awt.event
Componentes Componentes predefinidas Agregación de componentes Las interfaces se dibujan a sí mismas: funciones de
dibujo Creación de nuevas componentes
Interacción con el usuario: gestión de eventos Emisión de eventos Recepción y procesamiento de eventos
Layout de componentes
11
POO - EPS - UAM 21
Anatomía de un programa basado en GUI
Componer interfaces con las clases predefinidas La clase Container, adición de subcomponentes Control de la apariencia de las componentes manipulando su estado
Definir la disposición de las partes de un contenedor Posiciones absolutas Layout managers
Gestionar los eventos: modelo emisor / receptor Eventos de acción generados por las clases predefinidas Gestión directa del input del usuario
Definir componentes personalizadas La clase Canvas Utilización de las funciones de dibujo
POO - EPS - UAM 22
Ejemplo: editor de texto
12
POO - EPS - UAM 23
Componentes predefinidas
Frame
TextField
Button
TextArea
Label
POO - EPS - UAM 24
Disposición de las componentes
Alto fijo
Llenar espacio disponible hasta
borde inferior de la ventana
Ancho ocupa toda la ventana
Ancho fijo, centrado
Ancho ocupa toda la ventana
13
POO - EPS - UAM 25
Aspectos interactivos
Editar texto del campo
Cerrar ventana
Editar texto multilínea
Leer el fichero indicado en el campo de texto,
asignar como string del área de texto
Escribir string del área de texto en el fichero indicado en el campo de texto
POO - EPS - UAM 26
Ejemplo: código (I) import java.awt.*; import java.awt.event.*; import java.io.*;
public class Editor extends Frame implements WindowListener, ActionListener { TextField fileName; TextArea fileBuffer; Button load, save, quit;
Editor () { setLayout (null);
Label label = new Label ("File Name: "); label.setBounds (10, 30, 300, 20); add (label);
fileName = new TextField (); fileName.setBounds (10, 50, 290, 20); add (fileName); ...
14
POO - EPS - UAM 27
Ejemplo: código (II) load = new Button ("Load"); load.setBounds (40, 80, 60, 20); add (load);
save = new Button ("Save"); save.setBounds (120, 80, 60, 20); add (save);
quit = new Button ("Quit"); quit.setBounds (200, 80, 60, 20); add (quit);
fileBuffer = new TextArea (); fileBuffer.setBounds (10, 110, 300, 200); add (fileBuffer);
this.addWindowListener (this); load.addActionListener (this); save.addActionListener (this); quit.addActionListener (this); } // Fin del constructor
POO - EPS - UAM 28
Ejemplo: código (III)
... public void actionPerformed (ActionEvent e) { String command = e.getActionCommand (); if (command.equals ("Quit")) dispose (); else if (command.equals ("Load")) load (); else if (command.equals ("Save")) save (); }
public void windowClosing (WindowEvent e) { dispose (); } public void windowActivated (WindowEvent e) {} public void windowClosed (WindowEvent e) {} public void windowDeactivated (WindowEvent e) {} public void windowDeiconified (WindowEvent e) {} public void windowIconified (WindowEvent e) {} public void windowOpened (WindowEvent e) {} ...
15
POO - EPS - UAM 29
Ejemplo: código (IV)
... void load () { try { RandomAccessFile input = new RandomAccessFile (fileName.getText (), "r"); byte buffer[] = new byte [(int) input.length ()]; input.read (buffer); input.close (); fileBuffer.setText (new String (buffer)); } catch (IOException e) { System.out.println (e); } } void save () { try { FileWriter output = new FileWriter (fileName.getText ()); output.write (fileBuffer.getText ()); output.close (); } catch (IOException e) { System.out.println (e); } } ...
POO - EPS - UAM 30
Ejemplo: código (V)
... public static void main (String args[]) { Editor edit = new Editor (); edit.setSize (320, 320); edit.setVisible (true); } } // Fin clase Editor
16
POO - EPS - UAM 31
Resumen
Programar un IU para una aplicación en Java involucra: Composición Layout Eventos Paint
Abstract Window Toolkit (AWT)
2da. Parte: Componentes
17
POO - EPS - UAM 33
Componentes AWT predefinidas
POO - EPS - UAM 34
Jerarquía de componentes AWT: el package java.awt
Jerarquía = Herencia
18
POO - EPS - UAM 35
Jerarquía de componentes AWT: el package java.awt
Jerarquía = Herencia
POO - EPS - UAM 36
Uso componentes AWT: ejemplo
19
POO - EPS - UAM 37
Clases en el ejemplo
Label
TextField
ScrollBar
Converter Frame
Choice
ConversionPanel
layout manager: GridBagLayout
POO - EPS - UAM 38
Código del ejemplo
import java.awt.*; import java.awt.event.*; import java.util.*; import java.applet.Applet;
public class Converter extends Frame { ConversionPanel metricPanel, usaPanel; Unit[] metricDistances = new Unit[3]; Unit[] usaDistances = new Unit[4];
public void init() { // Use a GridLayout with 2 rows, as many columns as necessary, // and 5 pixels of padding around all edges of each cell. setLayout(new GridLayout(2,0,5,5)); ....
Creación de la
ventana
20
POO - EPS - UAM 39
Código del ejemplo // Create Unit objects for metric distances, and then // instantiate a ConversionPanel with these Units. metricDistances[0] = new Unit("Centimeters", 0.01); metricDistances[1] = new Unit("Meters", 1.0); metricDistances[2] = new Unit("Kilometers", 1000.0); metricPanel = new ConversionPanel(this, "Metric System", metricDistances);
//Create Unit objects for U.S. distances, and then //instantiate a ConversionPanel with these Units. usaDistances[0] = new Unit("Inches", 0.0254); usaDistances[1] = new Unit("Feet", 0.305); usaDistances[2] = new Unit("Yards", 0.914); usaDistances[3] = new Unit("Miles", 1613.0); usaPanel = new ConversionPanel(this, "U.S. System", usaDistances);
//Add both ConversionPanels to the Converter. add(metricPanel); add(usaPanel); }
Inicialización
POO - EPS - UAM 40
Código del ejemplo
/** * Does the conversion from metric to U.S., or vice versa, and * updates the appropriate ConversionPanel. */
void convert(ConversionPanel from) { ConversionPanel to;
if (from == metricPanel) to = usaPanel; else to = metricPanel;
double multiplier = from.getMultiplier() / to.getMultiplier(); to.setValue(multiplier * from.getValue()); }
funcionalidad
21
POO - EPS - UAM 41
Código del ejemplo
/** Draws a box around this panel. */ public void paint(Graphics g) { Dimension d = getSize(); g.drawRect(0,0, d.width - 1, d.height - 1); }
/** * Puts a little breathing space between * the panel and its contents, which lets us draw a box * in the paint() method. */ public Insets getInsets() { return new Insets(5,5,5,5); }
Dibujo
POO - EPS - UAM 42
Código del ejemplo public static void main(String[] args) { //Create a new window. Frame f = new Frame("Converter Applet/Application"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); //Create a Converter instance. Converter converter = new Converter(); converter.init();
//Add the Converter to the window and display the window. f.add("Center", converter); f.pack(); //Resizes the window to its natural size. f.setVisible(true); } }
Main
22
POO - EPS - UAM 43
Código del ejemplo
class ConversionPanel extends Panel implements ActionListener, AdjustmentListener, ItemListener { TextField textField; Choice unitChooser; Scrollbar slider; int max = 10000; int block = 100; Converter controller; Unit[] units;
Panel interno
POO - EPS - UAM 44
Código del ejemplo ConversionPanel(Converter myController, String myTitle, Unit[] myUnits) { //Initialize this ConversionPanel to use a GridBagLayout. GridBagConstraints c = new GridBagConstraints(); GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag);
controller = myController; //Save arguments in instance variables. units = myUnits;
//Set up default layout constraints. c.fill = GridBagConstraints.HORIZONTAL;
//Add the label. It displays this panel's title, centered. Label label = new Label(myTitle, Label.CENTER); c.gridwidth = GridBagConstraints.REMAINDER; //It ends a row. gridbag.setConstraints(label, c); add(label);
Composición
23
POO - EPS - UAM 45
Código del ejemplo
//Add the text field. It initially displays "0" and needs //to be at least 10 columns wide.
textField = new TextField("0", 10); c.weightx = 1.0; //Use maximum horizontal space... c.gridwidth = 1; //The default value. gridbag.setConstraints(textField, c); add(textField); textField.addActionListener(this);
+ componentes
POO - EPS - UAM 46
Código del ejemplo
//Add the pop-up list (Choice).
unitChooser = new Choice(); for (int i = 0; i < units.length; i++) { //Populate it. unitChooser.add(units[i].description); } c.weightx = 0.0; //The default value. c.gridwidth = GridBagConstraints.REMAINDER; //End a row. gridbag.setConstraints(unitChooser, c); add(unitChooser); unitChooser.addItemListener(this);
+ componentes
24
POO - EPS - UAM 47
Código del ejemplo
// Add the slider. It's horizontal, and it has the maximum // value specified by the instance variable max. Its initial // and minimum values are the default (0). A click increments // the value by block units.
slider = new Scrollbar(Scrollbar.HORIZONTAL); slider.setMaximum(max + 10); slider.setBlockIncrement(block); c.gridwidth = 1; //The default value. gridbag.setConstraints(slider, c); add(slider); slider.addAdjustmentListener(this); } + componentes
POO - EPS - UAM 48
Código del ejemplo
/** Draws a box around this panel. */ public void paint(Graphics g) { Dimension d = getSize(); g.drawRect(0,0, d.width - 1, d.height - 1); }
/** * Puts a little breathing space between the panel * and its contents, which lets us draw a box in the paint() method. */ public Insets getInsets() { return new Insets(5,5,5,8); }
Dibujo
25
POO - EPS - UAM 49
Código del ejemplo
/** Respond to the text field */ public void actionPerformed(ActionEvent e) { setSliderValue((double)Double.valueOf( textField.getText()).doubleValue()); controller.convert(this); }
/** Respond to the choice */ public void itemStateChanged(ItemEvent e) { controller.convert(this); }
/** Respond to the slider. */ public void adjustmentValueChanged(AdjustmentEvent e) { textField.setText(String.valueOf(e.getValue())); controller.convert(this); }
Respuesta a eventos
POO - EPS - UAM 50
Código del ejemplo
/** Set the values in the slider and text field. */ void setValue(double f) { setSliderValue(f); textField.setText(String.valueOf((float)f)); }
/** Set the slider value. */ void setSliderValue(double f) { int sliderValue = (int)f;
if (sliderValue > max) sliderValue = max; if (sliderValue < 0) sliderValue = 0; slider.setValue(sliderValue); } }
Modificación componentes
26
POO - EPS - UAM 51
Cómo se usan las componentes AWT
Jerarquía de componentes: Las componentes son estructuradas en una jerarquía de
componentes, con instancias de (subclases de) Container definiendo dicha estructura.
Dibujo de las componentes: Los componentes son dibujados desde el tope de la
jerarquía (la Ventana) hacia abajo, hasta arribar a las hojas (componentes no contenedores)
Manejo de eventos: Los eventos son enviados a los objetos que se registran
como “event listeners” Modelo de delegación
Jerarquía = Composición
POO - EPS - UAM 52
Jerarquía de componentes: la clase java.awt.Container
Las interfaces se construyen agregando componentes a modo de piezas
La jerarquía de componentes debe empezar con una ventana (frame) o un applet
Una componente sólo puede añadirse a un Container Agregar: add(Component) Retirar: remove(Component)
Las ventanas no pueden añadirse a otra componente La colocación de las componentes en un contenedor se
puede definir: Mediante layout managers de distintos tipos A mano, con posiciones absolutas
Jerarquía = Composición
27
POO - EPS - UAM 53
Jerarquía de componentes (II)
Las componentes se pueden añadir: En el constructor del contenedor En main En cualquier función
Atravesar el árbol de componentes: Acceso a componentes: getComponent(int),
getComponentAt(int,int), getComponentCount(), getComponents()
Acceso al contenedor desde una componente: getParent()
Jerarquía = Composición
POO - EPS - UAM 54
Jerarquía de componentes: ejemplo
public class Converter extends Frame { . . . public void init() { . . . add(metricPanel); add(usaPanel); . . .
28
POO - EPS - UAM 55
Apariencia de las componentes: paint(Graphics) de Component
La apariencia en pantalla de cada subclase de Component está definida por el código de paint(Graphics)
El código de paint consiste en llamadas a funciones de dibujo sobre el objeto de tipo Graphics
Es poco factible cambiar el dibujo de las componentes predefinidas (En cambio, es fácil cambiar su respuesta a eventos) Normalmente no se redefine paint de las clases predefinidas Para modificar su apariencia, modificar su estado (el sistema refleja
los cambios en la pantalla automáticamente) En componentes personalizadas desde cero sí se define paint
Es importante que paint no sea costoso de ejecutar Utilizar hilos si es necesario para no bloquear el repintado
POO - EPS - UAM 56
Dibujo de componentes
El dibujo comienza por el componente más alto en la jerarquía que necesita ser dibujado Por ejemplo, un Frame.
Se baja por la jerarquía, dibujando cada componente intermedio, hasta las hojas.
El sistema de dibujo de AWT organiza este procedimiento
No se pueden hacer suposiciones sobre el orden relativo de dibujo de las componentes
29
POO - EPS - UAM 57
Dibujo de componentes: ejemplo
Se dibuja el frame Se dibuja el Converter
Caja del borde Se dibuja uno de los
dos ConversionPanel Caja del borde
Los componentes de este panel (Label, TextField, Scrollbar y Choice) son dibujados
POO - EPS - UAM 58
Refresco de las componentes
Cuándo Al desplegar una ventana o cambiarle el tamaño Al hacer visible un componente Al cambiar desde el programa propiedades visuales de un
componente Al ser necesario cambiar la apariencia de uno
componente para reflejar cambios en la aplicación Quién solicita
En los tres primeros casos, el sistema AWT. En el último caso, el mismo programa
Refresco = (re)dibujar
30
POO - EPS - UAM 59
Refresco de las componentes
El proceso de dibujo en sí sólo puede llevarse a cabo cuando lo diga el sistema AWT Estos procesos se deben ejecutar sin
interrupción. AWT hace que todos los dibujos ocurran en el
mismo hilo. El dibujo no puede insumir mucho tiempo
Si es necesario, crear un hilo separado para ejecutar alguna operación larga
POO - EPS - UAM 60
Refresco de las componentes: update(Graphics) y repaint()
AWT decide dibujar un componente invoca a update(Graphics) Esta invocación se hace desde el hilo de procesamiento
de eventos update(Graphics) borra el área a refrescar e invoca a
paint(Graphics) Lo solicita el programa
invoca a repaint() Petición al sistema AWT para llamar a update lo antes
posible El programa no debe llamar a paint directamente
31
POO - EPS - UAM 61
Refresco de las componentes: el objeto Graphics
Es el argumento de los métodos update y paint Normalmente nos llega a nuestro código desde AWT
Provee métodos para: Dibujar y rellenar rectángulos, arcos, líneas, óvalos,
polígonos, textos e imágenes. Obtener o cambiar el color, tipo de fuente o área de
clipping actuales. Cambiar el modo de dibujo.
POO - EPS - UAM 62
Refresco de las componentes: ejemplo
La forma más simple de dibujar una componente es especializar el método paint
Ejemplo: /** Draws a box around this panel. */ public void paint(Graphics g) { Dimension d = getSize(); g.drawRect(0,0, d.width - 1, d.height - 1); }
32
POO - EPS - UAM 63
Gestión de eventos: modelo de eventos de AWT 1.1
Modelo basado en delegación Eventos generados por emisores (sources) de
eventos. Objetos (listeners) se registran para ser
notificados de eventos: De cierto tipo Desde un emisor en particular
Se pueden tratar y generar eventos
POO - EPS - UAM 64
Gestión de eventos
Los eventos son objetos de distintas subclases de AWTEvent Se generan eventos cuando:
Se produce input del usuario: MouseEvent,KeyEvent Un widget se acciona: ActionEvent, TextEvent, AdjustmentEvent
Una ventana es manipulada: WindowEvent Otras causas: ContainerEvent, ComponentEvent, PaintEvent, etc.
Los manejadores de eventos (listeners) pueden ser instancias de cualquier clase. Sólo es necesario que la clase implemente la interfaz listener
correspondiente
33
POO - EPS - UAM 65
Estructura de programa
En cada programa con un manejador de eventos:
1. En el encabezamiento de la clase, declaración de implementar la interfaz (o extender una clase que la implemente):
public class MyClass implements ActionListener {
2. Código que registra una instancia del manejador como receptor de eventos de uno o más emisores:
someComponent.addActionListener(instanceOfMyClass);
3. La implementación de los métodos declarados en la interfaz: public void actionPerformed(ActionEvent e) { ...//
code that reacts to the action...}
POO - EPS - UAM 66
Ejemplo visto
class ConversionPanel extends Panel implements
ActionListener, AdjustmentListener, ItemListener {
textField.addActionListener(this);
public void actionPerformed(ActionEvent e) {
setSliderValue((double)Double.valueOf( textField.getText()).doubleValue());
controller.convert(this);
}
34
Abstract Window Toolkit (AWT)
Repaso de clases básicas
POO - EPS - UAM 68
java.awt.Component
Dibujarse en la pantalla: paint(), update(), repaint()
Procesamiento de eventos: delegación Control de la apariencia visual:
Color: setForeground(Color), getForeground(), setBackground(Color), getBackground()
Font: setFont(Font), getFont() Cursor: setCursor(Cursor), getCursor()
35
POO - EPS - UAM 69
java.awt.Component (II)
Tamaño y posición: setSize(int,int)
getSize() Dimension
getLocation() Point
getLocationOnScreen() Point
setBounds(int,int,int,int)
getBounds() Rectangle
(El layout manager puede alterar estos valores) Mostrar detalles en System.out: list()
POO - EPS - UAM 70
java.awt.Graphics
Argumento de paint() y update() Dibujo de primitivas gráficas:
drawLine(int,int, int,int), drawRect(int,int,int,int), drawArc(int,int,int,int,int,int), fillRect(int,int,int,int)
drawString(String,int,int)
drawImage(Image,int,int[,int,int],ImageObserver)
Estado: Componente sobre la que dibujar: getGraphics() de Component Origen de coordenadas: translate(int,int) Área de clip: getClip(), setClip(int,int,int,int) Color: setColor(Color), getColor() Font: setFont(Font), getFont() Modo XOR: setXORMode(Color)
36
POO - EPS - UAM 71
Clases auxiliares en java.awt
Posiciones y tamaños: Dimension: width, height
Point: x, y
Rectangle: x, y, width, height, contains(Point)
Polygon: npoints, xpoints, ypoints, addPoint(Point)
Color: new Color(0.8f, 0.3f, 1.0f) en RGB Constantes de tipo Color: Color.white,Color.blue,
etc. Funciones para conversión RGB ↔ HSB
POO - EPS - UAM 72
Clases auxiliares en java.awt (II)
Font: new Font ("Helvetica", Font.BOLD + Font.ITALIC, 18)
getName(), getStyle(), getSize()
Constantes de estilo: Font.BOLD, Font.ITALIC, Font.PLAIN
Cursor: new Cursor(Cursor.HAND_CURSOR)
Cursor.CROSSHAIR_CURSOR
etc.
37
Abstract Window Toolkit (AWT)
3ra. Parte: Gestión de Eventos
POO - EPS - UAM 74
Modelo de eventos
Modelo basado en delegación. A cada tipo de evento xxxEvent corresponde:
Un tipo de receptor xxxListener (excepción: MouseEvent tiene dos)
Una lista de clases de componentes que pueden producir el evento
Un método addxxxListener para registrar receptores de esos eventos Este método está definido en las clases que generan el evento Una componente sólo puede registrar listeners del tipo de eventos
que genera la componente
38
POO - EPS - UAM 75
Clase de evento: ActionEvent
Objetos que lo emiten: Button, TextField, List, MenuItem
Tipo de interfaz listener: ActionListener
Métodos a implementar en clase listener: actionPerformed (ActionEvent)
Método para registrar listener: addActionListener (ActionListener)
Modelo de eventos: ejemplo
Una componente sólo puede registrar listeners del tipo de eventos que genera la componente
POO - EPS - UAM 76
Modelo de eventos: ejemplo
public class Beeper implements ActionListener { ... //where initialization occurs: button = new Button("Click Me"); button.addActionListener(this); ... public void actionPerformed(ActionEvent e){ ...//Implements the answer... } }
39
POO - EPS - UAM 77
Utilización de adapters y clases internas
La mayoría de las interfaces de eventos contienen más de un evento. Por ejemplo, MouseListener define cinco
métodos. Aunque sólo nos interese un evento, si nuestra
clase implementa directamente la interfaz, igual debemos dar código (probablemente un cuerpo vacío) para los otros cuatro métodos
POO - EPS - UAM 78
Ejemplo de código de listener public class MyClass implements MouseListener { ...
someObject.addMouseListener(this);
...
/* Empty method definition. */
public void mousePressed(MouseEvent e) { }
/* Empty method definition. */
public void mouseReleased(MouseEvent e) { }
/* Empty method definition. */
public void mouseEntered(MouseEvent e) { }
/* Empty method definition. */
public void mouseExited(MouseEvent e) { }
public void mouseClicked(MouseEvent e) {
...//Event handler implementation goes here... }
}
40
POO - EPS - UAM 79
Utilización de adapters
Este tipo de código resulta más difícil de leer y mantener.
Para evitar la implementación vacía de métodos, AWT provee clases adapters implementan listeners con métodos vacíos; proporciona los adaptadores en java.awt.event; para cada interfaz de listener con más de un método.
Crear una subclase del adaptador definiendo sólo los métodos que interesen
POO - EPS - UAM 80
Utilización de adapters: ejemplo
Por ejemplo, si se extiende la clase MouseAdapter se hereda definiciones (vacías) de los cinco métodos definidos por la interfaz MouseListener. class MouseAdapter implements MouseListener { public void mouseClicked (MouseEvent e) {} public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited (MouseEvent e) {} }
public class MyClass extends MouseAdapter { ... someObject.addMouseListener(this); ... public void mouseClicked(MouseEvent e) { ...//Event handler implementation goes here... } }
41
POO - EPS - UAM 81
Adaptadores: problemas (I)
Una subclase de Component no puede heredar de otra clase
⇒ Utilizar un objeto adaptador auxiliar para hacer de listener
POO - EPS - UAM 82
Adaptadores: código
class MyListener extends MouseAdapter {
public void mouseEntered (MouseEvent e) {
... // Respuesta de la ventana al evento
} }
class Ventana extends Frame {
Ventana () {
Button boton = new Button ();
boton.addMouseListener (new MyListener ());
...
} }
42
POO - EPS - UAM 83
Adaptadores: problemas (II)
A menudo los métodos listener necesitan acceder a variables de la clase de componente Incluir en el adaptador una variable que apunte a
la componente O bien definir el adaptador como clase interna
de la clase de componente
POO - EPS - UAM 84
class Ventana extends Frame {
private String nombre;
Ventana () { Button boton = new Button (); boton.addMouseListener (new MyListener ()); ... }
class MyListener extends MouseAdapter { public void mouseEntered (MouseEvent e) { ... System.out.println (nombre); ... } } }
Adaptador como clase interna
43
POO - EPS - UAM 85
class Ventana extends Frame {
private String nombre; Ventana () { Button boton = new Button ();
boton.addMouseListener (
new MouseAdapter () { public void mouseEntered (MouseEvent e) { ...
System.out.println (nombre);
... } } ); } }
Adaptador como clase anónima
POO - EPS - UAM 86
class Mover extends MouseAdapter implements MouseMotionListener { private Point initialPoint; public Mover (Component c) { listenTo (c); } public void listenTo (Component c) { c.addMouseListener (this); c.addMouseMotionListener (this); } public void mousePressed (MouseEvent e) { initialPoint = e.getPoint (); } public void mouseDragged (MouseEvent e) { Component c = (Component) e.getSource (); Point p = c.getLocation (); c.setLocation (p.x + e.getX () - initialPoint.x, p.y + e.getY () - initialPoint.y); } public void mouseMoved (MouseEvent e) {} }
Adaptadores autosuficientes = reutilizables
new Mover (obj);
44
POO - EPS - UAM 87
Ver apéndice A
Clases de Eventos Métodos de los listeners
Abstract Window Toolkit (AWT)
4ta. Parte: Gestión de Eventos:
Implementación de los listeners
45
POO - EPS - UAM 89
¿Qué deben hacer los métodos de los receptores?
Modificar características de la interfaz Cambiar colores, fonts, etiquetas, etc. Mover objetos, cambiar su tamaño Ocultar, mostrar, añadir, eliminar componentes Abrir un cuadro de diálogo etc.
Ejecutar programas de la aplicación Normalmente se refleja algún resultado en la interfaz
POO - EPS - UAM 90
¿Procesar eventos o ignorarlos?
Eventos de bajo nivel recogidos en widgets y elaborados en forma de eventos de alto nivel Botones: MouseEvent → ActionEvent Widgets de texto: MouseEvent, KeyEvent → TextEvent,
ActionEvent Widgets de selección: MouseEvent → ItemEvent, ActionEvent etc.
Eventos de cambio de estado de componentes: procesar los eventos inmediatamente vs. acceder al estado cuando se necesite TextEvent, ItemEvent, ComponentEvent, ContainerEvent,
AdjustmentEvent, etc.
46
POO - EPS - UAM 91
Contenido de las clases de eventos
Las distintas clases de eventos incluyen: Constantes (variables estáticas)
ID de los distintos eventos de una clase Ejemplo: MouseEvent.MOUSE_MOVED, KeyEvent.KEY_RELEASED
Constantes para ciertas propiedades de los eventos (valores devueltos por métodos) Ejemplo: ItemEvent.SELECTED, ItemEvent.DESELECTED
Métodos Devuelven información adicional sobre el evento Ejemplo: getX(), getY() de MouseEvent, getKeyChar()
de KeyEvent, getID() de AWTEvent
POO - EPS - UAM 92
Implementación de un ActionListener
Probablemente son los más fáciles y comunes de implementar.
Se implementa un ActionListener para responder a las indicaciones del usuario de que alguna acción dependiente de la implementación debe ocurrir.
Cuándo ocurre? Click sobre un botón Doble Click sobre un item de lista Elegir un menu item Enter en un campo de texto
Como resultado, se envía el mensaje actionPerformed a todos los listeners que se han registrado para ese componente
47
POO - EPS - UAM 93
Interfaz ActionListener
Define un solo método void actionPerformed(ActionEvent)
Llamado por AWT justo después que el usuario informe a la componente “oída” que algo debe ocurrir.
Por lo tanto, no tiene clase Adapter
POO - EPS - UAM 94
Ejemplo de ActionListener
48
POO - EPS - UAM 95
Ejemplo de ActionListener
public class MultiListener ... implements ActionListener { ... //where initialization occurs: button1.addActionListener(this); button2.addActionListener(this); button2.addActionListener(new Eavesdropper(bottomTextArea)); } public void actionPerformed(ActionEvent e) { topTextArea.append(e.getActionCommand() + "\n"); } }
class Eavesdropper implements ActionListener { ... public void actionPerformed(ActionEvent e) { myTextArea.append(e.getActionCommand() + "\n"); } }
POO - EPS - UAM 96
Ver apéndice B
Implementación de interfaces de listeners
49
Abstract Window Toolkit (AWT)
5ta. Parte: Layout de componentes dentro de un
contenedor
POO - EPS - UAM 98
Layout de componentes
¿Qué es layout? Disposición global de un conjunto de
componentes
Layout Manager
50
POO - EPS - UAM 99
Layout Manager
Objeto que controla el tamaño y posición de los componentes de un contenedor.
Implementan la interfaz LayoutManager ¿Por qué layout managers?
La posición de una componente depende de las componentes que la rodean y del espacio disponible para el grupo
Un layout manager por encima de las componentes individuales impone un orden
Las componentes negocian su colocación y tamaño con el layout manager.
POO - EPS - UAM 100
Clases de Layout Managers
Existen distintas clases de manager para distintos tipos de layout Predefinidos por AWT
Simples: FlowLayout y GridLayout Específicos: BorderLayout, CardLayout Ultra flexible:GridBagLayout
Cada uno tiene sus propias “reglas” de uso
51
POO - EPS - UAM 101
Clases de Layout Manager
Cada Container tiene un controlador por omisión. Panel FlowLayout Windows BorderLayout
Si no sirve, se puede cambiar fácilmente setLayoutManager(LayoutManager) de Container.
Es posible incluso crear manejadores propios
POO - EPS - UAM 102
Reglas generales de uso
A menos que el programador lo cambie, cada contenedor tiene su propia instancia de LayoutManager asociada.
Es consultado cada vez que que el contenedor tiene que cambiar su apariencia.
La mayoría de los LayoutManagers no requiere que se llame explícitamente a sus métodos
52
POO - EPS - UAM 103
Cómo elegir LayoutManager
Escenario: Se necesita mostrar una componente en tanto espacio
como sea posible.
Considere BorderLayout o GridBagLayout Con BorderLayout, se debe poner la componente
ávida de espacio en el centro. Con GridBagLayout es necesario que la propiedad fill de las restricciones sea fill=GridBagConstraints.BOTH.
Si no importa que las otras componentes sean igual de grandes, se puede usar un GridLayout.
POO - EPS - UAM 104
Cómo elegir LayoutManager (II)
Escenario: Se necesita mostrar unas pocas componentes en una fila a
tamaño natural.
Considere utilizar un Panel para contener los componentes y el manager por omisión para el Panel, el FlowLayout manager.
Escenario: Es necesario mostrar unos pocos componentes del mismo
tamaño en filas y/o columnas.
El GridLayout es perfecto para esto.
53
POO - EPS - UAM 105
Algunas guías de uso
Los siguientes métodos de Container provocan invocaciones al layout manager: add(), remove(), removeAll(): en
cualquier momento. layout(): usualmente como resultado de una
solicitud paint, y no directamente. preferredSize(), minimumSize(): el
retorno es sólo una sugerencia, el programa tiene que mantener estos valores.
POO - EPS - UAM 106
Ver apéndice C
Clases de layout managers
54
POO - EPS - UAM 107
Interfaz KeyListener
void keyTyped(KeyEvent) Llamado por AWT después que el usuario introduce un
carácter Unicode en la componente de interés. void keyPressed(KeyEvent)
Llamado por AWT después que el usuario presiona una tecla en el teclado.
void keyReleased(KeyEvent) Llamado por AWT después que el usuario suelta una
tecla en el teclado.
POO - EPS - UAM 108
Clase KeyEvent int getKeyChar() void setKeyChar(char)
Obtiene o cambia el carácter Unicode asociado con el evento. int getKeyCode() void setKeyCode(int)
Obtiene o cambia el código de tecla asociado al evento. La clase KeyEvent define varias constantes de códigos para las
teclas comunes. Por ejemplo: VK_A especifica la tecla con rótulo A VK_ESCAPE especifica la tecla ESCAPE.
void setModifiers(int) Cambia el estado de las teclas modificadoras para el evento.
55
Abstract Window Toolkit (AWT)
Apéndice C Clases de layout managers
POO - EPS - UAM 110
BorderLayout
56
POO - EPS - UAM 111
BorderLayout (II) class Ventana extends Frame { Ventana () { setLayout (new BorderLayout ()); setTitle ("Border Layout"); add("North", new Button("North")); add("South", new Button("South")); add("East", new Button("East")); add("West", new Button("West")); add("Center", new Button("Center")); } }
Importante: en este caso, siempre se debe utilizar una versión de add con dos argumentos:
Sector Componente
POO - EPS - UAM 112
BorderLayout (III)
La parte central es la que más varía con la ventana. Las otras partes sólo varían para mantener ocupado
todo el espacio disponible. Manager por omisión de las ventanas. Por omisión, no tiene ninguna distancia al borde
Se puede especificar con este constructor:
public BorderLayout(int horizontalGap, int verticalGap)
57
POO - EPS - UAM 113
FlowLayout
POO - EPS - UAM 114
FlowLayout (II)
Este manager pone las componentes en una fila, cada una a su preferredSize().
Si el espacio horizontal es muy pequeño, agrega nuevas filas.
En cada fila los componentes puedan estar centrados (omisión), alineados a izquierda o a derecha.
58
POO - EPS - UAM 115
FlowLayout (III)
class Ventana extends Frame { Ventana () { setLayout (new FlowLayout ()); setTitle ("Flow Layout"); add (new Button ("Button 1")); add (new Button ("Button 2")); add (new Button ("Button 3")); add (new Button ("Button 4")); add (new Button ("Button 5")); } }
POO - EPS - UAM 116
FlowLayout (IV)
class Ventana extends Frame { Ventana () { FlowLayout f = new FlowLayout (); f.setAlignment(FlowLayout.RIGHT); setLayout (f); setTitle ("Flow Layout"); add (new Button ("Button 1")); add (new Button ("Button 2")); add (new Button ("Button 3")); add (new Button ("Button 4")); add (new Button ("Button 5")); add (new Button ("Button 6")); } }
59
POO - EPS - UAM 117
FlowLayout (V)
Tres constructores: public FlowLayout()
public FlowLayout(int alignment)
public FlowLayout(int alignment, int horizontalGap, int verticalGap)
Alineamiento: FlowLayout.LEFT
FlowLayout.CENTER
FlowLayout.RIGHT
Horizontal y Vertical gap: distancia entre componentes (omisión: 5)
POO - EPS - UAM 118
GridLayout
setRows(int), setColumns(int)
GridLayout(0,n) → tantas filas como hagan falta
Ejemplo: GridLayout(2,3)
60
POO - EPS - UAM 119
GridLayout (II)
Este manager pone las componentes en una grilla de celdas.
Cada componente toma todo el espacio disponible en su celda, las cuales tienes todas el mismo tamaño.
Cuando se redimensiona una ventana con GridLayout, se cambia el tamaño de las celdas de forma que sean lo más grandes posibles dado el espacio disponible.
POO - EPS - UAM 120
GridLayout (III)
Constructores:
public GridLayout(int rows, int columns)
public GridLayout(int rows, int columns, int horizontalGap, int verticalGap)
class Ventana extends Frame { Ventana () { setLayout (new GridLayout (2,3)); setTitle ("Grid Layout"); add (new Button ("Button 1")); add (new Button ("Button 2")); add (new Button ("Button 3")); add (new Button ("Button 4")); add (new Button ("Button 5")); } }
61
POO - EPS - UAM 121
CardLayout
POO - EPS - UAM 122
CardLayout (II)
Un CardLayout permite manipular dos o más componentes (usualmente Paneles) para que compartan el mismo espacio de la pantalla.
Conceptualmente, una pila de cartas donde sólo se ve la que está en la cima.
Se puede elegir qué carta estará en la cima: Solicitando la primera o última carta (orden en que se
agregaron al contenedor). Recorriendo la pila hacia delante o hacia atrás. Especificando una carta por nombre
62
POO - EPS - UAM 123
CardLayout (III) //Where instance variables are declared: Panel cards; final static String BUTTONPANEL = "Panel with Buttons"; final static String TEXTPANEL = "Panel with TextField"; ... //Where the container is initialized: cards = new Panel(); cards.setLayout(new CardLayout()); ... //Create a Panel named p1. Put buttons in it. //Create a Panel named p2. Put a text field in it. ... cards.add(BUTTONPANEL, p1); cards.add(TEXTPANEL, p2); ... ((CardLayout)cards.getLayout()).show(cards, BUTTONPANEL); // o bien ((CardLayout)cards.getLayout()).show(cards, TEXTPANEL);
POO - EPS - UAM 124
CardLayout (IV)
Eligiendo componente: public void first(Container parent)
public void next(Container parent)
public void previous(Container parent)
public void last(Container parent)
public void show(Container parent, String name)
El primer argumento siempre es el contenedor para quien el manager está trabajando.
63
POO - EPS - UAM 125
GridBagLayout
mantienen igualdad
POO - EPS - UAM 126
GridBagLayout (II)
El más flexible (y complejo) de los layout managers.
Coloca a las componentes en una grilla de filas y columnas Ciertos componentes pueden abarcar varias filas o
columnas. No todas las filas (columnas) deben que tener el mismo
alto (ancho). Coloca las componentes en celdas y luego utiliza
los preferredSize de las componentes para determinar el tamaño de las celdas.
64
POO - EPS - UAM 127
GridBagLayout (III)
mantienen igualdad y ocupan todo el ancho
toma todo el espacio adicional
POO - EPS - UAM 128
GridBagLayout (IV)
Las posiciones y tamaños se especifican mediante restricciones (constraints) para cada componente. Se crea instancia de GridBagConstraint, Se le da valor a sus variables de instancia, Se asocia la restricción con el componente
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
// Para cada componente a ser agregado: //... Se crea el componente ... //... Se da valor a las variables de c gridbag.setConstraints(theComponent, c);
add(theComponent);
65
POO - EPS - UAM 129
Restricciones de GridBagLayout
Se puede usar la misma instancia de GridBagLayout para distintas componentes.
gridx, gridy Especifica la celda que contiene el extremo izquierdo
(superior) del componente. La primera celda tiene gridx (gridy) = 0. Usar GridBagConstraints.RELATIVE (el valor
por omisión) para especificar que el componente se coloque justo a la derecha (o abajo) del componente anterior.
POO - EPS - UAM 130
Restricciones de GridBagLayout (II)
gridwidth, gridheight Especifica el número de columnas (filas) que ocupa la
componente. No son pixels. El valor default es 1. Usar GridBagConstraints.REMAINDER para
especificar que la componente sea la última de la fila (columna).
Usar GridBagConstraints.RELATIVE para especificar que la componente sea la anteúltima en la fila (columna).
66
POO - EPS - UAM 131
Restricciones de GridBagLayout (III)
fill Usado cuando el área disponible para una componente es
mayor que la requerida: GridBagConstraints.NONE (valor por omisión), GridBagConstraints.HORIZONTAL:lacomponentecreceparaocuparhorizontalmentetodaelárea,peronocambiasualto.
GridBagConstraints.VERTICAL:lacomponentecreceparaocuparverticalmentetodaelárea,peronocambiasuancho.
GridBagConstraints.BOTH:hacequelacomponentelleneporcompletoeláreadisponible.
ipadx, ipady Especifica el margen interno (por omisión es 0). El ancho
(alto) de la componente es, por lo menos el ancho (alto) mínimo más ipadx*2 pixels (ipady*2 pixels).
POO - EPS - UAM 132
Restricciones de GridBagLayout (IV)
Insets Especifica el margen externo de la componente – el mínimo espacio
entre la componente y los márgenes del área disponible. El valor es especificado en un objeto Insets. Por omisión el valor es 0.
Anchor Usado cuando la componente es menor que el área disponible, para
determinar dónde (dentro del área) ubicarlo: GridBagConstraints.CENTER (default) GridBagConstraints.NORTH
GridBagConstraints.NORTHEAST
GridBagConstraints.EAST
GridBagConstraints.SOUTHEAST
GridBagConstraints.SOUTH
GridBagConstraints.SOUTHWEST
GridBagConstraints.WEST
GridBagConstraints.NORTHWEST
67
POO - EPS - UAM 133
Restricciones de GridBagLayout (V)
weightx, weighty Especificar los pesos es un arte que puede tener un
impacto significativo en la apariencia final. Son usados para determinar cómo se distribuye el
espacio entre las columnas (filas); esto es importante para el comportamiento de redimensionamiento.
A menos que se especifique un valor distinto de cero, todas las componentes se agrupan juntas en el centro del contenedor. Esto es porque cuando el peso es 0.0 (default), el GridBagLayout pone cualquier espacio extra en los márgenes externos del contenedor.
(continúa)
POO - EPS - UAM 134
Restricciones de GridBagLayout (VI)
weightx, weighty(cont.) Generalmente los pesos son especificados con 0.0 y 1.0
como valores extremos, usando números intermedios cuando es necesario.
Números mayores indican que la fila (columna) del componente debe tener más espacio.
Para cada columna (fila), el peso es relacionado con el mayor weightx (weighty) especificado para un componente en esa columna (fila). Para los componentes multicolumnas (multifilas) el peso es
dividido de alguna manera entre las columnas (filas) que abarca El espacio extra tiende a irse hacia abajo a la derecha.
68
POO - EPS - UAM 135
GridBagLayout: Ejemplo
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
POO - EPS - UAM 136
GridBagLayout: Ejemplo
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
Cada componente tan grande como sea posible
69
POO - EPS - UAM 137
GridBagLayout: Ejemplo
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
Si no estuviera
POO - EPS - UAM 138
GridBagLayout: Ejemplo
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
Todas las columnas iguales y mayores que 0
70
POO - EPS - UAM 139
GridBagLayout: Ejemplo
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
Si no estuviera (es decir, weightx = 0)
POO - EPS - UAM 140
GridBagLayout: Ejemplo
c.gridwidth = GridBagConstraints.REMAINDER; //end of row
makebutton("Button4", gridbag, c);
c.weightx = 0.0; //reset to the default
makebutton("Button5", gridbag, c); //another row
c.gridwidth = GridBagConstraints.RELATIVE; //next to last
makebutton("Button6", gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end of row
makebutton("Button7", gridbag, c);
71
POO - EPS - UAM 141
GridBagLayout: Ejemplo
c.gridwidth = 1; //reset to the default
c.gridheight = 2;
c.weighty = 1.0;
makebutton("Button8", gridbag, c);
c.weighty = 0.0; //reset to the default
c.gridwidth = GridBagConstraints.REMAINDER; //end of row
c.gridheight = 1; //reset to the default
makebutton("Button9", gridbag, c);
makebutton("Button10", gridbag, c);
POO - EPS - UAM 142
GridBagLayout: Ejemplo
c.gridwidth = 1; //reset to the default
c.gridheight = 2;
c.weighty = 1.0;
makebutton("Button8", gridbag, c);
c.weighty = 0.0; //reset to the default
c.gridwidth = GridBagConstraints.REMAINDER; //end of row
c.gridheight = 1; //reset to the default
makebutton("Button9", gridbag, c);
makebutton("Button10", gridbag, c);
ocupa dos filas
72
POO - EPS - UAM 143
GridBagLayout: Ejemplo
c.gridwidth = 1; //reset to the default
c.gridheight = 2;
c.weighty = 1.0;
makebutton("Button8", gridbag, c);
c.weighty = 0.0; //reset to the default
c.gridwidth = GridBagConstraints.REMAINDER; //end of row
c.gridheight = 1; //reset to the default
makebutton("Button9", gridbag, c);
makebutton("Button10", gridbag, c);
es el único con valor > 0
POO - EPS - UAM 144
GridBagLayout: Ejemplo
protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c) {
Button button = new Button(name);
gridbag.setConstraints(button, c);
add(button);
}
73
POO - EPS - UAM 145
Trabajando sin Layout Manager
Se debe utilizar un layout manager siempre que sea posible.
Con ellos es más fácil redimensionar los contenedores y ajustar la apariencia de componentes dependientes de la plataforma. También es fácil reutilizarlos.
Si el contenedor no será reutilizado, no puede ser redimensionado, y controla por completo los factores que normalmente dependen de la plataforma (fuentes y aspecto de los componentes), entonces puede tener sentido un layout absoluto.
POO - EPS - UAM 146
Trabajando sin Layout Manager
public void paint(Graphics g) {
if (!laidOut) {
Insets insets = insets();
/* We're guaranteed that insets() will return a valid
* Insets if called from paint() -- it isn't valid when
* called from the constructor.
*/
b1.reshape(50 + insets.left, 5 + insets.top, 50, 20);
b2.reshape(70 + insets.left, 35 + insets.top, 50, 20);
b3.reshape(130 + insets.left, 15 + insets.top, 50, 30);
laidOut = true;
}
74
Abstract Window Toolkit (AWT)
Apéndice D Widgets AWT
Clases predefinidas de componentes estándar
POO - EPS - UAM 148
java.awt.Button Estado y propiedades
Constructores: Button(), Button(String) El string se utiliza como etiqueta del botón
Cambiar / acceder a la etiqueta: GetLabel(), SetLabel(String)
Botón activo / inactivo: setEnabled(boolean) Operación
Emite un ActionEvent al ser pulsado Identificación para el evento de acción: setActionCommand(String) Asocia un string al botón (por omisión, el mismo que la etiqueta) El string formará parte de la información incluida en los ActionEvent's emitidos por el botón (ver getActionCommand() de ActionEvent)
75
POO - EPS - UAM 149
class ButtonDemo extends Frame implements ActionListener { Button b1, b2, b3; ButtonDemo () { setLayout (new FlowLayout ()); b1 = new Button (); b1.setLabel ("Disable middle button"); b1.setActionCommand ("Disable"); b2 = new Button ("Middle button"); b3 = new Button ("Enable middle button"); b3.setEnabled (false); b3.setActionCommand ("Enable");
add (b1); add (b2); add (b3);
b1.addActionListener (this); b3.addActionListener (this); } ...
POO - EPS - UAM 150
... public void actionPerformed (ActionEvent e) { String command = e.getActionCommand(); if (command.equals ("Disable")) { b1.setEnabled (false); b2.setEnabled (false); b3.setEnabled (true); } else { b1.setEnabled (true); b2.setEnabled (true); b3.setEnabled (false); } } }
76
POO - EPS - UAM 151
Widgets de selección Checkbox List Choice Menu
Selección múltiple
Doble click
Ahorro de espacio
ItemEvent lleva número de item
Emiten ItemEvents
Emiten ActionEvents
POO - EPS - UAM 152
java.awt.Checkbox
Descripción Botón seleccionable con dos estados: seleccionado /
deseleccionado Agrupable en grupos de botones de selección excluyente
(radio buttons) Estado y propiedades
Checkbox(), Checkbox(String), Checkbox(String,boolean)
getLabel(), setLabel(String)
getState(), setState(boolean)
77
POO - EPS - UAM 153
java.awt.Checkbox (cont.) Operación
Emite un ItemEvent al cambiar de estado
El item asociado el evento es el label del checkbox Identificación del item desde el evento:
getItem()→String (label del checkbox) getItemSelectable()→Object (la componente checkbox)
Botones excluyentes: grupos de Checkbox'es Crear objeto de la clase CheckboxGroup Utilizar el constructor Checkbox(String,boolean,CheckboxGroup)
Los checkbox creados con el mismo grupo como argumento forman un grupo
Sólo un checkbox de un grupo puede estar seleccionado
POO - EPS - UAM 154
class CheckboxDemo extends Frame { CheckboxDemo () { setLayout (new GridLayout (1, 2));
Panel p1 = new Panel (); Checkbox cb = new Checkbox (); cb.setLabel ("Checkbox 1"); cb.setState (true); p1.add (cb); p1.add (new Checkbox ("Checkbox 2")); p1.add (new Checkbox ("Checkbox 3")); add (p1);
Panel p2 = new Panel (); CheckboxGroup group = new CheckboxGroup (); p2.add (new Checkbox ("Checkbox 4", group, false)); p2.add (new Checkbox ("Checkbox 5", group, false)); p2.add (new Checkbox ("Checkbox 6", group, false)); add (p2); } }
78
POO - EPS - UAM 155
POO - EPS - UAM 156
java.awt.Choice
Descripción Lista de selección desplegable Uno de los elementos de la lista está seleccionado
Estado y propiedades add(String), getItem(int), getItemCount()
select(int), select(String), isIndexSelected(int), getSelectedItem() → String, getSelectedIndex() → int
Operación Emite un ItemEvent al cambiar la selección
El item asociado el evento es el string del item seleccionado
79
POO - EPS - UAM 157
java.awt.List
Descripción Lista de selección con barras de scroll El modo de selección puede ser simple o múltiple
Estado y propiedades List(), List(int), List(int,boolean)
add(String), add(String,int), remove(String), remove(int), getItem(int), getItems(), getItemCount(), getRows()
select(int), select(String), isIndexSelected(int), getSelectedItem() → String, getSelectedIndex() → int, getSelectedObjects() → Object[]
isMultipleMode(), setMultipleMode(boolean)
POO - EPS - UAM 158
java.awt.List (cont.)
Operación Seleccionar / deseleccionar item: emite ItemEvent
El item asociado al evento es el número de posición del item seleccionado Doble click: emite ActionEvent con el texto del
item seleccionado como action command string
80
POO - EPS - UAM 159
class ListDemo extends Frame implements ActionListener, ItemListener { TextArea output; List spanish, italian; ListDemo () { setLayout (new FlowLayout ()); spanish = new List (3, true); spanish.add ("uno"); spanish.add ("dos"); spanish.add ("tres"); spanish.add ("cuatro"); spanish.addActionListener (this); spanish.addItemListener (this);
italian = new List (); italian.add ("uno"); italian.add ("due"); italian.add ("tre"); italian.add ("quattro"); italian.addActionListener (this); italian.addItemListener (this); ...
POO - EPS - UAM 160
... Panel p = new Panel (); p.setLayout (new GridLayout (2, 1, 10, 10)); p.add (spanish); p.add (italian);
output = new TextArea (10, 40); output.setEditable (false);
add (output); add (p); } // Fin del constructor ...
81
POO - EPS - UAM 161
... public void actionPerformed (ActionEvent e) { List list = (List) (e.getSource ()); String language = (list == spanish)? "Spanish" : "Italian"; output.append ("Action event on " + list.getSelectedItem () + " in " + language + ".\n"); } public void itemStateChanged (ItemEvent e) { List list = (List) (e.getItemSelectable ()); String language = (list == spanish)? "Spanish" : "Italian"; int index = ((Integer) (e.getItem ())) .intValue (); if (e.getStateChange () == ItemEvent.SELECTED) { output.append ("Select event on item " + index + " (" + list.getItem (index) + ")" + " in " + language + ".\n"); } else output.append ("Deselect event on item " + index + " (" + list.getItem (index) + ")" + " in " + language + ".\n"); } }
POO - EPS - UAM 162
82
POO - EPS - UAM 163
java.awt.Menu
Descripción Conjunto de items de distintas modalidades:
MenuItem: tipo botón
CheckboxMenuItem: tipo checkbox
Menu: submenú MenuItem
Menu CheckBoxMenuItem
POO - EPS - UAM 164
java.awt.Menu
Construcción Menu(), Menu(String), MenuItem(), MenuItem(String),
CheckboxMenuItem(), CheckboxMenuItem(String)
Añadir items: add(String|MenuItem|CheckboxMenuItem|Menu), insert(String|MenuItem|...,int), getItem(int), addSeparator()
Se requiere una barra de menús para añadir menús a una ventana: setMenuBar(MenuBar) de Frame
add(Menu), getMenu(int), getMenuCount() de MenuBar
83
POO - EPS - UAM 165
java.awt.Menu (cont.)
Estado y propiedades getLabel(), setLabel(String)de Menu / MenuItem
Activar / desactivar item: isEnabled(), setEnabled(boolean)de Menu / MenuItem
Selección de CheckboxMenuItem: getState(), setState(boolean)
POO - EPS - UAM 166
java.awt.Menu (cont.)
Operación MenuItem emite sólo ActionEvent como un botón, con
el label del item pulsado como action command string
Source del evento: el item o el Menu contenedor del item
CheckboxMenuItem emite sólo ItemEvent como un checkbox, con el label del item seleccionado / deseleccionado como label del evento
Source del evento: el propio CheckboxMenuItem
84
POO - EPS - UAM 167
Widgets de texto
Label TextArea TextField
TextComponent
POO - EPS - UAM 168
java.awt.Label
Descripción Texto estático
Estado y propiedades Label(), Label(String), Label(String,LEFT|RIGHT|
CENTER)
getText(), setText(String)
getAlignment(), setAlignment(LEFT|RIGHT|CENTER)
Operación No tiene
85
POO - EPS - UAM 169
java.awt.TextComponent
Descripción Superclase de TextField y TextArea Texto editable, seleccionable
Estado y propiedades getText(), setText(String)
isEditable(), setEditable(boolean)
getCaretPosition(), setCaretPosition(int)
getSelectedText(), select(int,int), selectAll(), getSelectionStart(), getSelectionEnd(), setSelectionStart(int), setSelectionEnd(int)
POO - EPS - UAM 170
java.awt.TextField
Descripción Texto editable de una sola línea
Estado y propiedades (además de las de TextComponent) TextField(), TextField(String),
TextField(String,int)
getColumns(), setColumns(int)
getEchoChar(), setEchoChar(char), echoCharIsSet()
Operación Emite un TextEvent cuando se cambia un carácter del texto
Puede interesar procesar KeyEvent's si interesa obtener el carácter Cuando se pulsa 'Enter' emite un ActionEvent con el texto del
widget como action command string
86
POO - EPS - UAM 171
java.awt.TextArea
Descripción Texto editable multilínea con scrolling
Estado y propiedades (además de las de TextComponent) TextArea(), TextArea(String), TextArea(String,int,int)
Scrollbars: TextArea(String,int,int,int), TextArea.SCROLLBARS_NONE, SCROLLBARS_VERTICAL_ONLY... getColumns(), setColumns(int), getRows(), setRows(int) append(String), insert(String,int), replaceRange(String,int,int)
Operación Emite un TextEvent cuando se cambia un carácter del texto No emite ActionEvent's
POO - EPS - UAM 172
class TextDemo extends Frame implements ActionListener { TextField textField; TextArea textArea; TextDemo () { setLayout (new FlowLayout ()); textField = new TextField (20); textArea = new TextArea (5, 20); textArea.setEditable (false);
add (textField); add (textArea);
textField.addActionListener (this); } public void actionPerformed (ActionEvent evt) { String text = textField.getText (); textArea.append (text + "\n"); textField.selectAll (); } }
87
POO - EPS - UAM 173
POO - EPS - UAM 174
java.awt.Dialog
Descripción Depende de otra ventana:
Se destruye cuando se destruye la ventana principal Desaparece cuando se minimiza la ventana principal
Estado y propiedades Dialog (Frame [,String] [,boolean]) Modal / no modal: isModal(), setModal(boolean) isResizeable(), setResizeable(boolean)
de Window FileDialog extends Dialog
getDirectory(), setDirectory(String)
getFile(), setFile(String)
88
POO - EPS - UAM 175
class DialogWindow extends Frame implements ActionListener { private SimpleDialog dialog; private TextArea textArea; public DialogWindow () { textArea = new TextArea (5, 40); textArea.setEditable (false); add ("Center", textArea);
Button button = new Button ("Click to bring up dialog"); button.addActionListener (this); Panel panel = new Panel (); panel.add (button); add ("South", panel); } public void actionPerformed (ActionEvent event) { if (dialog == null) dialog = new SimpleDialog (this, "A Simple Dialog"); dialog.setVisible (true); } public void addLine (String text) { textArea.append(text + "\n"); } }
POO - EPS - UAM 176
class SimpleDialog extends Dialog implements ActionListener { TextField field; DialogWindow parent; Button setButton; SimpleDialog (Frame w, String title) { super (w, title, false); parent = (DialogWindow) w; Panel p1 = new Panel (); p1.setLayout (new GridLayout (2, 1)); Label label = new Label ("Enter text here:"); p1.add (label); field = new TextField (40); field.addActionListener (this); p1.add (field); add ("Center", p1); ...
89
POO - EPS - UAM 177
... Panel p2 = new Panel(); p2.setLayout (new FlowLayout (FlowLayout.RIGHT)); Button b = new Button ("Cancel"); b.addActionListener (this); setButton = new Button ("Set"); setButton.addActionListener (this); p2.add (b); p2.add (setButton); add ("South", p2); pack (); }
public void actionPerformed (ActionEvent event) { Object source = event.getSource(); if ((source == setButton) || (source == field)) parent.addLine (field.getText()); field.selectAll (); setVisible (false); } }
POO - EPS - UAM 178
java.awt.Dialog
90
POO - EPS - UAM 179
Widgets personalizados class Boton extends Canvas implements MouseListener { private boolean selected = false; protected String label; public Boton (String str) { label = str; addMouseListener (this); new Mover (this); } public void paint (Graphics g) { Dimension dim = getSize (); FontMetrics metrics = g.getFontMetrics (); g.drawRect (0, 0, dim.width-1, dim.height-1); g.drawString (label, (dim.width - metrics.stringWidth (label)) / 2, (dim.height - metrics.getHeight ()) / 2 + metrics.getMaxAscent ()); } ...
Def
inir
as
pect
o vi
sual
POO - EPS - UAM 180
Métodos para negociar tamaño con layout managers
... public Dimension getPreferredSize () { FontMetrics metrics = getGraphics () .getFontMetrics (); return new Dimension (metrics.stringWidth (label) + 20, metrics.getHeight () + 10); }
public Dimension getMinimumSize () { Dimension dim = getPreferredSize (); return new Dimension (dim.width / 2, dim.height / 2); }
public Dimension getMaximumSize () { Dimension dim = getPreferredSize (); return new Dimension (dim.width * 2, dim.height * 2); } ...
91
POO - EPS - UAM 181
... public void mouseClicked (MouseEvent e) { selected = !selected; if (selected) { setBackground (Color.black); setForeground (Color.white); } else { setBackground (Color.white); setForeground (Color.black); } }
public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited (MouseEvent e) {} ...
Resp
uest
a vi
sual
(fee
dbac
k)
a ac
ción
del
usu
ario
POO - EPS - UAM 182
... public String getLabel () { return label; } public void setLabel (String str) { label = str; repaint (); } public boolean getState () { return selected; } public void setState (boolean state) { selected = state; if (selected) { setBackground (Color.black); setForeground (Color.white); } else { setBackground (Color.white); setForeground (Color.black); } } // public void mouseClicked (MouseEvent e) { // setState (!selected); // } }
Inte
rfaz
par
a co
ntro
lar e
l est
ado
del w
idge
t
92
POO - EPS - UAM 183
class Boton2 extends Boton { boolean pointedAt = false; public Boton2 (String str) { super (str); }
public void paint (Graphics g) { super.paint (g); Dimension dim = getSize (); if (pointedAt) g.drawRect (4, 4, dim.width-9, dim.height-9); }
public void mouseEntered (MouseEvent e) { pointedAt = true; repaint (); } public void mouseExited (MouseEvent e) { pointedAt = false; repaint (); } }
Más
feed
back
a
acci
ones
del
usu
ario
POO - EPS - UAM 184
3. Click
2. Enter
4. Exit
5. Enter
6. Drag
1. Inicio
93
POO - EPS - UAM 185
class BotonAccion extends Boton {
private ActionListener multicaster = null; public BotonAccion (String str) { super (str); } public void mouseClicked (MouseEvent e) { super.mouseClicked (e);
processEvent ( new ActionEvent ( this, ActionEvent.ACTION_PERFORMED, label)); }
public void addActionListener (ActionListener listener) { multicaster = AWTEventMulticaster.add (multicaster, listener); }
public void processEvent (AWTEvent e) { if (e.getID () == ActionEvent.ACTION_PERFORMED && multicaster != null) multicaster.actionPerformed ((ActionEvent) e); super.processEvent (e); } }
Generación de eventos en respuesta a la interacción