java - Why is my JTable always reported as empty using VoiceOver on OS X? -
voiceover on osx 10.10.4 (yosemite), using jre 1.7.0_75 , jre 1.8.0_45, reports following table "empty".
package stackoverflow.examples.jtable; import javax.swing.jframe; import javax.swing.jtable; import javax.swing.swingutilities; public class tabledemo extends jframe { private static final long serialversionuid = 1l; public tabledemo() { super("accessible jtable?"); final string[] columnnames = { "first name", "last name", "sport", "# of years", "vegetarian" }; final object[][] data = { {"kathy", "smith", "snowboarding", new integer(5), new boolean(false)}, {"john", "doe", "rowing", new integer(3), new boolean(true)}, }; final jtable jtable = new jtable(data, columnnames); jtable.getaccessiblecontext().setaccessiblename("data table"); system.out.println("rows: " + jtable.getaccessiblecontext().getaccessibletable().getaccessiblerowcount()); system.out.println("cols: " + jtable.getaccessiblecontext().getaccessibletable().getaccessiblecolumncount()); system.out.println("java: " + system.getproperty("java.version")); jtable.setopaque(true); setcontentpane(jtable); } private static void createandshowgui() { final tabledemo frame = new tabledemo(); frame.pack(); frame.setvisible(true); } public static void main(string[] args) { swingutilities.invokelater(new runnable() { @override public void run() { createandshowgui(); } }); } }
apart voiceover saying table empty, else seems ok:
- voiceover picks name i've given table using setaccessiblename()
- the jtable correctly returns instance of accessibletable.
- calling getaccessiblerowcount() , getaccessiblecolumncount() prints expected values.
what missing?
further info:
- i've tried using jre 1.6.0_65 apple supplied jre , same issue. tried in case changed when moving oracle supplied jre.
the reason why voiceover says "empty" because accessibility hierarchy not being exposed correctly. can use accessibility inspector tool (one of xcode developer tools) examine accessibility hierarchy. in case, accessibility inspector tool running, hovering mouse pointer on jtable
shows there axtable element 10 axstatictext children (one each of cells). tables should exposed axtable > axrow > axcell > … . also, according roles reference, axtable element should have rows attribute among other required attributes, these have not been exposed accessibility hierarchy jre.
i have tried out program on windows 8.1 pro using java 1.8.0_51 , see similar problem. similar accessibility inspector tool, windows sdk comes inspect tool can used inspect accessibility data. when running test case, appears jtable
has not been exposed @ all. enabling windows narrator, unable navigate table or cells.
so, appears jre not support table accessibility.
in source of javax.accessibility.accessiblerole
, can see code define row
constant commented out along other constants documented "under consideration potential future use".
in source of jtable
, can see accessiblejtable
, accessibletableheader
, accessiblejtablecell
, , accessiblejtableheadercell
helper classes defined, there isn't accessible
implementation rows of table.
in theory write custom accessiblecontext
implementation operate expose more complete accessibility hierarchy jtable
os. however, not sure whether possible work around java's apparent lack of support table accessibility.
whether possible might depend on platform. example, examining source code of src/macosx/native/sun/awt/javaaccessibilityutilities.m
, can see how java's accessibility roles mapped nsaccessibility*role constants. can see row_header
accessible role mapped axrow. thus, expose axrow children of axtable using row_header
accessible role. here code succeeds in doing this:
public static class myjtable extends jtable { public myjtable(tablemodel tm) { super(tm); } @override public myaccessiblejtable getaccessiblecontext() { if (accessiblecontext == null) { accessiblecontext = new myaccessiblejtable(); } return (myaccessiblejtable)accessiblecontext; } protected class myaccessiblejtable extends accessiblejtable { @override public int getaccessiblechildrencount() { if (myjtable.this.getcolumncount() <= 0) { return 0; } return myjtable.this.getrowcount(); } @override public accessible getaccessiblechild(int i) { if (i < 0 || getaccessiblechildrencount() <= i) { return null; } tablecolumn firstcolumn = getcolumnmodel().getcolumn(0); tablecellrenderer renderer = firstcolumn.getcellrenderer(); if (renderer == null) { class<?> columnclass = getcolumnclass(0); renderer = getdefaultrenderer(columnclass); } component component = renderer.gettablecellrenderercomponent(myjtable.this, null, false, false, i, 0); return new myaccessiblerow(myjtable.this, i, component); } } protected static class myaccessiblerow extends accessiblecontext implements accessible { private myjtable table; private int row; private component renderercomponent; protected myaccessiblerow(myjtable table, int row, component rendercomponent) { this.table = table; this.row = row; this.renderercomponent = renderercomponent; } @override public accessiblerole getaccessiblerole() { // row_header used because maps nsaccessibilityrowrole // on mac. return accessiblerole.row_header; } @override public locale getlocale() { accessiblecontext ac = renderercomponent.getaccessiblecontext(); if (ac != null) { return ac.getlocale(); } else { return null; } } @override public int getaccessiblechildrencount() { return 0; // todo return number of columns in row } @override public accessible getaccessiblechild(int i) { return null; // todo return myaccessiblejtablecell } @override public int getaccessibleindexinparent() { return row; } @override public accessiblestateset getaccessiblestateset() { return null; // todo } @override public accessiblecontext getaccessiblecontext() { return this; // todo } @override public accessiblecomponent getaccessiblecomponent() { return table.getaccessiblecontext(); // todo } } }
as can see screenshot:
.. there 2 axrow children on axtable. however, voiceover still announces table "empty". not sure whether because rows not have axcell children, or because axtable missing required attributes, or other reason.
if go custom accessiblecontext
route, better avoid trying expose table hierarchy. instead, model table list, each row corresponds list item, , each list item contains group each of cells. similar approach used firefox (tested version 39.0). on mac, firefox not use table role when exposing html table. should fixed in firefox 41, though. see bug 744790 - [mac] html table semantics not communicated voiceover @ all.
i using mac os 10.10.4 , java 1.8.0_51.
edit: "empty" table issue has been reported openjdk bug jdk-7124284 [macosx] nothing heard voiceover when navigating in table. comments, there several known issues mac swing accessibility deferred jdk 9.
another possible work around use javafx tableview
class. trying out tableview
sample http://docs.oracle.com/javafx/2/ui_controls/table-view.htm seeing voiceover announcing table. javafx accessibility implemented part of jep 204 implemented in java 8u40.
Comments
Post a Comment