2

JScrollPane にラップされた JEditorPane を持つ単純な Swing アプリケーションがあります。

残念ながら、 JAWSNVDAなどのスクリーン リーダー ソフトウェアは正しく動作しません。

フォーカスが JEditorPane に入ると、アクセシビリティ対応の名前とそれに続く「テキスト」のみを読み取り、予期される動作が JEditorPane のコンテンツの読み取りを続行するときに停止します。

JEdi​​torPane を JScrollPane にラップしないと、期待どおりに動作します。

Monkey を使用してアクセス可能なツリーを検査しようとしましたが、JScrollPane にラップされた JEditorPane とラップされていない JEditorPane の間に関連する違いは見られません。

何か案は?

問題を示す簡単なサンプルを次に示します。フォーカスが最初の JEditorPane に入ると、JAWS は「最初のエディタペイン - 編集」と読み上げます。フォーカスが 2 番目の JEditorPane に入ると、JAWS は「2 番目のエディタ ペイン - 編集 - バー」と読み上げます。

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);
  }
}
4

1 に答える 1

2

私は自分で回避策を見つけました:

もし私が

  1. アクセス可能なツリーを変更して JScrollPane と JViewPort をスキップする
  2. アクセス可能なプロパティ変更イベントを JEditorPane から送信しないようにする

それは動作します。

なぜこれが機能するのかについての洞察をいただければ幸いです (editorPane2 の AccessibleContext を editorPane1 の AccessibleContext に置き換え、オーバーライドする必要があるメソッドが見つかるまで、メソッドを徐々に元に戻すことで回避策を見つけました)。

これは実際の例です (これはもう簡単ではありません)。

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);
    }
  }

}
于 2011-07-14T13:24:52.107 に答える