2

I'm running Python 2.7.5 with wxWidgets installed through homebrew.

My issue is that keyboard events aren't picked up at all when running on OS/X. Consider the following sample source:

noname.py:

import wx
import wx.xrc
class MyFrame2 ( wx.Frame ):
   def __init__( self, parent ):
      wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
      self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
      bSizer1 = wx.BoxSizer( wx.VERTICAL )
      self.m_button1 = wx.Button( self, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0 )
      bSizer1.Add( self.m_button1, 0, wx.ALL, 5 )
      self.SetSizer( bSizer1 )
      self.Layout()
      self.Centre( wx.BOTH )
      # Connect Events
      self.m_button1.Bind( wx.EVT_BUTTON, self.OnClick )
   def __del__( self ):
      pass
   # Virtual event handlers, overide them in your derived class
   def OnClick( self, event ):
      event.Skip()

main.py:

from noname import MyFrame2
class MyFrame2Impl(MyFrame2):
    def __init__(self, parent):
        MyFrame2.__init__(self, parent)
    def OnClick(self, event):
        self.m_button1.SetLabel(str(wx.Window.FindFocus() != None))

import wx
app = wx.App(False)  # Create a new app, don't redirect stdout/stderr to a window.
frame = MyFrame2Impl(None) # A Frame is a top-level window.
frame.m_button1.SetFocus()
frame.Show(True)     # Show the frame.
app.MainLoop()

On Ubuntu, once I click the button, it shows "True". Pressing spacebar clicks the button. On OS/X, once I click the button, it shows "False". Pressing spacebar achieves nothing.

At the bottom of the WxMac FAQ (http://www.wxwidgets.org/docs/faqmac.htm) it says this:

Why can't I set focus to my wxMac application? Because you didn't build your application as a bundle. You must create a bundle for Mac OS X applications, simply running the usual g++ wx-config --cxxflags --libs -o minimal minimal.cpp is not enough to build a correctly working Mac application. Please look at the samples makefiles which do build bundles under Mac OS X or read this wiki topic for more details.

I've made a bundle using this script:

from setuptools import setup
APP = ["main.py"]
OPTIONS = {"argv_emulation": True, "includes": ["wx"]}
setup(app=APP, options={"py2app": OPTIONS}, setup_requires=["py2app"])

which I use to build a bundle with the command:

python setup.py py2app

This makes an executable, but the focus problem still persists. As a consequence, I'm unable to use the keyboard to control the application. How can I get the application to detect keyboard events?

mpenkov
  • 21,621
  • 10
  • 84
  • 126

3 Answers3

1

Try putting a wx.Panel as the ONLY child for the frame. Next put all the other widgets in the panel (i.e. set the panel as the parent of the other widgets). I know the panel adds tabbing functionality cross-platform, so I suspect this might help with other keyboard events.

Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88
  • Thank you for your answer. It's helped a little bit: it appears that now *something* has focus, but it isn't the button (if I press space, nothing happens). This continues to be the case even if I click the button (this *should* transfer focus to the button, but doesn't for some reason). – mpenkov Oct 17 '13 at 10:27
  • You can use FindFocus to help you figure out what has the focus. See http://stackoverflow.com/questions/3452489/wxpython-how-do-i-find-out-which-widget-has-the-focus/3452599#3452599. I also wrote a little about focus events here: http://www.blog.pythonlibrary.org/2009/08/27/wxpython-learning-to-focus/. You might also try the Widget Inspection Tool – Mike Driscoll Oct 17 '13 at 14:09
  • 1
    Thank you for the suggestion. I did a bit of debugging, and found out that on OS/X, the parent Panel is getting the focus when the Button is clicked. On Ubuntu, the Button itself is getting the focus when the button is clicked. Why is there a discrepancy? How can I get the Button to have focus on OS/X? – mpenkov Oct 23 '13 at 04:35
0

I ended up coding around the problem.

Previously, my application was handling keyboard events globally (see http://wiki.wxwidgets.org/Catching_key_events_globally).

I couldn't get this to work on OS/X, so I gave up and rewrote the application such that it captures keyboard events locally. More specifically, the application includes a menu bar, and that menu bar has items. I can handle keyboard events by assigning keyboard shortcuts to the menu bar items.

I'm not sure why global handling doesn't work on OS/X, but I don't really care anymore.

mpenkov
  • 21,621
  • 10
  • 84
  • 126
0

Solved! Button focusable or not depends on keyboard preferences:

System Preferences -> Keyboard -> Shortcuts -> Check "All Controls" at the bottom (in Full Keyboard Access Field).

Now with WxWidgets (or for Any other application) you can tab-traverse on Buttons as well.

Cheers!

user18853
  • 2,771
  • 1
  • 21
  • 17