Download - Usabilidad en Interfaces de Escritorio
UT4. USABILIDAD Y ACCESIBILIDAD
Desarrollo de Interfaces
CFGS DAM
Juan V. Carrillo
PRINCIPIOS DE DISEÑO: USABILIDAD
1. Adoptar el punto de vista del usuario. – Ver la interfaz desde fuera y en relación con las tareas
que va a realizar el usuario.
2. Realimentación: La interfaz debe dar inmediatamente alguna respuesta a cualquier acción del usuario. – Movimiento del cursor.
– Resaltar la opción elegida de un menú.
– Comunicar el éxito o fracaso de una operación.
– Controles deshabilitados si no se pueden usar
– Para mostrar información: JTextField (evitar label)
3. Consistencia u homogeneidad: Seguir unas regla uniformes en cuanto a la forma de operar y la presentación de la información. – Las ordenes genéricas como copiar, mover, editar,
etc, deben poder aplicarse sobre cualquier tipo de objeto y de la misma forma.
– Los mensajes de error deben aparecer siempre en la misma posición y con el mismo formato.
OBJETIVO: Que el usuario pueda generalizar sus conocimientos de un aspecto de la interfaz a otros aspectos.
4. Tratamiento de errores: Minimizar la posibilidad de cometer errores. – Usar preferentemente controles que restrinjan los valores
a introducir.
– Inhibir controles que representan acciones no permitidas.
– Pedir la confirmación de operaciones peligrosas.
– Evitar los controles que sean físicamente difíciles de manejar (controles muy pequeños, menúes emergentes o submenúes con muchas opciones).
• En caso de error, dar información suficiente y adaptada al punto de vista del usuario, tanto a sus objetivos como a sus conocimientos.
• Facilitar la recuperación en caso de error (Ctrl + Z)
5. Minimizar la necesidad de memorización:
– Usar controles gráficos
– Limitar la carga de información a corto plazo: información necesaria en pantalla (7±2)
– Utilizar nombres y símbolos autoexplicativos y fáciles de recordar
6. Diseñar diálogos para conducir a la finalización
– Crear sistemas claros de conducción hasta el final del proceso de las secuencias de acción del usuario.
– Ej: Al final de una compra aparece una ventana o un texto que te indica que tu compra a finalizado.
7. Usar metáforas
• Similitudes con otros mecanismos y procesos conocidos por el usuario que aplica lo que ya conoce a los elementos y relaciones dentro de un dominio no familiar (Autoexplicativa)
• El ejemplo más tradicional: el escritorio con sus iconos representando carpetas y documentos.
JAVA SWING: BORDES
Bordes
• Principio de diseño 5: minimizar la necesidad de memorización
• Mejoran la comprensión
http://docs.oracle.com/javase/tutorial/uiswing/components/border.html
Crear Bordes
• Los bordes se pueden establecer sobre cualquier Jcomponent con el método setBorder
JPanel pane = new JPanel();
pane.setBorder(BorderFactory.
createLineBorder(Color.black));
• BorderFactory proporciona todos los bordes que se pueden crear con Swing
T
I
P
O
S
D
E
B
O
R
D
E
S
EJERCICIO
• Añade bordes a tu calculadora para mejorar la usabilidad, agrupando los componentes que actúan juntos
JAVA SWING: FOCUS TRAVERSAL POLICY (TABORDER)
Taborder
• Principio de diseño 3: consistencia u homogeneidad
• Regla de diseño en cualquier sistema de escritorio: – Al pulsar la tecla TAB no movemos al siguiente control
– Al pulsar la combinación MAY + TAB nos movemos al control anterior
• ¿Cómo controlamos en Swing el taborder? A través del focus traversal policy
http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html
Focus Traversal Policy
• Swing se encarga del taborder de forma automática, y suele hacerlo bien siempre que – Los paneles se agreguen unos dentro de otros de
forma lógica
– Los componentes se agreguen a los paneles de forma ordenada (en el mismo orden en que se realiza el tab)
• En caso contrario, tenemos dos posibilidades – Reordenar los contenedores / componentes
– Crear nuestra propia clase traversal policy
Orden de agregación: Inspector
• TIP: La ventana “Inspector” de NetBeans nos permite ver la jerarquía de contenedores así como el orden de agregación de componentes
Custom Focus Traversal Policy
• Debe extender FocusTraversalPolicy
• Implementa los métodos – getComponentAfter()
– getComponentBefore()
– getDefaultComponent()
– getFirstComponent()
– getLastComponent()
• Para establecerla
frame.setFocusTraversalPolicy
http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/FocusTraversalDemoProject/src/misc/FocusTraversalDemo.java
Obtener el foco al abrir la ventana
• Para asegurarse de que un componente obtiene el foco cuando se abre la ventana, hay que llamar al método requestFocusInWindow ANTES de que se muestre el frame
button.requestFocusInWindow();
frame.setVisible(true);
Actividad
• Comprueba el taborder de tu calculadora y reordena los controles si no es el correcto
• Establece el botón por defecto a la tecla de igual
JAVA SWING: VALIDACIÓN
Validación
• Principio de diseño 4: minimizar la posibilidad de cometer errores
• Para validar un control en Java hay que extender la clase InputVerifier.
InputVerifier
• Todos los componentes de Swing colaboran entre ellos a la hora de pasarse el foco de unos a otros. Si un componente gana el foco, primero le pregunta al componente que lo pierde (y en concreto a su InputVerifier) si se puede hacer la trasnmisión del foco.
• De esta forma, por ejemplo, si escribimos algo en el JTextField y vamos a pulsar un JButton, el JButton antes de ganar el foco preguntará al InputVerifier del JTextField si se puede cambiar el foco del JTextField al JButton.
• Este es el momento que tiene el JTextField para verificar si su entrada es o no correcta y negarse a perder el foco hasta que lo sea.
• El resultado es que podemos escribir cosas incorrectas, pero no podremos salir del JTextField hasta que la entrada sea correcta.
InputVerifier
• Solamente tiene el método verify, que devuelve un boolean class PassVerifier extends InputVerifier {
public boolean verify(JComponent input) {
JTextField tf = (JTextField) input;
return "pass".equals(tf.getText());
}
}
...
textField.setInputVerifier(new PassVerifier())
Simple Validation API
• Libería SimpleValidation: https://kenai.com/projects/simplevalidation/pages/Home
Ejemplo sencillo //This is our actual UI
JPanel inner = new JPanel();
JLabel lbl = new JLabel("Enter a URL");
JTextField f = new JTextField();
// The component name is used in error messages
f.setName("URL");
inner.add(lbl); inner.add(f);
//Create a ValidationPanel that will show
//any problem with the input at the bottom with an icon
ValidationPanel panel = new ValidationPanel();
panel.setInnerComponent(inner);
//This is all we do to validate the URL:
panel.getValidationGroup().add(f,
Validators.REQUIRE_NON_EMPTY_STRING,
Validators.NO_WHITESPACE,
Validators.URL_MUST_BE_VALID);
//Convenience method to show a simple dialog
if (panel.showOkCancelDialog("URL")) {...}
Simple Validation API Classes
• Validators – Interfaz que implementan los validadores.
• Es posible definir nuestro propio validador implementando la interfaz
• Hay varios validators predefinidos (String no vacío, número positivo, urls, nombre de fichero, IP, etc.)
Validators
• Los validators se pueden usar en cadena
Validator<String> v =
Validators.merge(validator1, validator2,
validator3)
validationGroup.add (theTextField,
Validators.REQUIRE_NON_EMPTY_STRING,
Validators.NO_WHITESPACE,
new MyCustomValidator());
Simple Validation API Classes
• Problems – información a enseñar al usuario information to show the user. – Tienen tres niveles:
FATAL, WARNING e INFO.
• ValidationGroup - Grupo de componentes que se evalúan juntos. – Normalmente hay un único grupo
por panel. – Un cambio en uno de los
componentes provoca la validación de todos
Simple Validation API Classes
• ValidationUI - Interfaz para validar y mostrar un problema al usuario. – Se puede usar la clase ValidationPanel o implementar
nuestro propio panel
EJERCICIO OPCIONAL
• Implementa una interfaz, a través de Simple Validation API, que permita introducir y valide los datos de whois para un dominio – Nombre del propietario (no vacío) – Correo electrónico – DNI (habrá que definir Validator propio) * – Dominio (url)
* http://amatellanes.wordpress.com/2013/07/30/java-validar-dni-nie-o-cif-en-java/ ** http://www.agenciatributaria.es/AEAT.desarrolladores/Desarrolladores/Descarga_de_modulos/Descarga_de_modulos.html
COPIAR / PEGAR
Copiar / Cortar / Pegar
• En los componentes de texto es sumamente sencillo
• Viene implementado a través de la clase DefaultEditorKit
• Solamente hay que declarar las acciones (predefinidas) y Swing se encarga de hacer todo el trabajo
http://docs.oracle.com/javase/tutorial/uiswing/dnd/intro.html
// CORTAR
menuItem = new JMenuItem(new DefaultEditorKit.CutAction());
menuItem.setText("Cut");
menuItem.setMnemonic(KeyEvent.VK_X);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_X, ActionEvent.CTRL_MASK));
mainMenu.add(menuItem);
// COPIAR
menuItem = new JMenuItem(new DefaultEditorKit.CopyAction());
menuItem.setText("Copy");
menuItem.setMnemonic(KeyEvent.VK_C);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_C, ActionEvent.CTRL_MASK));
mainMenu.add(menuItem);
// PEGAR
menuItem = new JMenuItem(new DefaultEditorKit.PasteAction());
menuItem.setText("Paste");
menuItem.setMnemonic(KeyEvent.VK_P);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_V, ActionEvent.CTRL_MASK));
mainMenu.add(menuItem);
EJERCICIO
• Habilita la opción de copiar y pegar en tu calculadora
DESHACER / REHACER
Command Pattern
Memento Pattern
Part 1: Remembering Undoable Edits
• En primer lugar, debemos crear el UndoManager (clase de Swing) que guarda la lista de mementos y los restaura
protected UndoManager undo = new UndoManager();
• Los elementos que contienen texto en un componente Swing implementan lanzan UndoableEditEvent
• Hay que añadir un Listener al document del componente
doc.addUndoableEditListener(
new MyUndoableEditListener());
Part 1: Remembering Undoable Edits
• El listener guarda la edición y actualiza la lista de “undos” y “redos”
protected class MyUndoableEditListener
implements UndoableEditListener {
public void undoableEditHappened(UndoableEditEvent e)
{
//Remember the edit and update the menus
undo.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
}
}
Part 2: Implementing the Undo and Redo Commands
// UNDO Action
public void actionPerformed(ActionEvent e) {
try {
undo.undo();
} catch (CannotUndoException ex) {
System.out.println("Unable to undo: " + ex);
ex.printStackTrace();
}
updateUndoState();
redoAction.updateRedoState();
}
Part 2: Implementing the Undo and Redo Commands
// UNDO Action
protected void updateUndoState() {
if (undo.canUndo()) {
setEnabled(true);
putValue(Action.NAME,
undo.getUndoPresentationName());
} else {
setEnabled(false);
putValue(Action.NAME, "Undo");
}
}
Part 2: Implementing the Undo and Redo Commands
// REDO Action
public void actionPerformed(ActionEvent e) {
try {
undo.redo();
} catch (CannotRedoException ex) {
System.out.println("Unable to redo: " + ex);
ex.printStackTrace();
}
updateRedoState();
undoAction.updateUndoState();
}
Part 2: Implementing the Undo and Redo Commands
// REDO Action
protected void updateRedoState() {
if (undo.canRedo()) {
setEnabled(true);
putValue(Action.NAME,
undo.getRedoPresentationName());
} else {
setEnabled(false);
putValue(Action.NAME, "Redo");
}
}
Part 2: Implementing the Undo and Redo Commands
• Añadir las opciones al menú, con sus accelerators (ctrl + z , ctrl + y)
JMenu menu = new JMenu("Edit");
//Undo and redo are actions of our own creation
undoAction = new UndoAction();
menuItem.add(undoAction);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
// Redo
redoAction = new RedoAction();
menuItem.add(redoAction);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
Ejercicio
• Habilita la opción de deshacer / rehacer en tu calculadora. Solamente tendrá efecto sobre los dígitos que se escriben en el textField. Es decir, que no se podrán deshacer operaciones
http://docs.oracle.com/javase/tutorial/uiswing/examples/components/index.html#TextComponentDemo
USABILIDAD EN VENTANAS
Usabilidad en Ventanas
• Principio de diseño 6: Diseñar diálogos para conducir a la finalización
– Crear sistemas claros de conducción hasta el final del proceso de las secuencias de acción del usuario.
– Ej: Al final de una compra aparece una ventana o un texto que te indica que tu compra a finalizado.
MODO
• Uso de las ventanas modales – Las ventanas secundarias no deberían ser nunca
modales. – Es conveniente que la mayoría de los diálogos sean
modales, pero con la posibilidad de cancelar la operación sin consecuencias.
– Una ventana modal SIEMPRE debe estar encima de cualquier otra ventana de la aplicación. Si se minimiza la aplicación o se cambia a otra aplicación, al volver a ella la ventana modal debe aparecer igualmente encima del resto de las ventanas, y en la misma posición.
Distribución por ventanas
• Distribución de elementos entre la ventana principal y las ventanas secundarias – Colocar las funciones principales en la ventana principal, y las
funciones secundarias en las ventanas secundarias. – Agrupar los datos y funciones que están lógicamente
relacionados.
• Por orden de prioridad: – Se usan al mismo tiempo. – Se usan con el mismo objetivo. – Se usan para manipular el mismo tipo de datos. – Representan el mismo tipo de cosa. – Se modifican o controlan el uno al otro.
Errores frecuentes
• Distribución incorrecta de funciones y datos entre la ventana principal y las secundarias. – (Ejemplo: Colocar una función que se usa con mucha
frecuencia en una ventana secundaria que no está siempre visible)
• Falta de equilibrio: – Ventana principal demasiado ambiciosa.
– Demasiadas ventanas secundarias.
• Ventanas secundarias que bloquean la ventana principal.
¿Cuándo usar diálogos?
• Los diálogos se deben usar sólo para situaciones muy concretas y estar activos durante periodos cortos de tiempo, como ventanas modales: – Introducir los parámetros de una operación. – Pedir confirmación de una operación peligrosa. – Que el usuario decida la acción a tomar ante una situación
inesperada. – Avisar de un error o una situación excepcional
• No se deben usar los diálogos: – Para dar sólo información. – Para comunicar que se ha realizado correctamente una
operación.