How Does Accessibility Work?

   

An assistive technology needs an entry point into a GUI before it can examine the state of each component. Java's accessibility framework specifies this entry point by enforcing the rule that each component's class implement the Accessible interface. For example, the JButton class implements Accessible.

The Accessible interface presents a getAccessibleContext method. When called, this method returns an object whose class implements the AccessibleContext interface. (Each component class contains an inner class that implements AccessibleContext. ) After an assistive technology has this object, it can call various methods to learn more about the component. For example, after a JButton object has been created, an assistive technology can call its getAccessibleContext method to return an AccessibleContext object. It can then call various AccessibleContext methods to learn more about the button.

Figure 17.1 illustrates a component's AccessibleContext object being obtained by an assistive technology.

Figure 17.1. A component's AccessibleContext object can be obtained by calling getAccessibleContext.

graphics/17fig01.gif

The simplest kind of information that an assistive technology can access is a component's name and description. The name is obtained by calling AccessibleContext 's getAccessibleName method and the description is obtained by calling AccessibleContext 's getAccessibleDescription method.

An assistive technology can obtain names and descriptions (and other information) by first obtaining an AccessibleContext object for the main component ”a frame component created from the JFrame class for Swing applications or an applet component created from the JApplet class for Swing applets. It can then call AccessibleContext 's getAccessibleChildrenCount method to obtain a count of accessible components contained by the frame or applet.

Each component is obtained by calling AccessibleContext 's getAccessibleChild method with an index argument ( ranging from zero through one less than getAccessibleChildrenCount 's return value) that identifies the component. This process can continue recursively until all names and descriptions (and other information) have been obtained. Listing 17.1 presents source code for the AccessibilityDemo1 application. This application demonstrates obtaining names and descriptions for all components in a GUI.

Listing 17.1 The AccessibilityDemo1 Application Source Code
 // AccessibilityDemo1.java import javax.accessibility.*; import javax.swing.*; import java.awt.event.*; class AccessibilityDemo1 extends JFrame implements ActionListener {    JButton jb;   AccessibilityDemo1 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                           });      AccessibleContext ac = getAccessibleContext ();      ac.setAccessibleDescription ("Accessibility Demo1 description.");      ac = getRootPane ().getAccessibleContext ();      ac.setAccessibleName ("Root pane");      ac.setAccessibleDescription ("Root pane description");      ac = getGlassPane ().getAccessibleContext ();      ac.setAccessibleName ("Glass pane");      ac.setAccessibleDescription ("Glass pane description");      ac = getLayeredPane ().getAccessibleContext ();      ac.setAccessibleName ("Layered pane");      ac.setAccessibleDescription ("Layered pane description");      ac = getContentPane ().getAccessibleContext ();      ac.setAccessibleName ("Content pane");      ac.setAccessibleDescription ("Content pane description");      JPanel p = new JPanel ();      ac = p.getAccessibleContext ();      ac.setAccessibleName ("Panel");      ac.setAccessibleDescription ("Panel description");      jb = new JButton ("Press Me");      jb.addActionListener (this);      jb.setToolTipText ("Press me for accessibility information.");      p.add (jb);      getContentPane ().add (p);       setSize (200, 75);       setVisible (true);    }    public void actionPerformed (ActionEvent e)    {       dumpInfo (getAccessibleContext ());    }    void dumpInfo (AccessibleContext ac)    {       System.out.println ("Name = " + ac.getAccessibleName ());       System.out.println ("Description = " +                           ac.getAccessibleDescription ());       int nChildren = ac.getAccessibleChildrenCount ();       for (int i = 0; i < nChildren; i++)            dumpInfo (ac.getAccessibleChild (i).getAccessibleContext ());    }    public static void main (String [] args)    {       new AccessibilityDemo1 ("Accessibility Demo1");    } } 

When you click AccessibilityDemo1 's button, the actionPerformed method obtains its frame's AccessibleContext object, and then calls dumpInfo to recursively dump the frame's (and contained components') information to the standard output device. Listing 17.2 presents the output generated by this program.

Listing 17.2 AccessibilityDemo1's Output
 Name = Accessibility Demo1 Description = Accessibility Demo1 description. Name = Root pane Description = Root pane description Name = Glass pane Description = Glass pane description Name = Layered pane Description = Layered pane description Name = Content pane Description = Content pane description Name = Panel Description = Panel description Name = Press Me Description = Press me for accessibility information. 

Notice that each component has both a name and description. The button's name is taken from the label passed as an argument to its constructor. However, not all components are given names when created. For example, the root pane, layered pane, glass pane, content pane, and panels are not given names. To assign a name, your code must obtain an AccessibleContext for the component and then call its setAccessibleName method. Furthermore, because components don't have default descriptions, you must call setAccessibleDescription to assign descriptions to components.

But wait! The setAccessibleDescription method was not called to assign a description to the button. Where did this description come from when getAccessibleDescription was called? The source code holds the answer. Notice the call to setToolTipText. Behind the scenes, the accessibility framework is "smart enough" to use the ToolTip text as the button's description. However, if setAccessibleDescription is called to assign a description to the button, this description is returned by getAccessibleDescription instead of the ToolTip text. (The ToolTip text, as specified by setToolTipText, will still appear when the mouse pointer is positioned over the button.)

In addition to a name and description, components can provide other information. This information includes actions, component layout, hypertext and hyperlinks , icons, selections, table attributes, text attributes, and numeric values. If a component provides one or more kinds of this information, its class implements the appropriate interfaces. These interfaces include

  • AccessibleAction

  • AccessibleComponent

  • AccessibleHypertext and AccessibleHyperlink

  • AccessibleIcon

  • AccessibleSelection

  • AccessibleTable

  • AccessibleText

  • AccessibleValue

AccessibleContext 's getAccessibleAction method returns an AccessibleAction object. After it is obtained, an assistive technology can call AccessibleAction methods to find out what actions are supported by the component. Furthermore, it can also tell this component to perform these actions.

AccessibleAction 's getAccessibleActionCount method can be called to return the number of actions associated with the component. For each action, getAccessibleActionDescription can be called to return a description of that action. Furthermore, the action can be performed by calling doAccessibleAction.

Note

The getAccessibleActionDescription method always returns the literal string click, instead of a more appropriate description. A complete implementation of this method is pending because localized strings are required to support internationalization software and work to ensure that these strings are localized has not yet been done. Presumably, this method will be completed when version 1.4 of the Java 2 Platform Standard Edition is released.


To learn more about AccessibleAction, look at the source code for the AccessibilityDemo2 application in Listing 17.3.

Listing 17.3 The AccessibilityDemo2 Application Source Code
 // AccessibilityDemo2.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo2 extends JFrame {    AccessibilityDemo2 (String title)    {       super (title);       addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JToolBar toolBar = new JToolBar ();      Action a = new AbstractAction ("Demo")                      {                         public void actionPerformed (ActionEvent e)                         {                            System.out.println ("Action taken.");                         }                      };       JButton b = toolBar.add (a);       b.setText ("Demo Button");       b.setToolTipText ("Press me to take action.");       JMenu mainMenu = new JMenu ("Menu");       JMenuItem mi = mainMenu.add (a);       mi.getAccessibleContext ().setAccessibleName ("Menu item");       JMenuBar mb = new JMenuBar ();       mb.add (mainMenu);       setJMenuBar (mb);       JPanel pane = new JPanel ();       pane.setLayout (new BorderLayout ());       pane.setPreferredSize (new Dimension (200, 100));       pane.add (toolBar, BorderLayout.NORTH);       setContentPane (pane);       pack ();       setVisible (true);    }    public static void main (String [] args)    {      AccessibilityDemo2 ad2;      ad2 = new AccessibilityDemo2 ("Accessibility Demo2");      try       {           Thread.sleep (5000);       }       catch (InterruptedException e) { }      ad2.dumpActionInfo (ad2.getAccessibleContext ());   }   void dumpActionInfo (AccessibleContext ac)   {      AccessibleAction aa = ac.getAccessibleAction ();      if (aa != null)      {          String s = ac.getAccessibleName ();          System.out.println (s);          int count = aa.getAccessibleActionCount ();          for (int i = 0; i < count; i++)           {                s = aa.getAccessibleActionDescription (i);                System.out.println ("Description = " + s);           }       }      int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)            dumpActionInfo (ac.getAccessibleChild (i)                              .getAccessibleContext ());    } } 

AccessibilityDemo2 creates a GUI that consists of a menu and a toolbar with a single button. Both the menu and toolbar are associated with an action called Demo. When either the menu's sole menu item or the toolbar's sole button is selected, this action is performed.

AccessibilityDemo2 (as with the rest of the AccessibilityDemo applications) simulates an assistive technology interrogating a GUI's components. This is done by causing its main thread to sleep for 5 or 10 seconds (which allows a user to interact with the GUI) before calling a dump method to recursively search for all components, whose classes implement an appropriate interface.

As far as AccessibilityDemo2 is concerned , the only components of interest are those whose classes implement AccessibleAction. As soon as an appropriate component is found, its accessible name and accessible action description are sent to the standard output device. This information is shown in Listing 17.4.

Listing 17.4 AccessibilityDemo2's Output
 Menu Description = click Menu item Description = click Demo Button Description = click 

As shown, three components are associated with AccessibleAction objects. These components are identified by their accessible names: Menu (for the JMenu component), Menu item (for the JMenuItem component), and Demo Button (for the JButton component added to the JToolBar ). Furthermore, the "most helpful" click description automatically identifies each action.

AccessibleContext's getAccessibleComponent method returns an AccessibleComponent object. After this object is obtained, an assistive technology can call AccessibleComponent methods to find out the onscreen size , position, color , cursor, and so on, of its associated component. Furthermore, these attributes can be changed. To learn more about AccessibleComponent, look at the source code for the AccessibilityDemo3 application in Listing 17.5.

Listing 17.5 The AccessibilityDemo3 Application Source Code
 // AccessibilityDemo3.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo3 extends JFrame {    AccessibilityDemo3 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          } );       JPanel p = new JPanel ();       p.setPreferredSize (new Dimension (200, 50));       JButton jb = new JButton ("OK");       p.add (jb);       getContentPane ().add (p);       pack ();       setVisible (true);    }    public static void main (String [] args)    {       AccessibilityDemo3 ad3;       ad3 = new AccessibilityDemo3 ("Accessibility Demo3");       try       {           Thread.sleep (5000);       }       catch (InterruptedException e) { }       ad3.dumpComponentInfo (ad3.getAccessibleContext ());   }   void dumpComponentInfo (AccessibleContext ac)   {      AccessibleComponent ax = ac.getAccessibleComponent ();      if (ax != null)      {          String s = ac.getAccessibleName ();          if (s != null && s.equals ("OK"))          {              System.out.println ("Background color: " +                                   ax.getBackground ());              System.out.println ("Cursor: " +                                   ax.getCursor ());              Cursor c;              c = Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR);              ax.setCursor (c);              System.out.println ("Foreground color: " +                                   ax.getForeground ());              System.out.println ("Location: " +                                   ax.getLocationOnScreen ());           }       }      int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)           dumpComponentInfo (ac.getAccessibleChild (i)                                .getAccessibleContext ());    } } 

AccessibilityDemo3 creates a GUI consisting of a single button. After a five-second delay, the main thread calls dumpComponentInfo to recursively search for the OK button's AccessibleComponent object. After the object is found, the background color, cursor, foreground color, and mouse pointer location are displayed. Furthermore, the mouse pointer's cursor is changed to a wait cursor. Listing 17.6 shows this information sent to the standard output device, after a five-second delay.

Listing 17.6 AccessibilityDemo3's Output
 Background color: javax.swing.plaf.ColorUIResource[r=204,g=204,b=204] Cursor: java.awt.Cursor[Default Cursor] Foreground color: javax.swing.plaf.ColorUIResource[r=0,g=0,b=0] Location: java.awt.Point[x=78,y=28] 

AccessibleContext 's getAccessibleHypertext method returns an AccessibleHypertext object. An assistive technology can query this object to learn about the number of links embedded in a Web page. Furthermore, one of AccessibleHypertext 's methods returns an AccessibleHyperlink object, whose methods can be called to obtain link information. Listing 17.7 presents source code for an AccessibilityDemo4 application that demonstrates how to obtain this information.

Listing 17.7 The AccessibilityDemo4 Application Source Code
 // AccessibilityDemo4.java import javax.accessibility.*; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.net.*; class AccessibilityDemo4 extends JFrame                          implements ActionListener, HyperlinkListener {    JEditorPane view;    JTextField commandLine;    AccessibilityDemo4 (String title)    {       super (title);       addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      commandLine = new JTextField ();      commandLine.addActionListener (this);      getContentPane ().add (commandLine, BorderLayout.NORTH);      view = new JEditorPane ();      view.setEditable (false);      view.setPreferredSize (new Dimension (400, 400));      view.addHyperlinkListener (this);      getContentPane ().add (view, BorderLayout.CENTER);      pack ();      setVisible (true);   }   public void actionPerformed (ActionEvent e)   {       try       {          URL url = new URL (e.getActionCommand ());          view.setPage (url);          commandLine.setText (url.toExternalForm ());       }       catch (MalformedURLException e2)       {          System.out.println ("Bad URL: " + e.getActionCommand ());       }       catch (java.io.IOException e2) { }    }   public void hyperlinkUpdate (HyperlinkEvent e)    {       try       {          view.setPage (e.getURL ());          commandLine.setText (e.getURL ().toExternalForm ());       }       catch (java.io.IOException e2) { }    }   public static void main (String [] args)   {      AccessibilityDemo4 ad4;      ad4 = new AccessibilityDemo4 ("Accessibility Demo4");      try      {          Thread.sleep (10000);      }      catch (InterruptedException e) { }      ad4.dumpHypertextInfo (ad4.getAccessibleContext ());   }   void dumpHypertextInfo (AccessibleContext ac)   {      AccessibleText at = ac.getAccessibleText ();      AccessibleHypertext ah = null;      if (at instanceof AccessibleHypertext)          ah = (AccessibleHypertext) at;      if (ah != null)      {          int nLinks = ah.getLinkCount ();          for (int i = 0; i < nLinks; i++)          {               AccessibleHyperlink ahl = ah.getLink (i);               int nActions = ahl.getAccessibleActionCount ();               for (int j = 0; j < nActions; j++)                {                    String s = ahl.getAccessibleActionDescription (j);                    System.out.println ("Action = " + s);                }           }           return;       }                  int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)            dumpHypertextInfo (ac.getAccessibleChild (i)                                 .getAccessibleContext ());    }} 

AccessibilityDemo4 creates a GUI consisting of command line text field and editor pane components. A uniform resource locator is entered in the command line and the resulting Web page is displayed in the editor pane. Listing 17.8 shows the information that is sent to the standard output device (after 10 seconds have elapsed) when the dummy .html file is used. (This file is included with the rest of this book's source code, which you can download from this book's Web site at http://www.mcp.com.)

Listing 17.8 AccessibilityDemo4's Output
 Action = CNN Web site Action = PC Magazine Web site 

Note

Listing 17.8's output was generated by using the dummy.html file, which is included with this book's source code. Furthermore, 10 seconds was chosen as being sufficient for interacting with AccessibilityDemo4 's GUI, before Listing 17.8's output is automatically generated. You might need to increase this delay to obtain the same results as shown in Listing 17.8. (This advice also applies to the other AccessibilityDemo programs shown in this chapter.)


AccessibleContext 's getAccessibleIcon method returns an AccessibleIcon object. An assistive technology can query this object to learn about a component's icons. Listing 17.9 presents source code for the AccessibilityDemo5 application, which demonstrates AccessibleIcon.

Listing 17.9 The AccessibilityDemo5 Application Source Code
 // AccessibilityDemo5.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo5 extends JFrame {    AccessibilityDemo5 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                         {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (200, 50));      JButton jb = new JButton (new ImageIcon ("bullet.gif"));      p.add (jb);      getContentPane ().add (p);      pack ();      setVisible (true);   }   public static void main (String [] args)   {      AccessibilityDemo5 ad5;      ad5 = new AccessibilityDemo5 ("Accessibility Demo5");      try      {          Thread.sleep (5000);      }      catch (InterruptedException e) { }      ad5.dumpIconInfo (ad5.getAccessibleContext ());   }   void dumpIconInfo (AccessibleContext ac)   {      AccessibleIcon [] ai = ac.getAccessibleIcon ();      if (ai != null)      {           for (int i = 0; i < ai.length; i++)           {                String s = ai [i].getAccessibleIconDescription ();                System.out.println ("Description = " + s);                System.out.println ("Width = "                                    + ai [i].getAccessibleIconWidth ());                System.out.println ("height = "                                    + ai [i].getAccessibleIconWidth ());           }          return;       }                  int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)            dumpIconInfo (ac.getAccessibleChild (i)                            .getAccessibleContext ());    } } 

AccessibilityDemo5 creates a GUI consisting of a button with an icon. Information about this icon is sent to the standard output device after five seconds have passed. This information is shown in Listing 17.10.

Listing 17.10 AccessibilityDemo5's Output
 Description = bullet.gif Width = 15 height = 15 

AccessibleContext 's getAccessibleSelection method returns an AccessibleSelection object. An assistive technology can query this object to learn about, and modify, the selections in a list, combo box, and so on. To demonstrate AccessibleSelection, Listing 17.11 presents source code for the AccessibilityDemo6 application.

Listing 17.11 The AccessibilityDemo6 Application Source Code
 // AccessibilityDemo6.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Vector; class AccessibilityDemo6 extends JFrame {    AccessibilityDemo6 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                         {                             public void windowClosing (WindowEvent e)                             {                                 System.exit (0);                              }                          });      Vector v = new Vector ();      v.add ("First item");      v.add ("Second item");      v.add ("Third item");      v.add ("Fourth item");      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (200, 100));      JList jl = new JList (v);      jl.setPreferredSize (new Dimension (100, 75));      p.add (jl);      getContentPane ().add (p);      pack ();      setVisible (true);   }   public static void main (String [] args)   {       AccessibilityDemo6 ad6;       ad6 = new AccessibilityDemo6 ("Accessibility Demo6");       try       {          Thread.sleep (5000);       }       catch (InterruptedException e) { }       ad6.dumpSelectionInfo (ad6.getAccessibleContext ());    }    void dumpSelectionInfo (AccessibleContext ac)    {       AccessibleSelection as = ac.getAccessibleSelection ();       if (as != null)       {           int count = as.getAccessibleSelectionCount ();           for (int i = 0; i < count; i++)           {                Accessible a = as.getAccessibleSelection (i);                AccessibleContext ac2 = a.getAccessibleContext ();                String s = ac2.getAccessibleName ();                System.out.println ("Name = " + s);           }          return;       }      int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)            dumpSelectionInfo (ac.getAccessibleChild (i)                                 .getAccessibleContext ());    } } 

AccessibilityDemo6 creates a GUI consisting of a list with four items. When the program is run, you must select an item from this list before the 5 seconds expires . Listing 17.12 shows that the third item was currently selected when the information was sent to the standard output device (after the passage of five seconds).

Listing 17.12 AccessibilityDemo6's Output
 Name = Third item 

AccessibleContext 's getAccessibleTable method returns an AccessibleTable object. An assistive technology can query this object to find out information about a table (such as the number of columns and rows). Listing 17.13 presents source code for an AccessibilityDemo7 application that shows how to accomplish this task.

Listing 17.13 The AccessibilityDemo7 Application Source Code
 // AccessibilityDemo7.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo7 extends JFrame {    AccessibilityDemo7 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                         {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (200, 200));      JTable jt = new JTable (10, 3);      p.add (jt);      getContentPane ().add (p);      pack ();      setVisible (true);   }   public static void main (String [] args)   {      AccessibilityDemo7 ad7;      ad7 = new AccessibilityDemo7 ("Accessibility Demo7");      try      {           Thread.sleep (5000);      }      catch (InterruptedException e) { }      ad7.dumpTableInfo (ad7.getAccessibleContext ());    }    void dumpTableInfo (AccessibleContext ac)    {       AccessibleTable at = ac.getAccessibleTable ();      if (at != null)      {           int nCol = at.getAccessibleColumnCount ();           System.out.println ("Columns = " + nCol);          int nRow = at.getAccessibleRowCount ();          System.out.println ("Rows = " + nRow);          return;      }      int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)           dumpTableInfo (ac.getAccessibleChild (i)                            .getAccessibleContext ());    } } 

AccessibilityDemo7 creates a GUI consisting of a 10 row by 3 column table. After a five-second delay, this row/column information is sent to the standard output device, as shown in Listing 17.14.

Listing 17.14 AccessibilityDemo7's Output
 Columns = 3 Rows = 10 

AccessibleContext 's getAccessibleText method returns an AccessibleText object. An assistive technology can query this object to retrieve text, text attributes (such as font style), and other information (such as text length). This is demonstrated by the AccessibilityDemo8 application, whose source code is presented in Listing 17.15.

Listing 17.15 The AccessibilityDemo8 Application Source Code
 // AccessibilityDemo8.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo8 extends JFrame {    AccessibilityDemo8 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                         {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (300, 50));      JTextField jtf = new JTextField (20);      jtf.setPreferredSize (new Dimension (100, 20));      p.add (jtf);      getContentPane ().add (p);      pack ();      setVisible (true);   }   public static void main (String [] args)   {      AccessibilityDemo8 ad8;      ad8 = new AccessibilityDemo8 ("Accessibility Demo8");      try      {          Thread.sleep (5000);      }      catch (InterruptedException e) { }      ad8.dumpTextInfo (ad8.getAccessibleContext ());   }   void dumpTextInfo (AccessibleContext ac)   {      AccessibleText at = ac.getAccessibleText ();      if (at != null)      {          System.out.println ("Caret position = "                              + at.getCaretPosition ());          System.out.println ("Selected text = "                              + at.getSelectedText ());          return;       }       int nChildren = ac.getAccessibleChildrenCount ();       for (int i = 0; i < nChildren; i++)             dumpTextInfo (ac.getAccessibleChild (i)                            .getAccessibleContext ());    } } 

AccessibilityDemo8 creates a GUI consisting of a single text field component. You can type and select text. After five seconds, information about this text is sent to the standard output device. This information is shown in Listing 17.16.

Listing 17.16 AccessibilityDemo8's Output
 Caret position = 1 Selected text = bc 

From the listing, the assistive technology can deduce that the caret is positioned to the right of the first entered character, and that two characters have been selected.

AccessibleContext's getAccessibleValue method returns an AccessibleValue object. An assistive technology can query this object to retrieve the minimum, current, and maximum values of a component object (such as a scrollbar) that contains numeric data. Listing 17.17 presents source code for the AccessibilityDemo9 application, which demonstrates retrieving this information.

Listing 17.17 The AccessibilityDemo9 Application Source Code
 // AccessibilityDemo9.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo9 extends JFrame {    AccessibilityDemo9 (String title)    {      super (title);      addWindowListener (new WindowAdapter ()                         {                             public void windowClosing (WindowEvent e)                             {                                System.exit (0);                             }                         });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (300, 50));      JScrollBar jsb;      jsb = new JScrollBar (Adjustable.HORIZONTAL, 0, 1, 0, 100);      jsb.setPreferredSize (new Dimension (200, 20));      p.add (jsb);      getContentPane ().add (p);      pack ();      setVisible (true);    }    public static void main (String [] args)    {       AccessibilityDemo9 ad9;       ad9 = new AccessibilityDemo9 ("Accessibility Demo9");      try      {          Thread.sleep (5000);      }      catch (InterruptedException e) { }      ad9.dumpValueInfo (ad9.getAccessibleContext ());    }   void dumpValueInfo (AccessibleContext ac)    {       AccessibleValue av = ac.getAccessibleValue ();       if (av != null)       {           System.out.println ("Minimum value = "                               + av.getMinimumAccessibleValue ());           System.out.println ("Current value = "                               + av.getCurrentAccessibleValue ());           System.out.println ("Maximum value = "                               + av.getMaximumAccessibleValue ());           return;       }       int nChildren = ac.getAccessibleChildrenCount ();       for (int i = 0; i < nChildren; i++)             dumpValueInfo (ac.getAccessibleChild (i)                              .getAccessibleContext ());    } } 

AccessibilityDemo9 creates a GUI consisting of a single scrollbar component. You can move the scrollbar's slider to any desired location within its range. After five seconds, information about the current state of this scrollbar is sent to the standard output device. This information is shown in Listing 17.18.

Listing 17.18 AccessibilityDemo9's Output
 Minimum value = 0 Current value = 48 Maximum value = 100 

Because Swing components are designed with accessibility in mind, much of the work is automatically done for you. However, there are some things you can do (in addition to assigning names and descriptions) to ensure that your GUI program is as accessible as possible:

  • Specify keyboard alternatives where practical. For example, you can call the setMnemonic method on a button or menu item to provide a convenient keyboard alternative. (If a user has no limbs , he won't be able to use a mouse ”at least not very effectively. However, by placing a straw between his teeth, the user could still operate the keyboarda certain extent.)

  • Call setDescription to assign descriptions to all ImageIcon objects. (If a user is blind, a description could be translated into speech when the mouse pointer is moved over the corresponding image.)

  • If a label is describing another component (such as a text field), call the label's setLabelFor method to associate this other component with the label. Assistive technologies can then identify this component by calling the label's getLabelFor method.

Tip

In addition to these three guidelines, IBM has established its own set of guidelines for developing accessible applications using 100% pure Java. IBM's guidelines are located at the following Web address:

 http://www-3.ibm.com/able/snsjavag.html 

To learn more about associating labels with other components, check out the source code for the AccessibilityDemo10 application. This source code is presented in Listing 17.19.

Listing 17.19 The AccessibilityDemo10 Application Source Code
 // AccessibilityDemo10.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo10 extends JFrame {   JLabel jl;   AccessibilityDemo10 (String title)   {      super (title);      addWindowListener (new WindowAdapter ()                         {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (300, 50));      jl = new JLabel ("Name:");      p.add (jl);      JTextField jtf = new JTextField (20);      jtf.getAccessibleContext ().setAccessibleName ("Name-entry");      p.add (jtf);      jl.setLabelFor (jtf);      getContentPane ().add (p);      pack ();      setVisible (true);    }    public static void main (String [] args)    {      AccessibilityDemo10 ad10;      ad10 = new AccessibilityDemo10 ("Accessibility Demo10");      try      {          Thread.sleep (5000);      }      catch (InterruptedException e) { }      ad10.dumpConnectedInfo (ad10.getAccessibleContext ());   }   void dumpConnectedInfo (AccessibleContext ac)   {      String s = ac.getAccessibleName ();      if (s != null && s.equals ("Name:"))      {          AccessibleContext ac2;          ac2 = jl.getLabelFor ().getAccessibleContext ();          System.out.println ("Label connected to: "                               + ac2.getAccessibleName ());          return;      }                  int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)           dumpConnectedInfo (ac.getAccessibleChild (i)                                .getAccessibleContext ());    } } 

AccessibilityDemo10 creates a GUI consisting of label and text field components. The setLabelFor method is called to associate the text field with the label. After five seconds, the information shown in Listing 17.20 is sent to the standard output device.

Listing 17.20 AccessibilityDemo10's Output
 Label connected to: Name-entry 

Caution

If you don't call setAccessibleName to assign a name to the component associated with a label, and this component doesn't display any text, the label's name will be returned when you call getAccessibleName for the component associated with the label.


AccessibilityDemo10 demonstrates a weakness with setLabelFor and getLabelFor. An assistive technology needs access to the label component so that it can call getLabelFor to retrieve the associated text field component. Unless it has access to the label (which isn't possible), it cannot retrieve the associated text field component. (This is why the JLabel jl field variable was declared outside AccessibilityDemo10 's methods, and used in the dumpConnectedInfo method.)

There is a better technique for retrieving associated components. This technique involves AccessibilityContext 's getAccessibleRelationSet method along with the AccessibleRelation and AccessibleRelationSet classes.

The getAccessibleRelationSet method returns an object created from the AccessibleRelationSet class. This object identifies the set of all components associated with another component. For example, a reference to the text field component would be placed in the relation set belonging to the label component.

Each entry in the AccessibleRelationSet object is an object that's created from the AccessibleRelation class. An AccessibleRelation object describes a component that serves as the target of an association between two components. For example, the text field component is the target of the label component. AccessibleRelation methods can retrieve this target or change it to another component.

Listing 17.21 presents source code for AccessibilityDemo11. This application is equivalent to AccessibilityDemo10, except that it uses the new relationship architecture. (The output is the same as the output shown previously in Listing 17.20.)

Listing 17.21 The AccessibilityDemo11 Application Source Code
 // AccessibilityDemo11.java import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class AccessibilityDemo11 extends JFrame {    JLabel jl;    AccessibilityDemo11 (String title)    {       super (title);       addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          });      JPanel p = new JPanel ();      p.setPreferredSize (new Dimension (300, 50));      jl = new JLabel ("Name:");      p.add (jl);      JTextField jtf = new JTextField (20);      jtf.getAccessibleContext ().setAccessibleName ("Name-entry");      p.add (jtf);      AccessibleRelation ar = new AccessibleRelation ("connector", jtf);      AccessibleContext ac = jl.getAccessibleContext ();      ac.getAccessibleRelationSet ().add (ar);      getContentPane ().add (p);      pack ();      setVisible (true);   }   public static void main (String [] args)   {       AccessibilityDemo11 ad11;       ad11 = new AccessibilityDemo11 ("Accessibility Demo11");       try       {           Thread.sleep (5000);       }       catch (InterruptedException e) { }       ad11.dumpConnectedInfo (ad11.getAccessibleContext ());    }    void dumpConnectedInfo (AccessibleContext ac)    {       AccessibleRelationSet ars = ac.getAccessibleRelationSet ();       AccessibleRelation ar = null;       if (ars != null)           ar = ars.get ("connector");      if (ar != null)      {          Object [] o = ar.getTarget ();          JComponent jc = (JComponent) o [0];          System.out.println ("Label connected to: "                              + jc.getAccessibleContext ()                                  .getAccessibleName ());          return;      }                  int nChildren = ac.getAccessibleChildrenCount ();      for (int i = 0; i < nChildren; i++)           dumpConnectedInfo (ac.getAccessibleChild (i)                                .getAccessibleContext ());    } } 

Troubleshooting Tip

Now that you've explored how an assistive technology uses the accessibility framework to learn about a GUI's components, you might be wondering how to support the accessibility framework in any new components that you create. To learn how to implement this support, see "Creating Accessible Components" in the "Troubleshooting" section.


   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net