wx.ListCtrl.OnGetItemColumnImage

I’m having the oddest error.

If I have a wx.ListCtrl subclass with wx.LC_REPORT and wx.LC_VIRTUAL, I can load it up and everything looks fine-- its full of text.

However, if I define:

def OnGetItemColumnImage(self, row, col):

    return -1

Then when I load up the view-- its blank. Nothing shows up.

I have nooo idea why. The data IS there: OnGetItemText IS being called, and it IS returning real data.

And what’s worse? The testcase demo I was going to attach to demonstrate the problem-- refuses to break.

Uh. Any clue? :slight_smile:

As an aside, this came up while testing a totally different problem: trying to construct a wx.Image (with a valid path, that can be constructed anywhere else) within OnGetItemColumnImage would say:

TypeError: coercing to Unicode: need string or buffer, int found

I don’t know if its relavent, but I’m just getting odd behavior when trying to overload that method (and I don’t see a wx.PyListCtrl
)
–S

Do you assign a image list to the ListCtrl?

Cheers, Frank

···

2007/2/19, Stephen Hansen <apt.shansen@gmail.com>:

I'm having the *oddest* error.

If I have a wx.ListCtrl subclass with wx.LC_REPORT and wx.LC_VIRTUAL, I can
load it up and everything looks fine-- its full of text.

However, if I define:

    def OnGetItemColumnImage(self, row, col):
        return -1

Then when I load up the view-- its blank. Nothing shows up.

I have nooo idea why. The data IS there: OnGetItemText IS being called, and
it IS returning real data.

And what's worse? The testcase demo I was going to attach to demonstrate the
problem-- refuses to break.

Uh. Any clue? :slight_smile:

As an aside, this came up while testing a totally different problem: trying
to construct a wx.Image (with a valid path, that can be constructed anywhere
else) within OnGetItemColumnImage would say:

    TypeError: coercing to Unicode: need string or buffer, int found

I don't know if its relavent, but I'm just getting odd behavior when trying
to overload that method (and I don't see a wx.PyListCtrl )

Do you assign a image list to the ListCtrl?

Cheers, Frank

I didn’t at first-- I was returning “-1” from the method, so don’t think the ImageList woulda been accessed at all. However, just to test it-- I added one, and the behavior is still identical.

Stephen Hansen wrote:

I'm having the *oddest* error.

If I have a wx.ListCtrl subclass with wx.LC_REPORT and wx.LC_VIRTUAL, I can load it up and everything looks fine-- its full of text.

However, if I define:

    def OnGetItemColumnImage(self, row, col):
        return -1

Then when I load up the view-- its blank. Nothing shows up.

I have nooo idea why. The data IS there: OnGetItemText IS being called, and it IS returning real data.

And what's worse? The testcase demo I was going to attach to demonstrate the problem-- refuses to break.

Uh. Any clue? :slight_smile:

Only to closely examine any code differences between your working sample and non-working app.

As an aside, this came up while testing a totally different problem: trying to construct a wx.Image (with a valid path, that can be constructed anywhere else) within OnGetItemColumnImage would say:

    TypeError: coercing to Unicode: need string or buffer, int found

Well, were you passing an int?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

As an aside, this came up while testing a totally different problem:

trying to construct a wx.Image (with a valid path, that can be
constructed anywhere else) within OnGetItemColumnImage would say:

TypeError: coercing to Unicode: need string or buffer, int found

Well, were you passing an int?

Wow.

I found the problem. I can even reproduce it. But it is bizarre.

The situation: if non-String data is returned from OnGetItemText (say, … 4), then creating an image in OnGetItemColumnImage throws that bizarre error. It’s like the real error is getting snuffed and held for awhile.

class TestList(wx.ListCtrl):
def init(self, parent):
wx.ListCtrl.init(self, parent, -1, style=wx.LC_REPORT | wx.LC_VIRTUAL)

    self.SetItemCount(1)
    self.InsertColumn

(1, “Other”)

def OnGetItemText(self, item, col):
    return 4
   
def OnGetItemColumnImage(self, item, image):
    img = wx.EmptyImage(16,16)
    return -1

As long as that image call isn’t there, it doesn’t report the actual error. (the column-portion is just blank)

Deferred exceptions are confusing. :slight_smile:

Stephen Hansen wrote:

     > As an aside, this came up while testing a totally different problem:
     > trying to construct a wx.Image (with a valid path, that can be
     > constructed anywhere else) within OnGetItemColumnImage would say:
     >
     > TypeError: coercing to Unicode: need string or buffer, int found

    Well, were you passing an int?

Wow.

I found the problem. I can even reproduce it. But it is bizarre.

The situation: if non-String data is returned from OnGetItemText (say, ... 4), then creating an image in OnGetItemColumnImage throws that bizarre error. It's like the real error is getting snuffed and held for awhile.

class TestList(wx.ListCtrl):
    def __init__(self, parent):
        wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.LC_VIRTUAL)
               self.SetItemCount(1)
        self.InsertColumn (1, "Other")
           def OnGetItemText(self, item, col):
        return 4
           def OnGetItemColumnImage(self, item, image):
        img = wx.EmptyImage(16,16)
        return -1

As long as that image call isn't there, it doesn't report the actual error. (the column-portion is just blank)

Deferred exceptions are confusing. :slight_smile:

Actually, in this case it does make sense, but you have to know a bit more about how things work in the guts of wxPython. When the call to OnGetItemText returns to the C++ code it notices the error in return type when it tries to convert the PyObject into a wxString and sets an exception, but Python won't do anything with that until it executes another Python statement, or until control returns from Python to C++ again. Control is staying in C++ code until it makes the call to OnGetItemColumnImage, where it then executes the wx.EmptyImage statement. Then Python notices that the exception has been set and goes through its routine of raising it. I expect that you could have had nearly anything on that line, but apparently just a simple return of a constant value is not enough to trigger Python into raising the exception...

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Well-- the problem is, that exception isn’t being just deferred until the next time Python takes control. I did the OnGetItemText days ago and the exception never appeared once; it just went away, for days.

I can do any Python-stuff within OnGetColumnImage and the exception doesn’t appear either; it’s only if I call back into wxPython in any way (even wx.GetApp()) does the exception get revived. It seems like the exception is getting “stuck” somewhere and is discarded silently not too long after. OnGetColumnImage calling back into Python lets it slip out, but if it wasn’t there, the exception just poofs.

To check, I took out OnGetColumnImage, and stuck in a silly event handler in to fire off if the ListCtrl is clicked, just to make sure its getting back into Python at some point to see if the exception comes out, and it doesn’t.

I say “on OSX” because I’m 90% sure the exception propagates out and is shown on

···

On 2/20/07, Robin Dunn robin@alldunn.com wrote:

Actually, in this case it does make sense, but you have to know a bit
more about how things work in the guts of wxPython. When the call to
OnGetItemText returns to the C++ code it notices the error in return

type when it tries to convert the PyObject into a wxString and sets an
exception, but Python won’t do anything with that until it executes
another Python statement, or until control returns from Python to C++

again. Control is staying in C++ code until it makes the call to
OnGetItemColumnImage, where it then executes the wx.EmptyImage
statement. Then Python notices that the exception has been set and goes
through its routine of raising it. I expect that you could have had

nearly anything on that line, but apparently just a simple return of a
constant value is not enough to trigger Python into raising the exception…

Stephen Hansen wrote:

    Actually, in this case it does make sense, but you have to know a bit
    more about how things work in the guts of wxPython. When the call to
    OnGetItemText returns to the C++ code it notices the error in return
    type when it tries to convert the PyObject into a wxString and sets an
    exception, but Python won't do anything with that until it executes
    another Python statement, or until control returns from Python to C++
    again. Control is staying in C++ code until it makes the call to
    OnGetItemColumnImage, where it then executes the wx.EmptyImage
    statement. Then Python notices that the exception has been set and goes
    through its routine of raising it. I expect that you could have had
    nearly anything on that line, but apparently just a simple return of a
    constant value is not enough to trigger Python into raising the
    exception...

Well-- the problem is, that exception isn't being just deferred until the next time Python takes control. I did the OnGetItemText days ago and the exception never appeared once; it just went away, for days.

I can do any Python-stuff within OnGetColumnImage and the exception doesn't appear either; it's only if I call back into wxPython in any way (even wx.GetApp()) does the exception get revived. It seems like the exception is getting "stuck" somewhere and is discarded silently not too long after. OnGetColumnImage calling back into Python lets it slip out, but if it wasn't there, the exception just poofs.

Ok, I'll check into this and see if I can find what is going on.

···

On 2/20/07, *Robin Dunn* <robin@alldunn.com <mailto:robin@alldunn.com>> > wrote:

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!