410 likes | 756 Views
Java Look-and-Feel Design Guidelines – Part IV. Eileen Kraemer University of Georgia CSCI 4800/600. Previously, we talked about …. Applet v. Application Placement of applets Designing for accessibility Checking for accessibility Usability testing Internationalization / localization
E N D
Java Look-and-Feel Design Guidelines – Part IV Eileen Kraemer University of Georgia CSCI 4800/600
Previously, we talked about … • Applet v. Application • Placement of applets • Designing for accessibility • Checking for accessibility • Usability testing • Internationalization / localization • Creating/using resource bundles
Designing for accessibility • Provide accessible names, accessible descriptions • Use mnemonics and keyboard shortcuts • All interface components must be keyboard traversable • Assign initial keyboard focus • Specify tab traversal order • Don’t customize fonts or colors unnecessarily • If necessary, use properties to specify colors, fonts • Use dynamic GUI layout • Custom components must implement accessible
Now, … • … let’s look at the “nuts and bolts” of accomplishing these goals
The Java Accessibility API (JAAPI) • standard extension in all releases of the Java 2 platform • component can utilize this extension by implementing the Accessible interface • only one method call: getAccessibleContext() • returns an instance of AccessibleContext • specific to the component • provides the info and functionality to enable accessibility • AccessibleContext • info about the component's role (button, checkbox, etc.) • accessible name (more on this soon) • Number of children, & more • Can generate accessibility events when a noteworthy event has occurred. • All of the standard JFC/Swing components implement the Accessible interface
Accessible name, description: how used • accessible name • succinct explanation of component’s purpose • assistive technology will often present (speak) the name of each component encountered by a user • accessible description • more verbose explanation • provide in cases where additional info needed • assistive tech retrieves when user requests it
Accessible name: how to set • JFC/Swing components with non-editable text (menu items, buttons, etc.) have accessible name set automatically • Other components need to have accessible name set by developer • If the component has a label: JTextField text = new JTextField(20); JLabel label = new Label("Address Line 1"); label.setLabelFor(text); // ... Add the text and label to a Container • For ImageIcons , create using: ImageIcon(URL url, String name);
Accessible description: how to set • Accessible descriptions set automatically by setting tooltiptext: JComponent.setTooltipText( ) • If component has no label or tooltip, directly set name & description: • permanently overrides values pulled from label or tooltip AccessibleContext context = component.getAccessibleContext(); context.setAccessibleName("Zip"); context.setAccessibleDescription("Recipient's Zip Code");
Don’t Customize Fonts or Colors Unnecessarily • JFC/Swing components/ applications automatically inherit font and color properties from desktop and user prefs. • In most cases, get good results by accepting user's preferences.
But, if you have to specify colors and fonts …. • Use a properties file • Example: • want flight simulator to have a red "stop" button in Western countries • define a property, • store it in a file, flightsim.properties: flightsim.stop.color=#ff0000
Then, use the properties: • The program can load properties file as a ResourceBundle: ResourceBundle resources = null; Color stopColor = Color.red; // the default try { resources=ResourceBundle.getBundle("flightsim"); String colorString = resources.getString("flightsim.stop.color"); stopColor = Color.decode(colorString); // the specified } catch (MissingResourceException missingException) { // Report the error, according to severity } // stopColor has now been customized
Use Dynamic GUI Layout • Don’t call setSize() with constant values. • defeats dynamic layout • resulting application won’t adapt properly to users' settings. • Instead, adjust the size of each JFrame, JDialog, and JWindow at creation and each time its contents change window.setSize(window.getPreferredSize()); • allows all nested layout managers to affect the size and position of each object at runtime. • If component’s preferred size is not acceptable(rare), call setSize() with a value between getMinimumSize() and getMaximumSize().
Dynamic LayoutManagers • position graphical objects relative to each other • changes in size are handled automatically • components never obscure one another. • All JFC/Swing layout managers are dynamic (BorderLayout, FlowLayout, GridBagLayout, etc.) setLayout(null); // Don’t do this!! • Requires manually setting (x,y) of every component. • interface won’t work right with many accessibility options, internationalization , user-defined preferences.
Custom Layout Managers • Implement LayoutManager2 interface • (old LayoutManager interface is obsolete). • Components should be positioned relative to each other when the toolkit invokes layoutContainer() on the custom layout manager.
All Interface Components Must Be Keyboard Traversable • … because many people can’t use a pointing device effectively • Pressing tab key should move input focus from component to component • shift-tab should move focus in opposite direction.
How to implement? • default FocusManager sets focus order : left-to-right and top-to-bottom. • If component shouldn’t receive input focus, create a subclass and override isFocusTraversable() to return false. • Invoke setNextFocusableComponent() on each JComponent to "hard-wire" the focus traversal order. • Messy to do this on some components and have others use the default ordering. If used, invoke on all JComponents in a window. • Implement a subclass of java.awt.FocusManager and install it with the static method FocusManager.setCurrentManager().
Use Mnemonics • Mnemonics • underlined characters that appear in menu items and on the buttons in some dialog boxes. • can only be activated when the item is visible and does not require a modifier key (e.g., the user does not need to press the Alt key). • If keyboard use is to be practical, then All menu items must have mnemonics menu = new JMenu(); menu.setText(resources.getString("fileMenu.label")); menu.setMnemonic( resources.getString("fileMenu.mnemonic").charAt(0)); item = new JMenuItem(); … item.setMnemonic( resources.getString("menuitem.file.new.mnemonic").charAt(0)); …
Use Accelerators • displayed on menu items or buttons in parentheses after the item's text [e.g., "Save (Ctrl+S)"]. • requires the use of a modifier key • can be activated any time the application's window has the input focus. • … item = new JMenuItem(); item.setAccelerator(KeyStroke.getKeyStroke( resources.getString("menuitem.file.new.accelerator"))); …
Custom Components Must Implement Accessible • All standard JComponent subclasses implement this interface and do everything necessary to be accessible • All custom components should extend a standard class as far down the JFC/Swing inheritance hierarchy as possible. • For example, you want round buttons • First try to extend JButton, override all paint methods, add support for any new properties. • If JButton is too restrictive, then try to extend JButton's superclass, AbstractButton. • Only if AbstractButton is too restrictive should you extend directly from JComponent. • JComponent doesn’t implement Accessible, so subclass must do more work to work w/ assistive technologies. • Some methods do exist in JComponent to help: getAccessibleParent() and getAccessibleName() will work properly for most JComponent subclasses, with no additional code (other than 'implements Accessible').
Custom components, continued • must express its accessible role as specifically as possible. See: http://java.sun.com/j2se/1.4.2/docs/api/javax/accessibility/AccessibleContext.html • Each JFC/Swing class contains a protected inner class that actually does the accessibility work, and the root class is JComponent.AccessibleJComponent • To extend accessibility behavior of subclass, create a protected inner class that extends the inner class of the superclass • override getAccessibleContext() to create an instance of this new accessibility class.
Example public class WarningLight extends JComponent implements Accessible { public AccessibleContext getAccessibleContext() { // variable accessibleContext is protected in superclass if (accessibleContext == null) { accessibleContext = new AccessibleWarningLight(); } return accessibleContext; } protected class AccessibleWarningLight extends AccessibleJComponent { public AccessibleRole getAccessibleRole() { return AccessibleRole.ALERT; } … // Implementation of WarningLight omitted... }
Test Cases • 1. Don't touch your mouse • Bring up each window and popup in your application and attempt to visit every component using only the Tab key on the keyboard. • Use the application without touching the mouse • Verify that: • Application’s features are all available • Frequently-used functionality is directly accessible via an accelerator • All menu items have mnemonics
Test Cases • 2. Change the default font and color • Choose a font of 24 points or larger, and colors other than the default. • Bring up each window of the application and verify that screen objects do not overlap and that the colors are correct. • If overlapping occurs, check the code that interacts with the LayoutManager in that window.
Test Cases • Try using a low-vision look-and-feel • Here’s a sample LowVisionMetalLookAndFeel.java • Compile the file • Add this code to your application: import LowVisionMetalLookAndFeel; // ... code omitted try { UIManager.setLookAndFeel("LowVisionMetalLookAndFeel"); } catch (Exception ex) { System.out.println("Failed loading Low Vision Metal Look and Feel"); ex.printStackTrace(System.out); }
Test Cases • 3. Use a screen reader • Download and install a trial version of a screen reader that works with Java applications, (more/better links coming soon) • http://cap.ic.gc.ca/english/learning.html • Bring up each window in your application and tab to every component, verifying that you hear a reasonable description of each component as it receives the input focus. • Turn your display off. • Try to use your application in this mode, accessing both core functionality and more lightly-used features.
Internationalization • Identify Culturally Dependent Data • Isolate Translatable Text in Resource Bundles • Deal with Compound Messages • Format Dates and Times • Use Unicode Character Properties • Compare Strings Properly • Convert Non-Unicode Text
Nuts and Bolts … • Creating and accessing resource bundles … • ResourceBundle objects contain locale-specific objects. • When you need a locale-specific object, you fetch it from a ResourceBundle, which returns the object that matches the end user's Locale.
The ResourceBundle Class • each ResourceBundle is a set of related subclasses that share the same base name. • Example: ButtonLabel // base_name ButtonLabel_de // with language code ButtonLabel_en_GB // with language and country codes ButtonLabel_fr_CA_UNIX // with lang, country, and variant codes
To select a ResourceBundle • invoke the ResourceBundle.getBundle method. • Example: Locale currentLocale = new Locale("fr", "CA", "UNIX"); ResourceBundle introLabels = ResourceBundle.getBundle(“ButtonLabel”, currentLocale);