construcción de la interfaz gráfica
Nychol Bazurto Gómez

Interfaz gráfica
Nivel
5
Distribuciones
Creación de la
Manejo de eventos
VEREMOS lo siguiente
-
Cómo proponer una arquitectura para un programa simple:
- Repartir responsabilidades entre interfaz, mundo y pruebas.
- Cómo construir las clases que implementan una interfaz usuario
- Cómo integrar las clases de la interfaz con las clases del mundo
POR QUé es importante la interfaz
POR QUé es importante la interfaz
medio de comunicación entre el usuario y el modelo del mundo

Ejecuta operaciones sobre el modelo del mundo.

Interfaz de usuario ideal

Usuario siente que está visualizando e interactuando directamente con los elementos del modelo del mundo
Un
Esperamos que sea agradable y fácil de utilizar


Agradable y fácil de utilizar
Condiciones mínimas que influyen en la percepción
- Combinación de colores
- Organización de los elementos en las ventanas
- Los gráficos
- Los tipos de letra
Los elementos de interacción se comporten de forma intuitiva.
Cantidad de conocimiento que el usuario debe tener para utilizar el programa.

DIseño de la interfaz
Diseño funcional y gráfico
Arquitectura


- Colores
- Distribución de elementos gráficos (menús, botones, …)
- Estructura clara
- Fácil de mantener
Asignación de responsabilidades

Cómo estructurar la interfaz de usuario y cómo comunicarla con las clases del modelo del mundo, sin mezclar en ningún momento las responsabilidades de esos dos componentes de un programa.


Interfaz gráfica

Interfaz gráfica

Etiquetas
Botones
Campos de texto
Caja de chequeo
Imágenes
Interfaz gráfica

Etiquetas
- Sirven para mostrar información estática (que no cambia)
- En Java se llama JLabel
Interfaz gráfica

Botónes
- Sirven para crear (generar) eventos que modifican el estado de la aplicación
- En Java se llaman JButton
Interfaz gráfica

Campos de texto
- Muestra información dinámica (que varía)
- Permite ingresar información al usuario.
- En Java se llaman JTextField.
Interfaz gráfica

Caja de chequeo
- Permite seleccionar elementos de una lista
- Permite mostrar una condición booleana.
- En Java se llama JCheckBox
Interfaz gráfica

Imágenes
- No son elementos gráficos propios, remplazan el texto de etiquetas y/o botones por la ruta de la imagen.
- En Java son ImageIcon.
Interfaz gráfica
- Para declarar los componentes como atributos:
-
Etiquetas (JLabel):
- private JLabel <nombreComienzaPor:lbl>;
-
Botones (JButton):
- private JButton <nombreComienzaPor:btn>;
-
Campos de texto (JTextField)
- private JTextField <nombreComienzaPor:txt>;
-
Caja de chequeo (JCheckBox):
- private JCheckBox <nombreComienzaPor:cb>;
Interfaz gráfica
- Cuando los declaren en su ejercicio les aparecerán de la siguiente forma:

Interfaz gráfica
- Para solucionar el problema deben “importar” cada uno de los componentes haciendo click izquierdo sobre el signo de alerta al igual que hicieron con ArrayList.
- Después del click izquierdo seleccionar la opción Import para cada componente:




Interfaz gráfica
- Para inicializar los componentes, dentro del constructor de la clase que los contiene:
-
Etiquetas (JLabel):
- nombreEtiqueta = new JLabel (“Texto de la etiqueta”);
-
Botones (JButton):
- nombreBoton = new JButton (“Texto del bótón”);
-
Campos de texto (JTextField)
- nombreCampoTexto = new JTextField (“Texto campo”);
-
Caja de chequeo (JCheckBox):
- nombreCajaChequeo = new JCheckBox (“Texto caja”);
Ventana principal

Ventana principal
- Contiene TODOS los elementos de visualización e interacción
- UNICA FUNCION: Servir como marco para los demás elementos de la interfaz (AGRUPA)
- Es un contenedor gráfico
Ventana principal

Controles para cerrar el programa
Título
Ventana principal

La ventana principal será un objeto de la clase InterfazEmpleado
Ventana principal

La ventana principal será un objeto de la clase InterfazEmpleado
Clase interfazempleado
Como cualquier clase:
- Está declarada en su propio archivo: InterfazEmpleado.java
- Sigue las mismas reglas que cualquier clase del mundo.
Diferencia:
- Está declarada en otro paquete: uniandes.cupi2.empleado.interfaz (ver en Eclipse).
Clase interfazempleado
package uniandes.cupi2.empleado.interfaz;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import uniandes.cupi2.empleado.mundo.Empleado;
import uniandes.cupi2.empleado.mundo.Fecha;
/**
* Ventana principal de la aplicación.
*/
public class InterfazEmpleado extends JFrame
{
}Se importan las clases del modelo del mundo
Se agrega extends JFrame para indicar que es una ventana
Clase interfazempleado
¿Cómo cambiar el estado (apariencia) de la ventana?
Con los métodos de la clase JFrame que nos permiten
- Cambiar el título de la
ventana - Cambiar el tamaño de la
ventana - Agregar componentes gráficos

Métodos del frame
- setSize ( ancho, alto )
- setResizable ( true/false )
- setTitle ( titulo )
- setDefaultCloseOperation (EXIT_ON_CLOSE)
- setVisible ( true/false )
- setLayout( layout )
- add ( componente )
DISTRIBUCIONES
DISTRIBUCIONES
- Permiten darle un orden a la interfaz gráfica y determinar en qué posición se ubica cada uno de sus componentes.
- Partimos de que las aplicaciones tienen una ventana principal (JFrame)

DISTRIBUCIONES
Al tener la interfaz principal (ventana principal), debemos dividirla en páneles (que en Java son JPanel) según alguna de las siguientes dos distribuciones (Layout):
BorderLayout: distribución de bordes geográficos (norte, sur, este, oeste y centro).
GridLayout: distribución de cuadrícula en la que cada casilla tiene la misma dimensión, se debe especificar la cantidad de filas y columnas de la cuadrícula.


DISTRIBUCIONES
Al tener la interfaz principal (ventana principal), debemos dividirla en páneles (que en Java son JPanel) según alguna de las siguientes dos distribuciones (Layout):
BorderLayout
GridLayout
add( panelVehiculo, BorderLayout.NORTH );Objeto que se va a adicionar
Zona (posición relativa dentro de la ventana) donde se va a adicionar el objeto. Es una constante de la clase BorderLayout.
Al agregar un componente a la ventana, NO SE DEBE especificar la posición. Esta es asignada en el orden de llegada (fila 1, fila 2, …)
setLayout( new GridLayout ( 4, 3 ) );
add( panelVehiculo);
Utiliza el tamaño definido para cada uno de los componentes y asigna TODO el espacio sobrante al componente que se encuentre en la zona del centro
DISTRIBUCIONES

¿Para el
DISTRIBUCIONES

Norte
centro
sur
este
DISTRIBUCIONES
A su vez cada pánel tiene su distribución
El panel ubicado en el Norte de interfaz principal, su distribución puede ser BorderLayout (con una imagen en el centro ó GridLayout (con tamaño 1x1).

DISTRIBUCIONES
A su vez cada pánel tiene su distribución
Panel ubicado en Sur de interfaz principal, su distribución es GridLayout, con tamaño 1x3 (1 fila y 3 columnas).

Panel ubicado en Este de Interfaz principal, su distribución es GridLayout, con tamaño 6x1 (6 filas y 1 columna).

DISTRIBUCIONES
A su vez cada pánel tiene su distribución
Panel ubicado en Centro de Interfaz principal, su distribución es BoderLayout, con tamaño 3 sub-páneles.

centro
oeste
sur
DISTRIBUCIONES
A su vez cada pánel tiene su distribución

centro
sur
- El sub-panel Oeste puede tener distribución BorderLayout con la imagen en el Centro, ó GridLayout de tamaño 1x1.
oeste
DISTRIBUCIONES
A su vez cada pánel tiene su distribución

centro
- El sub-panel Sur tiene distribución GridLayout, con tamaño 1x4 (1 fila y columnas).
oeste
DISTRIBUCIONES
A su vez cada pánel tiene su distribución

- El sub-panel Centro tiene distribución GridLayout, con tamaño 5x2 (5 filas y 2 columnas). Se puede decir que el tamaño es 6x2 si se cuenta los espacios vacíos debajo de “está en remate”.
sur
Un Panel
- Se encarga de agrupar elementos gráficos por contenido y uso
- Facilita al usuario su localización y su uso
- Cada panel se implementa como una clase aparte en el modelo
- PanelInformacion
- PanelOpciones
- PanelCalificacion
clase interfazmuseo
/**
* Ventana principal de la aplicación.
*/
public class InterfazMuseo extends JFrame
{
// -----------------------------------------------------------------
// Atributos
// -----------------------------------------------------------------
/**
* Clase principal del mundo.
*/
private Museo museo;
// -----------------------------------------------------------------
// Atributos de la interfaz
// -----------------------------------------------------------------
/**
* Panel con la imagen del banner.
*/
private PanelImagen panelImagen;
/**
* Panel con la información de la obra.
*/
private PanelInformacion panelInformacion;
/**
* Panel para calificar la obra.
*/
private PanelCalificacion panelCalificacion;
/**
* Panel para ejecutar las extensiones a la aplicación.
*/
private PanelOpciones panelOpciones;clase interfazmuseo
public InterfazMuseo( )
{
setLayout( new BorderLayout( ) );
panelInformacion = new PanelInformacion( this );
add( panelInformacion, BorderLayout.CENTER );
panelCalificacion = new panelCalificacion( );
add( panelOpciones, BorderLayout.EAST );
panelOpciones = new panelOpciones( this );
add( panelOpciones, BorderLayout.SOUTH );
}Atributo panelInformacion de la clase InterfazMuseo
Llamado al constructor de la clase PanelInformacion
clase interfazmuseo
public InterfazMuseo( )
{
setLayout( new BorderLayout( ) );
panelInformacion = new PanelInformacion( this );
add( panelInformacion, BorderLayout.CENTER );
panelCalificacion = new panelCalificacion( );
add( panelOpciones, BorderLayout.EAST );
panelOpciones = new panelOpciones( this );
add( panelOpciones, BorderLayout.SOUTH );
}Parámetro
CONCEPTO NUEVO!
Es una variable de JAVA
Hace referencia al objeto que está ejecutando un método
Es la ventana principal, (objeto de la clase InterfazMuseo, que es el “padre” del panel)
CREación de la interfaz
Creación de la interfaz
- Para el Museo, definimos la distribución BorderLayout para la ventana principal (interfaz principal) de la aplicación.
- En Eclipse deben crear 5 clases: 1 para la interfaz principal y una para cada panel (los sub-paneles del panel centro no necesitan clases a parte).
- La primera clase en ser creada debe ser la Interfaz principal, por convención el nombre debe ser Interfaz+Nombreaplicacion, por ejemplo, para el Museo se llamará InterfazMuseo.
- Al crearla debe aparecer algo como lo siguiente:
Creación de la interfaz

- Dado que estamos hablando de la ventana principal, la clase InterfazMuseo DEBE extender JFrame (no olvidar importar JFrame)

Creación de la interfaz
- A continuación se crea 1 clase por cada panel, por convención el nombre de cada panel debe ser Panel+información que contiene por ejemplo para este caso:
- Norte: PanelImagen
- Centro: PanelInfoObra
- Este: PanelCalificaciones
- Sur: PanelOpciones

Creación de la interfaz
- Cada una de las clases creadas para los páneles DEBE extender JPanel (no olvidar importar):




Creación de la interfaz
- Luego se procede, dentro del constructor de InterfazMuseo, a crear y agregar los paneles como se definió anteriormente, los páneles que tienen botones, necesitan como parámetro la InterfazMuseo, para poder ejecutar sus acciones, por lo que se utiliza el parámetro this (que hace referencia a la clase actual, en este caso InterfazMuseo).

- Los errores que marcan en rojo se resolverán en el paso siguiente cuando definamos los constructores de cada pánel.
Creación de la interfaz
- Para los páneles que no tienen botones, se define un constructor sin parámetros. (PanelImagen)

- Para los páneles que tienen botones se define un atributo de tipo InterfazMuseo y un constructor con un parámetro de tipo InterfazMuseo.




Creación de la interfaz
- Al guardar los cambios en los páneles (Ctrl+Shift+S) se solucionarán los problemas en el constructor de InterfazMuseo.

Creación de la interfaz
- En la clase InterfazMuseo se debe crear un método que Eclipse (y Java) necesita para poder ejecutar el proyecto como una aplicación. Este método se llama “main” y siempre es:
- public static void main (String [] pArgs)

Adentro del método se crea una nueva InterfazMuseo y se vuelve visible.
Creación de la interfaz
- Al ejecutar, la aplicación debe lucir asi:

Creación de la interfaz
-
Métodos para usar dentro de los páneles:
- setSize(ancho, alto); aunque con el BorderLayout y GridLayout ocupan todo el espacio que pueden.
- setLayout (Layout);
-
setBorder (Border); para darle un borde al pánel, para los ejercicios de Nivel 5 se utilizan borders con título que en Java se llaman TitledBorder.
- setBorder( new TitledBorder(“Titulo”));
Creación de la interfaz
- Para el museo al definir el borde de cada pánel, dentro del constructor de cada pánel se tendrá:
- PanelOpciones:
- PanelInfoObra:
- PanelCalificaciones:



Creación de la interfaz
- Al poner bordes como fueron definidos anteriormente la interfaz queda asi:

- El PanelCalificaciones ocupará espacio cuando se le agreguen componentes.
Creación de la interfaz
Para mostrar ventanas de mensajes al usuario, se utiliza la clase JOptionPane y dos métodos
- showMessageDialog: para mostrar mensaje con información (usualmente mensaje de error).
- showInputDialog: para pedirle al usuario que ingrese algún valor (texto o números).
En el manejo de eventos se explicará como utilizar cada uno de estos métodos.
Manejo de eventos

usuario
interfaz usuario
modelo del mundo


evento
llamada a un método
El usuario ejecuta acciones:
- Hace click sobre un botón
- Chequea una caja de chequeo
- Selecciona una opción de un Menú
Las acciones se convierten en objetos llamados eventos:
- Describen lo que el usuario hizo
- Se puede analizar su contenido para que el programa reaccione de acuerdo a la acción del usuario.
Hay tres pasos que se deben seguir para decidir la manera de manejar un evento con un botón de la interfaz
Decidir el nombre del evento y asociarlo con un botón.
Implementar el método que va a atender el evento
Declarar que el panel es el responsable de atender los eventos de sus botones.
1
2
3
Decidir el nombre del evento y asociarlo con un botón.
1
public class PanelConsultas extends JPanel implements ActionListener
{
// -----------------------------------------------------------------
// Constantes
// -----------------------------------------------------------------
/**
* Constante para calcular la edad del empleado.
*/
private final static String CALCULAR_EDAD = "CALCULAR EDAD";
/**
* Constante para calcular la antigüedad del empleado.
*/
private final static String CALCULAR_ANTIGUEDAD = "CALCULAR ANTIGUEDAD";
...
public PanelConsultas( InterfazEmpleado pPrincipal )
{
...
btnEdad = new JButton( );
btnEdad.setText( "Calcular edad" );
btnEdad.setActionCommand( PanelConsultas.CALCULAR_EDAD );
btnAntiguedad = new JButton( );
btnAntiguedad.setText( "Calcular antigüedad" );
btnAntiguedad.setActionCommand( PanelConsultas.CALCULAR_ANTIGUEDAD );
}
}En la clase del panel que contiene el botón
Se declaran constantes para los nombres de los eventos
En el método constructor del panel
Se asocian los nombres de los eventos con cada botón
Atender el evento
2
public class PanelConsultas extends JPanel implements ActionListener
{
...
/**
* Manejo de los eventos de los botones.
* @param pEvento Acción que generó el evento. pEvento != null.
*/
public void actionPerformed( ActionEvent pEvento )
{
String command = pEvento.getActionCommand( );
if( command.equals( CALCULAR_EDAD ) )
{
principal.calcularEdadEmpleado( );
}
else if( command.equals( CALCULAR_ANTIGUEDAD ) )
{
principal.calcularAntiguedadEmpleado( );
}
else if( command.equals( CALCULAR_PRESTACIONES ) )
{
principal.calcularPrestacionesEmpleado( );
}
}
}Agregar una declaración en el encabezado de la clase del panel que contiene el botón (para que pueda “percibir” las acciones del usuario)
Atender el evento
2
public class PanelConsultas extends JPanel implements ActionListener
{
...
/**
* Manejo de los eventos de los botones.
* @param pEvento Acción que generó el evento. pEvento != null.
*/
public void actionPerformed( ActionEvent pEvento )
{
String command = pEvento.getActionCommand( );
if( command.equals( CALCULAR_EDAD ) )
{
principal.calcularEdadEmpleado( );
}
else if( command.equals( CALCULAR_ANTIGUEDAD ) )
{
principal.calcularAntiguedadEmpleado( );
}
else if( command.equals( CALCULAR_PRESTACIONES ) )
{
principal.calcularPrestacionesEmpleado( );
}
}
}Implementar en la clase del panel que contiene el botón, el método especial actionPerformed
Atender el evento
2
public class PanelConsultas extends JPanel implements ActionListener
{
...
/**
* Manejo de los eventos de los botones.
* @param pEvento Acción que generó el evento. pEvento != null.
*/
public void actionPerformed( ActionEvent pEvento )
{
String command = pEvento.getActionCommand( );
if( command.equals( CALCULAR_EDAD ) )
{
principal.calcularEdadEmpleado( );
}
else if( command.equals( CALCULAR_ANTIGUEDAD ) )
{
principal.calcularAntiguedadEmpleado( );
}
else if( command.equals( CALCULAR_PRESTACIONES ) )
{
principal.calcularPrestacionesEmpleado( );
}
}
}parámetro del método: evento ocurrido en el panel
Atender el evento
2
public class PanelConsultas extends JPanel implements ActionListener
{
...
/**
* Manejo de los eventos de los botones.
* @param pEvento Acción que generó el evento. pEvento != null.
*/
public void actionPerformed( ActionEvent pEvento )
{
String command = pEvento.getActionCommand( );
if( command.equals( CALCULAR_EDAD ) )
{
principal.calcularEdadEmpleado( );
}
else if( command.equals( CALCULAR_ANTIGUEDAD ) )
{
principal.calcularAntiguedadEmpleado( );
}
else if( command.equals( CALCULAR_PRESTACIONES ) )
{
principal.calcularPrestacionesEmpleado( );
}
}
}Se analiza cuál fue el evento que ocurrió
Se llaman métodos de la ventana principal
Cada vez que el usuario hace click en un botón del panel, se ejecuta el método actionPerformed
Decir que el panel es el encargado de atender el evento
3
Mediante el método addActionListener de la clase JButton. Se le pasa como parámetro del método el objeto que lo está ejecutando, es decir el panel mismo
public PanelConsultas( InterfazEmpleado pPrincipal )
{
...
btnEdad = new JButton( );
btnEdad.setText( "Calcular edad" );
btnEdad.setActionCommand( PanelConsultas.CALCULAR_EDAD );
btnEdad.addActionListener( this );
btnAntiguedad = new JButton( );
btnAntiguedad.setText( "Calcular antigüedad" );
btnAntiguedad.setActionCommand( PanelConsultas.CALCULAR_ANTIGUEDAD );
btnAntiguedad.addActionListener( this );
btnPrestaciones = new JButton( );
btnPrestaciones.setText( "Calcular prestaciones" );
btnPrestaciones.setActionCommand( PanelConsultas.CALCULAR_PRESTACIONES );
btnPrestaciones.addActionListener( this );
}Arquitectura y distribución de responsabilidades
Por dónde comienza la ejecución del programa?
- Por el método main de la ventana principal.
-
Su función: crear una instancia de la ventana y hacerla visible en la pantalla
public static void main( String[] args ) {
InterfazEmpleado interfaz = new InterfazEmpleado( );
interfaz.setVisible( true );
}Quién crea el modelo del mundo?
-
La interfaz
-
En el método constructor de la ventana principal
public InterfazEmpleado( )
{
setTitle( "Sistema de un empleado" );
setSize( 600, 580 );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// Construir el empleado
empleado = new Empleado( );
...
}Arquitectura propuesta
Los requerimientos funcionales se implementan en la ventana principal:
- Hay UN método por REQUERIMIENTO
- La ventana principal coordina todas las acciones
Arquitectura propuesta
- El usuario realiza una acción.
- El panel reacciona a su evento con el ActionPerformed: Llama un método de la ventana principal. Cada requerimiento tiene su método.
- El método de la ventana principal completa la información: La saca de otros páneles y verifica que la información esté completa y válida.
- El método pide al modelo del mundo que haga una modificación o calcule un valor.
-
Si se pidió una modificación, se llaman los métodos que retornan los nuevos valores que se deben desplegar
-
Pide a todos los paneles que tienen información que pudo haber cambiado, que actualicen sus valores (REFRESCO)
Para convertir la cadena de caracteres al tipo adecuado …
A un número:
- Se usa el método parseInt de la clase Integer de Java.
- Se captura la excepción NumberFormatException que lanza el método parseInt si la cadena no se puede convertir en número.
try
{
int nCantidad = Integer.parseInt ( strCantidad );
}
catch (NumberFormatException e)
{
// Mensaje al usuario
}Para convertir la cadena de caracteres al tipo adecuado …
A mayúsculas/minúsculas (y otros tipos de conversión de cadenas de caracteres):
La clase String de Java provee métodos para transformar la cadena de caracteres tecledada por el usuario (y en general cualquier cadena de caracteres):
- toLowerCase(): pasa a minúsculas
- toUpperCase(): pasa a mayúsculas
- Trim: elimina espacios en blanco al inicio y final de la cadena
PRACTIQUEMOS

¿PREGUNTAS?
¿PREGUNTAS?
- Text
GRACIAS
- J. Villalobos and R. Casallas, Fundamentos de Programación. https://cupi2.virtual.uniandes.edu.co/libro-del-curso-pdf/libro-completo
- Icons made by wanicon from Flaticonis licensed by Creative Commons BY 3.0
Nivel5
By nychi713
Nivel5
- 623