Has wx.Accessible ever worked?

We already know that accessibility on wxWidgets/wxPython is a bit sketchy and quirky overall (exhibit one, this very recent issue on the wxWidgets trac).
However, what I’m wondering right now is, specifically, how wx.Accessible is supposed to work - or if it works at all.
This class is meant to override/inject accessible info, into pretty much any gui element. The docs says, just derive and implement the functions, and you are good to go. Except, it doesn’t seem to work at all:

class MyAcc(wx.Accessible): # you must be on Windows to test this
    def GetName(self, childid):
        print('we hit wx.Accessible!')
        return (wx.ACC_OK, 'this is an accessible name')

class MainFrame(wx.Frame):
    def __init__(self, *a, **k):
        wx.Frame.__init__(self, *a, **k)
        p = wx.Panel(self)

        self.widget = wx.TextCtrl(p, pos=(10, 10))
        self.acc = MyAcc(self.widget) # or just MyAcc()?... doc isn't clear
        self.widget.SetAccessible(self.acc)

        wx.Button(p, pos=(10, 50)) # to let the focus change

app = wx.App()
MainFrame(None).Show()
app.MainLoop()

Even if you don’t want to test this code with a screen reader or the MS accessibility inspector, you can easily see that MyAcc just won’t work. Every time we clic on the TextCtrl, on WIndows the underlying MSAA framework is queried and should provide, among other things, our custom accessible name. Nothing happens instead, as MyAcc.GetName is never called (we never get to see the printed message on the console output).

Moreover, I’m having a very hard time to find even a single example with wx.Accessible online. And I mean, not just wxPython stuff. There’s not even a test case in the wxWidgets test suite.
Even the accessibility demo in wxWidget, that is supposed to showcase this feature, never makes direct use of wxAccessible. It uses instead the (undocumented!) subclass wxWindowAccessible, which is not ported into wxPython.

So, I guess, my questions are…
is there any wxPython-specific issue with wx.Accessible?
maybe porting wx.WindowAccessible too could be worth the shot?
has anyone ever given this whole accessible thing a try?

I know this is a rather niche topic, but thanks in advance for any feedback…
riccardo-

1 Like

My moonshot guess-in-the-dark would be that wxPython automagically
carries over the “name” property of a widget ?

Karsten

Indeed it does, and it’s not magic at all… And it will also use the label of a button, and a well-placed static text next to the widget, and… maybe other things I don’t know of.
But this is not what I asked, unfortunately. I’m not interested right now in all the info the framework will gather on its own, by default. I am specifically interested in using wx.Accessible (or any other tool) to override/implement from scratch these informations.

(This is not to say that your “name” remark is not interesting in itself. For instance, it will work with a wx.Panel, but won’t work with a wx.TextCtrl. Why? I wish I knew… but I’ll save it for another day…)

class MyFrame10(wx.Frame):
	def __init__(self):		
		wx.Frame.__init__(self,None,-1,'ty')
		pn1=wx.Panel(self)
		pn2=wx.Panel(self)
		pn2.SetBackgroundColour('red')

		vbox = wx.BoxSizer(wx.VERTICAL)
		vbox.Add(pn1, flag=wx.ALL|wx.EXPAND,proportion=1)
		vbox.Add(pn2,flag=wx.ALL|wx.EXPAND,proportion=2)
		self.SetSizer(vbox)

		myacc(self)

		ac=wx.Accessible(self)

		print(ac.DoDefaultAction(self.GetId()))
		print(ac.GetChildCount())
		print(ac.GetName(2))
class myacc(wx.Accessible):
	def __init__(self,win):
		wx.Accessible.__init__(self,win)
		print(self.GetChildCount())
		print(self.GetName(2))

if __name__ == '__main__':
	app = wx.App()
	frame = MyFrame10()	
	frame.Show()
	app.MainLoop()

But I have also two quetions. One is GetChildCount().I use it in different place,as above the example.it gets different results.Why?Another question is how to know who the results returned by getchildcount() are?

Can anyone help ?

What versions are you using? Did you try a snapshot build?

With 4.11 I get this output:

myacc
(3, -1194135955)
(3, '')
MYFrame10
3
(3, -1194135955)
(3, '')

With a more recent build from the repository:

myacc
(3, 0)
(3, '')
MYFrame10
3
(3, 0)
(3, '')

P.S.: Please post the code such that it is runnable. If you make a mistake, there is an edit function.

An update, after I have been working on accessibility topics in the last weeks.
Basically widget.SetAccessible should work. If it does not work, try a 32 bit build. The 64 bit builds do not always work.

The usual pattern in wxWidgets, though, is to create a wxAccessibility instance only on demand, by overriding the widgets’s method CreateAccessibility. Currently this is not available in wxPython, but I have submitted PRs for wxWidgets and wxPython. So, if testing is successful, this functionality should be available in the next wxPython version. At that time I will also post example code here.

I have also started work on accessibility support for wxGrid. The first step is to implement this in wxWidgets and then at some time it should arrive in wxPython as well.
(Most widgets inherit accessibility support from the native Windows widgets, but wxGrid is a generic widget on Windows and therefore all support needs to be implemented ‘manually’.)