FeaturesPluginsDocs & SupportCommunityPartners

Initially created by: Jan Benway October 12, 2001
Last modified by: Jan Benway October 15, 2001

Dealing with Unfocusable Components - by Design

This document describes how to make "standalone text" accessible to screenreaders and usable by all other users.

The Problem

The problem is that in many dialog boxes, important text is stored in JLabel components or disabled JTextAreas. Screen readers cannot read text that is not in focusable components.

JLabels are not focusable unless they are connected (using labelFor) with another component (such as a JComboBox).

Disabled JTextAreas are not focusable. The developer can make a JTextArea focusable by making it non-editable but enabled. This is problematic, though, because sighted users can accidentally put the keyboard focus on these areas. This causes a usability problem. There is seldom any reason for sighted users to put the focus there. Also, the JDK doesn't provide any visual feedback when the focus is there. Making the problem worse, users cannot use Tab to move the focus away from the component. Control-Tab is needed.

The Solution

There are two solutions to this problem. Which solution should be used in which dialog box depends on how the components are being used.

Uneditable text tends to fall into two categories: Text that is displaying uneditable parameters or status, and text that gives instructions. Which solution you use depends on which type of text you have.

Uneditable Parameters and Status

Dialog boxes often display dynamic information as background information or status for the user. If this information is displayed in JLabel components or other unfocusable components, screenreaders will not have access to it.

Here is an example:

In the dialog box above, most of the information is read-only, but the read-only information is labeled. So, the read-only information should be put into uneditable JTextFields. The labels for these JTextFields should be set with labelFor and mnemonics should be assigned.

This has been done in the Class wizard:

Here, the screenreader users (or any user) can focus the value for "Name" by using the N mnemonic, or by tabbing to the component. The same things for the value for "Package" and for "Class Declaration".

If there is no JLabel labeling the unfocusable information

In some cases, dynamic information is contained in a JLabel that has no static label.

For example, see this dialog box:

In this case, the text "You are already logged in" has no static label. Consider whether a logical label could be added so that a mnemonic could be assigned. In this case, perhaps a label with the text "Login Status:" would be appropriate.

In some cases, such information could be treated the same way as instructional text and be added to the accessible description of the dialog box. Consider what makes sense in your case.

Guidelines:

1. Put dynamic read-only information into uneditable JTextFields.

2. Use the default appearance of these JTextFields (gray background, visible border)

3. Assign the labelFor and mnemonic appropriately for the static JLabel associated with the JTextField.

4. Automatically select the text in the JTextField when that component gains focus. This is not the default behavior -- the developer must explicitly implement it. This is required by the Java Look and Feel Design Guidelines.

5. Do not make the JTextField disabled, only uneditable. Making the component disabled makes it unfocusable, and also difficult to read. Making the component uneditable keeps it focusable and it has the added benefit of allowing users to copy the text out of these components, which can be useful in some cases (for instance, it is useful if a long path name is displayed).

6. Assign the initial focus to some editable component, if there is one. If the first component in a dialog box is a non-editable textfield (as in both examples shown above), set the initial focus elsewhere -- on the first component a user is like to use. Leave the non-editable text fields in the tab order.

7. Whenever the value of a parameter changes, a VISIBLE_PROPERTY_CHANGE event should be generated to cue the assistive technology to read it again.

How to Implement These Guidelines

initComponents();
jLabel1.setDisplayedMnemonic('L');
jTextField1.selectAll();    //use this but next part with Listener is recomended
jTextField1.addFocusListener(new java.awt.event.FocusListener() {
    public void focusGained(java.awt.event.FocusEvent e) {
        jTextField1.selectAll();
    }
    public void focusLost(java.awt.event.FocusEvent e) {
    }
});

If you have many JTextField in dialog, you could use this syntax:

initComponents();
jTextField1.selectAll();
jTextField2.selectAll();
jTextField1.selectAll();
jTextField1.addFocusListener(new CheckSelectAll());
jTextField2.addFocusListener(new CheckSelectAll());
jTextField3.addFocusListener(new CheckSelectAll());
.
.
.
class CheckSelectAll implements java.awt.event.FocusListener {    // Inner class
    public void focusGained(java.awt.event.FocusEvent e) {
        ((javax.swing.JTextField)e.getComponent()).selectAll();
    }
        public void focusLost(java.awt.event.FocusEvent e) {
    }
}

 

Open Issue

There is no visible feedback when a uneditable textfield has focus and is why we are selecting the entire text (JTextField.selectAll();)of an uneditable area.. This is a JDK problem: 4512626

 

Instructional Information

Many dialog boxes, and especially wizard pages have information that describes the dialog box as a whole.

For example, the New Class Wizard contains this page:

This page has two JLabels that are not focusable: The page title and the instruction text. The text of both of these should be added to the AccessibleDescription of the page. This way, the user with a screenreader can issue an instruction to hear a description of the dialog box. The steps text is added to the accessible description automatically by the WizardDescriptor, so each developer needn't handle this. The instruction text does need to be handled by the wizard developer. This accessibleContext should be set for the JPanel. It is forwarded to the WizardDescriptor in openide.

If the information applies to only part of the dialog box

In some cases, instructional text doesn't describe the dialog box as a whole, but only on component or set of components.

For example, in this dialog box, there is a label that describes the "Add recursively" checkbox:

In this case, the instructional text should be added as the labelFor for the checkbox. If this instructional text is a JLabel then use setLabelFor to link the text to the component it is describing; AccessibleDescription will be set by default. If the instructional text is a JTextArea then set the AccessibleDescription.

In some cases, instructional text describes a group of components. For example:

In this case, place the group of components on their own JPanel. Then, assign the instruction text as the labelFor for the JPanel.

Guidelines

1. Assign text that describes the whole dialog box as the accessible description of that dialog box. DialogDescriptor, NotifyDescriptor and WizardDescriptor will use AccessibleContext (Name,Description) assigned to obtained JPanel.

2. Assign text that describes smaller sections of the dialog box as labelFor (which will set the AccessibleDscription) the component it describes. If it describes a group of components, place those components on a sub-panel and assign the text to that sub-panel.

3. The text of the AccessibleDescription should be placed in the I18N bundle file. If text is written especially for accessible names and descriptions, use the NetBeans naming convention to prefix the bundle: Use the prefix ACS_. If it is necessary to make a distinction between accessibleName and accessibleDescription use ACSN_ and ACSD_.

4. If the instruction text is in a JTextArea, make the JTextArea disabled and non-editable. Make sure to set the appropriate properties of the JTextArea. Then, add the text to the AccessibleDescription as with the JLabel example.

jTextArea.setWrapStyleWord (true);
jTextArea.setLineWrap (true);
jTextArea.setEnabled (false);
jTextArea.setEditable (false);
jTextArea.setOpaque (false);
jTextArea.setFont (javax.swing.UIManager.getFont ("Label.font"));
jTextArea.setDisabledTextColor (javax.swing.UIManager.getColor ("Label.foreground"));

5. The steps pane on wizards can be left unfocusable by developers implementing wizards. All text available there will also be available as the page title for each page. OpenIDE assigns the text in the following and preceding steps as the AccessibleDescription for the Next and Back buttons, respectively. Developers implementing individual wizards do not need to worry about it.

How to Implement These Guidelines

<code here>

<Need concrete example of how to assign this in NetBeans. Need example for: Regular dialog, property editor, and wizard page>

Open Issue

The NetBeans team has not been able to get JAWS to read these accessible descriptions on entire dialog boxes (only individual components). Further testing is needed.

Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by