I recently tried to help someone (on the wxPython mailing list) figure out how to use a Grid widget (wx.grid.Grid) via XRC. It should be simple, but if you run the code below, you’ll discover a weird issue:
import wx from wx import xrc ######################################################################## class MyApp(wx.App): def OnInit(self): self.res = xrc.XmlResource("grid.xrc") frame = self.res.LoadFrame(None, 'MyFrame') panel = xrc.XRCCTRL(frame, "MyPanel") grid = xrc.XRCCTRL(panel, "MyGrid") print type(grid) grid.CreateGrid(25, 6) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 5) panel.SetSizer(sizer) frame.Show() return True if __name__ == "__main__": app = MyApp(False) app.MainLoop()
You’ll note that when you run this, the type that is printed out is a “wx._windows.ScrolledWindow”, not a Grid object. Thus you’ll end up with the following traceback:
AttributeError: 'ScrolledWindow' object has no attribute 'CreateGrid' File "c:\Users\mdriscoll\Desktop\xrcGridDemo.py", line 26, inapp = MyApp(False) File "C:\Python26\Lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 7981, in __init__ self._BootstrapApp() File "C:\Python26\Lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 7555, in _BootstrapApp return _core_.PyApp__BootstrapApp(*args, **kwargs) File "c:\Users\mdriscoll\Desktop\xrcGridDemo.py", line 14, in OnInit grid.CreateGrid(25, 6)
Now you may be wondering what’s in the XRC file, so here’s its contents:
As you can see, you should be getting a wxGrid back. What’s the solution? You need to import wx.grid! See this thread for more information. According to Robin Dunn, creator of wxPython, here is the reason you need to do that:
You need to import wx.grid in your python code. When you do that then
some internal data structures are updated with the type info for the
grid classes, and this info is used when figuring out how to convert a
C++ pointer to a Python object of the right type for the XRCCTRL return
value.
Thus the updated code would look like this:
import wx import wx.grid from wx import xrc ######################################################################## class MyApp(wx.App): def OnInit(self): self.res = xrc.XmlResource("grid.xrc") frame = self.res.LoadFrame(None, 'MyFrame') panel = xrc.XRCCTRL(frame, "MyPanel") grid = xrc.XRCCTRL(panel, "MyGrid") print type(grid) grid.CreateGrid(25, 6) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 5) panel.SetSizer(sizer) frame.Show() return True if __name__ == "__main__": app = MyApp(False) app.MainLoop()
Now if you run into this oddball issue, you too will know what to do.
Related Articles
- wxPython: An Intro to XRC
- wxPython: An XRCed tutorial
Pingback: Mike Driscoll: wxPython: Creating a Grid with XRC | The Black Velvet Room