Tkinter的event_generate命令被忽略

时间:2014-12-20 15:53:42

标签: python tkinter unit-testing

我试图弄清楚如何在对话框窗口中对bind命令进行单元测试。我尝试使用tkinter event_generate进行此操作。它不像我期望的那样工作。对于此StackOverflow问题,我通过一次调用event_generate设置了一些代码。有时这条线有效,有时就好像线条甚至不存在一样。

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

        self.bind('<BackSpace>',  #Print "BackSpace event generated."
            lambda event: print(event.keysym, 'event generated.'))

对话框中的任何操作都将回调其终止方法(该对话框基于Frederik Lundh的示例对话框&#39;简介Tkinter&#39;。)

    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()

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

parent = tk.Tk()
dialog = Dialog(parent)
dialog.wait_window()

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

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

parent = tk.Tk()
dialog = Dialog(parent)
dialog.terminate()

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

Tkinter没有执行回调。为什么呢?

编辑:这个裸骨代码显示update正常工作。但是,只有在主程序调用{​​{1}}之前在__init__中调用它才有效。 (这个谜题已被提升为separate question

event_generate

3 个答案:

答案 0 :(得分:6)

默认情况下,

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

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

答案 1 :(得分:1)

@lemi57ssss 我知道这是一个老问题,但我只想强调 Bryan Oakley 提出的观点并更正您的最后一个代码以使其工作。他说你必须先更新,然后它才能响应生成的事件。因此,如果您切换 update()event_generate() 的位置,您将获得“生成的 BackSpace 事件”。文本打印出来。

当您将 update() 放入 __init__() 时它起作用是因为相同的原因,即它在 event_generated() 之前首先被调用。< /p>

请参阅下面的修正代码:

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.update() # Update also works if you placed it here
app.event_generate('<BackSpace>')

答案 2 :(得分:0)

不知道这是否与您的问题有关,但是我通过首先致电widget.event_generate()使widget.focus_set()正常工作。