views:

49

answers:

2

I'm trying to make a new wx.Choice-like control (actually a replacement for wx.Choice) which uses the wx.ItemContainer to manage the list of items. Here is a minimal example showing the error:

import wx
class c(wx.ItemContainer):
    def __init__(my): pass

x = c()
x.Clear()

This fails with:

Traceback (most recent call last):
  File "", line 1, in 
  File "c:\python25\lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 1178
7, in Clear
    return _core_.ItemContainer_Clear(*args, **kwargs)
TypeError: in method 'ItemContainer_Clear', expected argument 1 of type 'wxItemContainer *'

The other controls using ItemContainer seem to be internal to wxWindows, so it may not be possible for me to use it this way. However, it would certainly be convenient.

Any ideas on what I'm doing wrong?

A: 

Your suspicions are on the right track. You can't subclass any of the wxWidgets types, because they're in the C++ domain and only nominally wrapped in Python. Instead, you need a Py* class, which you can subclass. The explanation is given in this Wiki entry on writing custom controls.

For ItemContainer, there doesn't appear to be such a wrapper - and the fact that ItemContainer is used as a parent in a multiple inheritance pattern may even complicate matters.

I suspect that from within wxPython, it may not be possible to replace ItemContainer--and if you do need it, it will have to be integrated at the C++ level.

Jason R. Coombs
Thanks for the answer. I wound up doing something like this.
oofoe
+1  A: 

wx.ItemContainer can't be instantiated directly e.g. try

x = wx.ItemContainer()

it throws error

Traceback (most recent call last):
  File "C:\<string>", line 1, in <module>
  File "D:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 11812, in __init__
    def __init__(self): raise AttributeError, "No constructor defined"
AttributeError: No constructor defined

Reason being it is a type of interface(if we can call that in python) and you can not call __init__ on it, instead use it as second base and override the methods you use e.g.

class C(wx.PyControl, wx.ItemContainer): 
    def __init__(self, *args, **kwargs):
        wx.PyControl.__init__(self, *args, **kwargs)

    def Clear(self):
        pass

app = wx.PySimpleApp()

frame = wx.Frame(None,title="ItemContainer Test")
x = C(frame)
x.Clear()

frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
Anurag Uniyal
This is a cool trick. I'll keep this in mind. I wound up creating my own control in the end (see above answer), but I think I would have had a much easier time of it if I had seen your response. Thanks for answering!
oofoe