`new_root.mainloop()` 不会使主窗口无响应 [英] `new_root.mainloop()` doesn't make main window unresponsive

查看:38
本文介绍了`new_root.mainloop()` 不会使主窗口无响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个 tkinter 脚本:

Let's say that I have this tkinter script:

import tkinter as tk

def callback():
   new_root = tk.Tk()
   new_root.mainloop()
   print("Done")

root = tk.Tk()

button = tk.Button(root, text="Click me", command=callback)
button.pack()

root.mainloop() 

根据我对 tkinter 的理解,当我按下按钮时,应该会创建一个新窗口和 tcl 解释器.在运行 callback 时,主窗口 (root) 不应更新,因此应无响应.new_root.mainloop() 是一个 while True 循环,它一直运行到第二个窗口关闭.因此,当我按下按钮时,它应该创建一个新窗口,在其上调用 .mainloop() ,这应该会使主窗口无响应.问题是这不会发生.即使代码执行卡在 new_root.mainloop() 中,主窗口也能响应.

From my understanding of tkinter, when I press the button, a new window and tcl interpreter should be created. While running callback, the main window (root) shouldn't be updated so it should be unresponsive. new_root.mainloop() is a while True loop that runs until the second window is closed. Therefore, when I press the button it should create a new window, call .mainloop() on it and that should make the main window unresponsive. The problem is that that doesn't happen. The main window is responsive even though code execution is stuck inside new_root.mainloop().

同时关闭第二个窗口不会打印 Done",直到其余 tkinter 窗口关闭.为什么会这样?

Also closing the second window doesn't print "Done" until the rest of the tkinter windows are closed. Why does that happen?

我查看了 tkinter_tkinter 的源代码,但我找不到任何有用的东西.我有 Python 3.7.9,tcl 8.6

I looked at the source code for tkinter and _tkinter but I couldn't find anything useful. I have Python 3.7.9, tcl 8.6

推荐答案

虽然你正在运行一个附属事件循环(真的不要那样做!)它仍然与外部循环共享相同的事件处理程序注册表,所以传入的事件在内部循环中处理,就像在外部循环中一样.(有一段常见的低级事件处理代码可以深入操作系统以有效地进行事件处理.该代码,即通知程序,是很少人应该接触的东西;这很棘手因为它合并了一些非常奇怪和完全不同的事件源,同时还解决了一些平台上的一堆奇怪的错误.)一旦 所有 窗口被删除,event_loop 方法就会返回.它从字面上调用具有适当标志的低级事件处理引擎(API 调用是 Tcl_DoOneEvent()),并在 while 循环中执行此操作(直到现有窗口的数量降至 1 以下;即 正是它在等待什么).这就是为什么您可能不应该指望它终止并且绝对不应该将它嵌套在 GUI 回调中.

Though you're running a subsidiary event loop (really don't do that!) it still shares the same registry of event handlers as the outer loop, so events coming in are handled in the inner loop just as in the outer one. (There's a common piece of low-level event handling code that reaches deep into the OS to do the event processing efficiently. That code, the notifier, is stuff that very few people should ever touch; it's tricky because it merges some really weird and disparate event sources while also working around a bunch of strange bugs on some platforms.) The event_loop method returns once all windows are deleted. It literally calls the low level event processing engine (the API call is Tcl_DoOneEvent()) with appropriate flags, and does that in a while loop (until the number of existing windows drops below 1; that's exactly what it is waiting for). This is why you probably shouldn't count on it terminating and absolutely shouldn't nest it in a GUI callback.

这篇关于`new_root.mainloop()` 不会使主窗口无响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆