2011-07-13 62 views
2

我有一個簡單的Swing應用程序,它帶有一個包裝在JScrollPane中的JEditorPane。JEditorPane,JScrollPane和可訪問性

不幸的屏幕閱讀器軟件,如JAWSNVDA行爲不正確。

焦點進入JEditorPane時,它只會讀取可訪問的名稱,後跟「text」,然後停止,當預期的行爲是繼續讀取JEditorPane的內容時。

如果我不將JEditorPane包裝到JScrollPane中,它將按預期工作。

我已經嘗試檢查使用猴子訪問樹,但我看不到包裝在JScrollPane中的JEditorPane與未包裝的JEditorPane之間的任何相關區別。

任何想法?

這是一個簡短的示例,演示了這個問題。如果焦點進入第一個JEditorPane,JAWS將讀取「第一個編輯器窗格 - 編輯」。如果焦點進入第二個JEditorPane,JAWS將讀取「第二個編輯窗格 - 編輯欄」。

public final class SmallExample { 
    public static void main(String... aArgs){ 
    JFrame frame = new JFrame("Test Frame"); 

    JPanel panel = new JPanel(); 

    JEditorPane editorPane1 = new JEditorPane(); 
    editorPane1.setText("Foo"); 
    editorPane1.getAccessibleContext().setAccessibleName("first editorpane"); 
    editorPane1.getAccessibleContext().setAccessibleDescription(""); 

    JScrollPane scrollPane = new JScrollPane(editorPane1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
    panel.add(scrollPane); 

    JEditorPane editorPane2 = new JEditorPane(); 
    panel.add(editorPane2); 
    editorPane2.setText("Bar"); 
    editorPane2.getAccessibleContext().setAccessibleName("second editorpane"); 
    editorPane2.getAccessibleContext().setAccessibleDescription("");  

    frame.getContentPane().add(panel);  

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setVisible(true); 
    } 
} 

回答

2

我找到了一個解決方法自己:

如果我

  1. 修改訪問樹跳過JScrollPane中和的JViewport
  2. 避免對JEditorPane
  3. 發送訪問的屬性更改事件

然後它工作。

我還是很欣賞任何見解爲什麼這工作(我找到了解決方法通過與一個editorPane1更換的AccessibleContext的editorPane2逐步切換方法後面,直到我發現我需要覆蓋的那些)。

這裏是一個工作示例(它不是那麼簡單了):

public final class Example { 

    public static void main(String... aArgs){ 
    JFrame frame = new JFrame("Test Frame"); 

    final JPanel panel = new JPanel(){ 
     public AccessibleContext getAccessibleContext() { 
      if(accessibleContext==null){ 
       accessibleContext = new AccessibleContextWrapper(super.getAccessibleContext()){ 
        public Accessible getAccessibleChild(int i) { 
         Accessible accessibleChild = super.getAccessibleChild(i); 
         while(accessibleChild!=null && (accessibleChild instanceof JScrollPane || accessibleChild instanceof JViewport)){ 
          accessibleChild = accessibleChild.getAccessibleContext().getAccessibleChild(0); 
         } 
         return accessibleChild; 
        } 
       }; 
      } 
      return accessibleContext; 
     } 
    }; 

    final JEditorPane editorPane = new JEditorPane(){ 
     public AccessibleContext getSuperAccessibleContext() { 
      return super.getAccessibleContext(); 
     } 
     @Override 
     public AccessibleContext getAccessibleContext() { 
      return new AccessibleContextWrapper(super.getAccessibleContext()){ 
       public Accessible getAccessibleParent() { 
        Accessible parent = super.getAccessibleParent(); 
        while(parent!=null && (parent instanceof JScrollPane || parent instanceof JViewport)){ 
         parent = parent.getAccessibleContext().getAccessibleParent(); 
        } 
        return parent; 
       } 

       public int getAccessibleIndexInParent() { 
        int res = super.getAccessibleIndexInParent();       
        Accessible parent = super.getAccessibleParent(); 
        while(parent!=null && (parent instanceof JScrollPane || parent instanceof JViewport)){ 
         res = parent.getAccessibleContext().getAccessibleIndexInParent(); 
         parent = parent.getAccessibleContext().getAccessibleParent(); 
        } 
        return res; 
       } 

       public void addPropertyChangeListener(
         PropertyChangeListener listener) {     
       } 

       public void removePropertyChangeListener(
         PropertyChangeListener listener) {     
       }   
      }; 
     }  
    }; 
    editorPane.setText("Foo"); 
    editorPane.getAccessibleContext().setAccessibleName("first editorpane"); 
    editorPane.getAccessibleContext().setAccessibleDescription(""); 
    editorPane.getAccessibleContext(); 
    JScrollPane scrollPane = new JScrollPane(editorPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

    panel.add(scrollPane); 

    frame.getContentPane().add(panel);  

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setVisible(true); 
    } 

    public static class AccessibleContextWrapper extends AccessibleContext { 
    private final AccessibleContext inner; 

    public AccessibleContextWrapper(AccessibleContext inner) { 
     this.inner = inner; 
    } 

    public String getAccessibleName() { 
     return inner.getAccessibleName(); 
    } 

    public void setAccessibleName(String s) { 
     inner.setAccessibleName(s); 
    } 

    public String getAccessibleDescription() { 
     return inner.getAccessibleDescription(); 
    } 

    public void setAccessibleDescription(String s) { 
     inner.setAccessibleDescription(s); 
    } 

    public AccessibleRole getAccessibleRole() { 
     return inner.getAccessibleRole(); 
    } 

    public AccessibleStateSet getAccessibleStateSet() { 
     return inner.getAccessibleStateSet(); 
    } 

    public Accessible getAccessibleParent() { 
     return inner.getAccessibleParent(); 
    } 

    public void setAccessibleParent(Accessible a) { 
     inner.setAccessibleParent(a); 
    } 

    public int getAccessibleIndexInParent() { 
     return inner.getAccessibleIndexInParent(); 
    } 

    public int getAccessibleChildrenCount() { 
     return inner.getAccessibleChildrenCount(); 
    } 

    public Accessible getAccessibleChild(int i) { 
     return inner.getAccessibleChild(i); 
    } 

    public Locale getLocale() throws IllegalComponentStateException { 
     return inner.getLocale(); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     inner.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     inner.removePropertyChangeListener(listener); 
    } 

    public AccessibleAction getAccessibleAction() { 
     return inner.getAccessibleAction(); 
    } 

    public AccessibleComponent getAccessibleComponent() { 
     return inner.getAccessibleComponent(); 
    } 

    public AccessibleSelection getAccessibleSelection() { 
     return inner.getAccessibleSelection(); 
    } 

    public AccessibleText getAccessibleText() { 
     return inner.getAccessibleText(); 
    } 

    public AccessibleEditableText getAccessibleEditableText() { 
     return inner.getAccessibleEditableText(); 
    } 

    public AccessibleValue getAccessibleValue() { 
     return inner.getAccessibleValue(); 
    } 

    public AccessibleIcon[] getAccessibleIcon() { 
     return inner.getAccessibleIcon(); 
    } 

    public AccessibleRelationSet getAccessibleRelationSet() { 
     return inner.getAccessibleRelationSet(); 
    } 

    public AccessibleTable getAccessibleTable() { 
     return inner.getAccessibleTable(); 
    } 

    public void firePropertyChange(String propertyName, Object oldValue, 
      Object newValue) { 
     inner.firePropertyChange(propertyName, oldValue, newValue); 
    } 
    } 

}