Ich versuche herauszufinden, wie man einen Bindebefehl in einem Dialogfenster unittest. Ich versuche dies mit tkinter event_generate
. Es funktioniert nicht so, wie ich es erwarte. Für diese StackOverflow-Frage habe ich einen Code mit einem einzigen Anruf auf event_generate
eingerichtet. Manchmal funktioniert diese Linie und manchmal ist es so, als ob die Linie gar nicht existiert.Tkinter's event_generate Befehl ignoriert
Die bind in der __init__
Methode des Dialog sieht wie folgt aus:
self.bind('<BackSpace>', #Print "BackSpace event generated."
lambda event: print(event.keysym, 'event generated.'))
Jede Aktion im Dialog wird auf seiner beenden Methode zurückrufen (Der Dialog basiert auf Frederik Lundhs Beispiel Dialog in ‚An Introduction to Tkinter ‘.)
def terminate(self, event=None):
print('terminate called') # Make sure we got here and the next line will be called
self.event_generate('<BackSpace>')
self.parent.focus_set()
self.destroy()
Wenn der Dialog den Code jeder Benutzeraktion aufgerufen wird wird bis Aufruf terminate
beenden. In jedem Fall "terminate called" und "BackSpace event generated". sind angezeigt. Dies beweist, dass der Aufruf von event_generate korrekt eingerichtet ist.
parent = tk.Tk()
dialog = Dialog(parent)
dialog.wait_window()
Falls es relevant Ich sollte erwähnen, dass ich Lundhs Aufruf self.wait_window
aus seinem Dialog des __init__
Methode an den Aufrufer bewegt. Während dies die saubere Verkapselung seines Dialogs unterbricht, scheint es für automatisierte Untestests notwendig zu sein. Andernfalls zeigt der Komponententest den Dialog an und wartet auf Benutzereingaben. Ich mag diese Lösung nicht, aber mir ist keine Alternative bekannt.
Das Problem, das ich habe, ist, wenn wait_window
durch einen direkten Aufruf an die terminate
Methode ersetzt wird. Dies ist die Art von Dingen, die ich in Unittests erwarten könnte, nämlich meinen GUI-Code zu testen, ohne die Hauptschleife von tkinter oder wait_window auszuführen.
parent = tk.Tk()
dialog = Dialog(parent)
dialog.terminate()
Diese druckt nur „Terminate genannt“ und druckt nicht „Backspace Ereignis generiert hat.“. Der Aufruf an event_generate
scheint keine Wirkung zu haben. Wenn ich dem Aufruf im Debugger folge, kann ich sehen, dass tkinter's event_generate()
mit den richtigen Argumenten aufgerufen wird. self = {Dialog} .99999999, sequence = {str}'<BackSpace>', kw = {dict}{}
In Anbetracht der Warnung in den TkCmd man Seiten über den Fensterfokus habe ich verifiziert, dass der Dialog mit der Bindung in seiner __init__
Methode fokussiert ist.
Tkinter führt den Rückruf nicht aus. Warum?
EDIT: Dieser nackte Knochen Code zeigt update
funktioniert. Es funktioniert jedoch nur, wenn es in __init__
aufgerufen wird, bevor event_generate
vom Hauptprogramm aufgerufen wird. (Dieses Puzzle wurde als separate question angehoben)
class UpdWin(tk.Tk):
def __init__(self):
super().__init__()
self.bind('<BackSpace>',
lambda event: print(event.keysym, 'event generated.'))
self.update() # Update works if placed here
app = UpdWin()
app.event_generate('<BackSpace>')
# app.update() # Update doesn't work if placed here
ich dies nicht zur Arbeit kommen kann. Ich habe versucht, 'parent.update()' hinter 'dialog.terminate()' zu setzen. Ich habe auch versucht, 'self.parent.update()' unmittelbar nach 'self.event_generate ('')' in der 'terminate'-Methode zu setzen, falls' destroy 'mehr tun würde, als sichtbare Elemente zu entfernen. Ich habe bemerkt, dass die Fenster in beiden Fällen kurz auf dem Bildschirm angezeigt wurden. –
lemi57ssss
Wenn das Widget zerstört wird, bevor es das Ereignis verarbeiten kann (dh wenn Sie 'dialog.terminate()' aufrufen und dann 'update()') aufrufen, wird das Ereignis wahrscheinlich ignoriert, weil das Fenster nicht mehr existiert. –
Ich habe es geschafft, Update-Funktion zu bekommen, aber auf eine sehr eigenartige Weise. Es scheint nur zu funktionieren, wenn 'update' die Ereigniswarteschlange in' _init__' vor einem nachfolgenden Aufruf von 'event_generate' leert. Ich bin verwirrt und besorgt, da ich es vorziehen würde, den Code nicht zu ändern, um das Testen zu erleichtern. Sehen Sie meine Bearbeitung für eine nackte Knochen-Code-Illustration. – lemi57ssss