[wxPython] invalid page fault in module WX22_0.DLL

When running the experimental code below
on Windows98 2nd edition, Python 1.5.2,
wxPython 2.2, the window pops up fine.
However, when clicking the "X" to close
the window, the "This program has
performed an illegal operation..."
dialog appears with the Details>>

PYTHON caused an invalid page fault in
module WX22_0.DLL at 017f:00c8126f.

The same code runs fine on an Alpha
with Tru64 Unix.

I have been trying to isolate the problem
for some time. There is no illegal operation
if I take out the first EVT_KILL_FOCUS.
Taking out the second does not make
a difference.
There also is no problem if I take out
the first EVT_TEXT_ENTER and at the same
time set self.ID_W = -1.
However, I really need that ID because I
want to control both event types.

Is there something I am doing wrong?
Or is this a bug in the library?

Thanks for your help, and thanks for the
response yesterday!

Ralf

from wxPython.wx import *
from string import atoi

class MySW(wxScrolledWindow):
  def __init__(self, parent, id = -1):
    wxScrolledWindow.__init__(self, parent, id, wxPoint(0, 0),
                              wxDefaultSize, wxSUNKEN_BORDER)
    self.SetSize(20, 20)

  def getWidth(self):
    return self.maxWidth

  def getHeight(self):
    return self.maxHeight

  def SetSize(self, W, H):
    if (W > 0): self.maxWidth = W
    if (H > 0): self.maxHeight = H
    self.SetScrollbars(20, 20, (self.maxWidth + 19) / 20,
                               (self.maxHeight + 19) / 20)

class MyApp(wxApp):

  def OnInit(self):
    ID_FRAME = NewId()
    self.frame = wxFrame(NULL, ID_FRAME, "Task Parameters",
                         wxDefaultPosition, wxSize(300, 400))

    ID_SW = NewId()
    self.sw = MySW(self.frame, ID_SW)

    wxStaticText(self.sw, -1, "Width", wxPoint(5, 25), wxSize(75, 20))
    self.ID_W = NewId()
    self.Ctrl_W = wxTextCtrl(self.sw, self.ID_W, str(self.sw.getWidth()),
      wxPoint(80, 25), wxSize(150, 20), wxTE_PROCESS_ENTER)
    self.Ctrl_W.SetInsertionPointEnd()
    EVT_TEXT_ENTER(self.sw, self.ID_W, self.OnTextEnter)
    EVT_KILL_FOCUS(self.Ctrl_W, self.OnKillFocus)
    self.Ctrl_W.SetBackgroundColour(wxNamedColor("WHITE"))

    wxStaticText(self.sw, -1, "Height", wxPoint(5, 75), wxSize(75, 20))
    self.ID_H = NewId()
    self.Ctrl_H = wxTextCtrl(self.sw, self.ID_H, str(self.sw.getHeight()),
      wxPoint(80, 75), wxSize(150, 20), wxTE_PROCESS_ENTER)
    self.Ctrl_H.SetInsertionPointEnd()
    EVT_TEXT_ENTER(self.sw, self.ID_H, self.OnTextEnter)
    EVT_KILL_FOCUS(self.Ctrl_H, self.OnKillFocus)
    self.Ctrl_H.SetBackgroundColour(wxNamedColor("WHITE"))

    self.frame.Show(true)
    self.SetTopWindow(self.frame)
    wxYield()
    return true

  def OnTextEnter(self, event):
    id = event.GetId()
    if (id != self.ID_W and id != self.ID_H): raise RuntimeError
    if (id == self.ID_W):
      ctrl = self.Ctrl_W
    else:
      ctrl = self.Ctrl_H
    i = event.GetString()
    try: i = atoi(i)
    except:
      ctrl.SetBackgroundColour(wxNamedColor("RED"))
      ctrl.Refresh()
      return
    if (id == self.ID_W):
      self.sw.SetSize(i, -1)
    else:
      self.sw.SetSize(-1, i)
    ctrl.SetBackgroundColour(wxNamedColor("WHITE"))
    ctrl.Clear()
    ctrl.SetValue(str(i))
    ctrl.SetInsertionPointEnd()

  def OnKillFocus(self, event):
    id = event.GetId()
    if (id != self.ID_W and id != self.ID_H): raise RuntimeError
    if (id == self.ID_W):
      ctrl = self.Ctrl_W
    else:
      ctrl = self.Ctrl_H
    i = ctrl.GetValue()
    try: i = atoi(i)
    except:
      ctrl.SetBackgroundColour(wxNamedColor("RED"))
      ctrl.Refresh()
      event.Skip()
      return
    if (id == self.ID_W):
      self.sw.SetSize(i, -1)
    else:
      self.sw.SetSize(-1, i)
    ctrl.SetBackgroundColour(wxNamedColor("WHITE"))
    ctrl.Clear()
    ctrl.SetValue(str(i))
    ctrl.SetInsertionPointEnd()
    event.Skip()

app = MyApp(0)
app.MainLoop()

--== Sent via Deja.com http://www.deja.com/ ==--
Before you buy.

I have been trying to isolate the problem
for some time. There is no illegal operation
if I take out the first EVT_KILL_FOCUS.
Taking out the second does not make
a difference.
There also is no problem if I take out
the first EVT_TEXT_ENTER and at the same
time set self.ID_W = -1.
However, I really need that ID because I
want to control both event types.

Is there something I am doing wrong?
Or is this a bug in the library?

My guess is that Windows is sending another kill focus event when the text
control with the focus is destroyed. In your OnKillFocus you end up trying
to call methods on a C++ object that no longer exists and so it ends up
accessing garbage and crashing.

Try this: Create a flag initialized to false to specify that the frame is
closing. Add an EVT_CLOSE handler on the frame that sets the flag to true
and calls event.Skip(). In OnKillFocus only execute the current code if the
flag is false.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com
http://wxpython.org Java give you jitters?
http://wxpros.com Relax with wxPython!