[wxPython] wxListCtrl_virtual crashes and I can't find what I'm doing wrong


F

F. GEIGER

[Posted to comp.soft-sys.wxwindows and comp.lang.python]


Hi all,

in my MainFrame class I have def'ed a method which is called on idle. There
I retrieve the frame's title for further processing:

currentTitle = self.GetTitle().

No problem so far.

I have a wxNotebook containing several pages. Those pages contain controls
updating themselves, using a wxTimer for that.

No problem so far.

I have added another page containing a control derived from wxListCtrl,
virtual style.

And now I have problems:

This control is named VipAPSpooler. It first used a wxTimer, to update
itself periodically: If the underlying model had changed in the number of
items, it exec'ed a DeleteAllItems() and a SetItemCount().

This did not work: The debugger halted in the MainFrame's(!) on-idle-method
in line

currentTitle = self.GetTitle()

saying "Inappropriate argument type: an integer is required".

I thought, that using too many wxTimer-s could cause this problem (other
controls used timers too to update themselves).

So I decided to eliminate all timers and to write an update method for all
controls that should be able to update themselves. This update-method were
then called from the MainFrames's on-idle-method. The rationale: No more
timers and only one on-idle-method.

But that did not solve the problem. The same and sometimes other weired
errors popped up now in code called by OnGetItemAttr() ans OnGetItemText()
of the virtual wxListCtrl.

Example:

def __str__(self):
if self._value: # <- "Inappropriate argument type: an integer is
required".
return str(self._value)
return ''

Or this:

def OnGetItemAttr(self, item):
if item == self.model().currentLineNbr(): # <- "Inappropriate argument
type: an integer is
return self._attr
return None


Executing the offending line in the Debug Probe (yes, it's WingIDE) in each
case passes w/o problems - weird. Looking at the stack data doesn't show any
data corruption, everything seems okay.

I commented out this and that and seem to have found out, that as soon
SetItemCount() is called, the control is no more able to do its job.

I'm stuck in the middle. Despite the fact that my code is cut & pasted from
the demo I am sure to overlook something.

Any idea?

Kind regards
Franz GEIGER

P.S.:
Python 2.3.2 and wxPython 2.4.2.4u on Win2k.
and
Python 2.3.2 and wxPython 2.5.1.5u on WinXP.
 
Ad

Advertisements

F

F. GEIGER

Thank you, Robin, for answering that quick!

Robin Dunn said:
F. GEIGER wrote:
[...]
And now I have problems:

This control is named VipAPSpooler. It first used a wxTimer, to update
itself periodically: If the underlying model had changed in the number of
items, it exec'ed a DeleteAllItems() and a SetItemCount().

Since it's virtual just a SetItemCount should be enough.

Okay, I'll try that.

If an exception happens in some of the C++ wrapper code (such as after
returning from an event handler or a callback), then the next time
control enters Python code the exception is detected and raised from
that point. Normally the C++ code will detect the situation and print
the traceback and then clear the error, but it's possible that this is a
case that it is missed.

Does the same thing happen if you run outside of WinIDE? Try running it

Yes, but see below.

from a command-line window using python.exe so you can see any warning
log messages that wxWidgets is issuing. I seem to recall that WinIDE
has a setting that causes it to stop on all exceptions, even if they are
caught or cleared, perhaps changing that will help.



Doubtful, unless you have dozens of timers.

Glad to here that. I'll unroll all my changes regarding timers. They are
really handy for having controls updating themselves.
Because it probably happened in whatever weas executed before the error
was detected.



Do you also implement OnGetItemImage? Does it always return an integer?
(If you don't use an ImageList for this control then just return -1.)

That's it <face flushed red/>.

I had written:

def OnGetItemImage(self, item):
# if item % 3 == 0:
# return self.idx1
# else:
# return -1
pass

Oh god, how embarrassing!

When I deleted the whole method, wxPython 2.5 threw a wxAssert stating, that
OnGetItemImage() shouldn't be called or something like that (can reproduce
that if there's interest on it). Anyway, overriding this method seems to be
a must. But with the right return value, of course...

So, writing

def OnGetItemImage(self, item):
return -1

did it. Small cause, big effect.

Again, thanks a lot, Robin!

Kind regards
Franz GEIGER
 

Top