wxpython and EVT_KILL_FOCUS

Stefanie Wagner wagner at inet-nb.de
Tue Nov 15 10:13:45 EST 2005


Hello, I am fighting with EVT_KILL_FOCUS for quite a time now and I
don't succeed at all.

Situation:

If a user leaves a textfield the entered information should be checked
and an additional window should be opened to make a search possible to
complete the entry.

Basic solution:

def __init__(...):
  ...
  self.artikelnrBox = wxTextCtrl(self.bestelldialog, -1, artikelnr,
wxPoint(60,290), wxSize(60, -1))
  ...
  EVT_KILL_FOCUS(self.artikelnrBox, self.OnArtikel)
  ...

def OnArtikel(self,event):
  event.Skip()
  ....
  artikelnr = self.artikelnrBox.GetValue().strip()
  ...
  dialog =
dialog_stamm_artikel.ArtikelSucheDialog(self.bestelldialog,artikelnr)
  ergebnis,artikelid = dialog.GetValues()
  dialog.Destroy()
  ...

Problem:

If I don't open any dialog everything works fine. But if there is a
dialog around the window opens, I can count to two and the whole
application crashes.

The error message is:
(gui.py:29768): Gtk-WARNING **: GtkEntry - did not receive
focus-out-event. If you
connect a handler to this signal, it must return
FALSE so the entry gets the event as well

Gtk-ERROR **: file gtkentry.c: line 4919 (blink_cb): assertion failed:
(GTK_WIDGET_HAS_FOCUS (entry))
aborting...

Reason of the problem:

I found a very good description for the reason:

> This is a lot easier to understand with a timeline:

> - focus into GtkEntry
> - GtkEntry installs timeout for cursor blinking
> - focus out of entry
> - GtkEntry emits focus-out-event
> - your handler runs **before the default handler**.
> - your handler traps exception and creates dialog box
> - dialog box runs nested event loop
> - event processing continues, focus goes to another widget
> - entry's cursor blink timeout is still installed, and runs again.
> entry does not have focus, but timeout has run, so the widget
> is in an invalid state and calls g_error() with a nastygram.
> - default handler runs, uninstalls cursor blink timeout

> The problem is that you're allowing the event loop to run in your handler for focus-out.

Ok, if I use EVT_KILL_FOCUS the event has not finished completly, this
timeout is still around. That's ok with me but I thought this is what
event.Skip() is for, to call the standard handler.

Solution:

And there I am. event.Skip() doesn't help at all. And the other source
gives the following suggestion:

> a) use signal_connect_after to have your handler run *after* the default handler for focus-out-event instead of before.
> b) leave the signal connected normally, but in your "catch" block, instead of running the dialog right then, defer it with an idle, like this:

I couldn't find signal_connect_after anywhere in wxpython and I don't
know how to use idle in this case. And I have the problem more than
once (every time a have an error message in other EVT_KILL_FOCUS
routines).

There must be some solution to use EVT_KILL_FOCUS and a dialog without
killing the application.

Please help!

 Steffi




More information about the Python-list mailing list