Tkinter的event_generate命令被忽略

lem*_*sss 7 python unit-testing tkinter

我试图找出如何在对话框窗口中单元测试绑定命令.我正在尝试使用tkinter event_generate.它不像我期望的那样工作.对于这个StackOverflow问题,我通过一次调用设置了一些代码event_generate.有时这条线有效,有时就好像线条甚至不存在一样.

对话框__init__方法中的绑定如下所示:

        self.bind('<BackSpace>',  #Print "BackSpace event generated."
            lambda event: print(event.keysym, 'event generated.'))
Run Code Online (Sandbox Code Playgroud)

对话框中的任何操作都将回调其终止方法(该对话框基于Frederik Lundh在"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()
Run Code Online (Sandbox Code Playgroud)

使用下面的代码调用对话框时,任何用户操作都将最终调用terminate.在每种情况下"终止被叫"和"BackSpace事件生成".显示.这证明了对event_generate的调用是正确设置的.

parent = tk.Tk()
dialog = Dialog(parent)
dialog.wait_window()
Run Code Online (Sandbox Code Playgroud)

如果它是相关的,我应该提到我已经将Lundh的调用self.wait_window从他的对话框的__init__方法移动到调用者.虽然这打破了对话框的整洁封装,但似乎有必要进行自动化的单元测试.否则,unittest将显示对话框并停止等待用户输入.我不喜欢这个解决方案,但我不知道任何替代方案.

我遇到的问题是何时wait_window被直接调用terminate方法替换.这是我希望在单元测试中可以做的事情,即在不运行tkinter的mainloop或wait_window的情况下测试我的GUI代码.

parent = tk.Tk()
dialog = Dialog(parent)
dialog.terminate()
Run Code Online (Sandbox Code Playgroud)

这只打印"终止被叫"并且不打印"BackSpace事件生成".呼叫event_generate似乎没有效果.如果我在调试器中跟随调用,我可以看到event_generate()正在使用正确的参数调用tkinter .self = {Dialog} .99999999, sequence = {str}'<BackSpace>', kw = {dict}{} 鉴于TkCmd手册中关于窗口焦点的警告,我已经验证了带有绑定的对话框在其__init__方法中得到了重点.

Tkinter没有执行回调.为什么?

编辑:这个裸骨代码显示update工作.但是,只有在主程序调用__init__之前event_generate调用它才有效.(这个谜题已被提出作为一个单独的问题)

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
Run Code Online (Sandbox Code Playgroud)

Bry*_*ley 6

event_generate默认情况下会立即处理所有事件回调.但是,如果您在调用之前未调用update event_generate,则窗口将不可见,并且tkinter可能会忽略任何事件.您可以控制何时使用该when属性处理生成的事件.默认情况下,该值为"now",但另一个选项是"tail",这意味着在处理完任何事件(如重绘)后将其附加到事件队列.

有关该when属性的完整文档位于tcl/tk手册页上event_generate:http://tcl.tk/man/tcl8.5/TkCmd/event.htm#M34