简体   繁体   English

如何测试带有 Tkinter 主循环的 Python 代码?

[英]How can Python code with Tkinter mainloop be tested?

How can I test the following code with nosetests?如何用鼻子测试测试以下代码?

# GUI
try:
    # for Python2
    import Tkinter as tk
except ImportError:
    # for Python3
    import tkinter as tk


def main():
    root = tk.Tk()
    canvas = tk.Canvas(root, width=250, height=250)
    canvas.pack()
    root.bind('<B1-Motion>', lambda x: True)
    root.bind('<Button-1>', lambda x: True)
    root.mainloop()

When I call main() the mainloop gets executed.当我调用main()时,主循环被执行。 How can I prevent that?我怎样才能防止这种情况?

Instead of calling root.mainloop() the idea is to call root.update().这个想法不是调用 root.mainloop(),而是调用 root.update()。 This will run the tk loop only once (any pending event will hence be dispatched and handled by your application).这将只运行 tk 循环一次(因此任何挂起的事件都将由您的应用程序调度和处理)。

Testing the application behavior becomes then a succession of steps like:测试应用程序的行为变成了一系列的步骤,例如:

root.event_generate('<B1-Motion>') # will generate a "fake" event <B1-Motion>
root.update()
# test that '<B1-Motion>' callback was correctly executed (by eg checking an expected state of you app
root.event_generate('<Button-1>')
root.update()
# test ....

Note that you can also directly invoke button (as if they were clicked) by calling button.invoke()请注意,您也可以通过调用 button.invoke() 直接调用按钮(就像它们被点击一样)

You can redesign this into a Class:您可以将其重新设计为 Class:


import tkinter as tk

class GUI(tk.Tk):
    def __init__(self):
        super().__init__()
        canvas = tk.Canvas(self, width=250, height=250)
        canvas.pack()
        self.bind('<B1-Motion>', lambda x: True)
        self.bind('<Button-1>', lambda x: True)
    


if __name__ == "__main__":
    
    root = GUI()
    root.mainloop()

Your test should workaround the object created from GUI class easily, and to guarantee that the mainloop wouldn't run once you import this file elsewhere, I just added the if __name__ == "__main__": block at the end.您的测试应该解决从 GUI class 创建的 object 的问题,并且为了保证在您将这个文件导入其他地方后主循环不会运行,我只是在最后添加了if __name__ == "__main__":块。

To stop the mainloop() running, you could comment out the line, this would run main() without Tkinter creating the canvas.要停止 mainloop() 运行,您可以注释掉该行,这将运行 main() 而无需 Tkinter 创建画布。

try:
    # for Python2
     import Tkinter as tk
except ImportError:
     # for Python3
    import tkinter as tk


def main():
    root = tk.Tk()
    canvas = tk.Canvas(root, width=250, height=250)
    canvas.pack()
    root.bind('<B1-Motion>', lambda x: True)
    root.bind('<Button-1>', lambda x: True)
    #root.mainloop() """#stops the line being run"""
main()

or have the root.mainloop() outside the main() function and comment out mainloop()或者在 main() 函数之外设置 root.mainloop() 并注释掉 mainloop()

try:
    # for Python2
     import Tkinter as tk
except ImportError:
     # for Python3
    import tkinter as tk
def main():
    root = tk.Tk()
    canvas = tk.Canvas(root, width=250, height=250)
    canvas.pack()
    root.bind('<B1-Motion>', lambda x: True)
    root.bind('<Button-1>', lambda x: True)
main()
#root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM