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.artikelnrB ox = wxTextCtrl(self .bestelldialog, -1, artikelnr,
wxPoint(60,290) , wxSize(60, -1))
...
EVT_KILL_FOCUS( self.artikelnrB ox, self.OnArtikel)
...
def OnArtikel(self, event):
event.Skip()
....
artikelnr = self.artikelnrB ox.GetValue().s trip()
...
dialog =
dialog_stamm_ar tikel.ArtikelSu cheDialog(self. bestelldialog,a rtikelnr)
ergebnis,artike lid = dialog.GetValue s()
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:
[color=blue]
> This is a lot easier to understand with a timeline:[/color]
[color=blue]
> - 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[/color]
[color=blue]
> The problem is that you're allowing the event loop to run in your handler for focus-out.[/color]
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:
[color=blue]
> 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:[/color]
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
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.artikelnrB ox = wxTextCtrl(self .bestelldialog, -1, artikelnr,
wxPoint(60,290) , wxSize(60, -1))
...
EVT_KILL_FOCUS( self.artikelnrB ox, self.OnArtikel)
...
def OnArtikel(self, event):
event.Skip()
....
artikelnr = self.artikelnrB ox.GetValue().s trip()
...
dialog =
dialog_stamm_ar tikel.ArtikelSu cheDialog(self. bestelldialog,a rtikelnr)
ergebnis,artike lid = dialog.GetValue s()
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:
[color=blue]
> This is a lot easier to understand with a timeline:[/color]
[color=blue]
> - 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[/color]
[color=blue]
> The problem is that you're allowing the event loop to run in your handler for focus-out.[/color]
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:
[color=blue]
> 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:[/color]
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