【问题标题】:Python Tkinter, destroy toplevel after functionPython Tkinter,函数后销毁顶层
【发布时间】:2017-11-15 12:15:00
【问题描述】:

我正在使用 Tkinter 作为 GUI 使用 python 编写一些驱动器。当我的机器运行时,我想向用户显示一个顶层窗口,其中包含一些信息,这些信息应该在函数完成后自行关闭。这是我的最小示例:

from Tkinter import *
import time


def button_1():
     window = Toplevel()
     window.title("info")
     msg = Message(window, text='running...', width=200)
     msg.pack()     
     time.sleep(5.0)
     window.destroy()

master = Tk()
frame = Frame(width=500,height=300)
frame.grid()
button_one = Button(frame, text ="Button 1", command = button_1)
button_one.grid(row = 0, column = 0, sticky = W + E)
mainloop()

主要问题是,顶层窗口在 5 秒后才出现。有什么建议么? 谢谢!

【问题讨论】:

  • 我不明白你为什么认为你的代码没有达到你想要的效果?它在函数完成后关闭“自身”,或者更确切地说,它通过关闭来完成函数。

标签: python tkinter toplevel


【解决方案1】:

time.sleep(5) 在 GUI 有时间更新之前启动,这就是为什么顶层仅在 5 秒结束后出现的原因。要更正此问题,您可以在 time.sleep(5) 之前添加 window.update_idletasks() 以强制更新显示。

但是,正如 Bryan Oakley 在他的回答中指出的那样,GUI 在执行 time.sleep(5) 时被冻结。我猜你的最终目标不是执行time.sleep,而是一些耗时的操作。因此,如果您不想冻结 GUI 但不知道执行需要多长时间,您可以在单独的线程中执行您的函数,并定期使用after 检查它是否完成:

import Tkinter as tk
import time
import multiprocessing

def function():
    time.sleep(5)


def button_1():
    window = tk.Toplevel(master)
    window.title("info")
    msg = tk.Message(window, text='running...', width=200)
    msg.pack()
    thread = multiprocessing.Process(target=function)
    thread.start()
    window.after(1000, check_if_running, thread, window)


def check_if_running(thread, window):
    """Check every second if the function is finished."""
    if thread.is_alive():
        window.after(1000, check_if_running, thread, window)
    else:
        window.destroy()


master = tk.Tk()
frame = tk.Frame(width=500,height=300)
frame.grid()
button_one = tk.Button(frame, text ="Launch", command=button_1)
button_one.grid(row = 0, column = 0, sticky = "we")
master.mainloop()

【讨论】:

    【解决方案2】:

    一般的经验法则是,您永远不应该在运行 GUI 的线程中调用 sleep。原因是 sleep 完全按照它所说的那样做,它使整个程序进入睡眠状态。这意味着它无法刷新窗口或对任何事件做出反应。

    如果你想在一段时间后做某事,正确的做法是使用after。例如,这将在五秒后销毁窗口:

    window.after(5000, window.destroy)
    

    【讨论】:

    • 感谢您的回答。这只是一个最小的例子,我不会在我的真实程序中调用睡眠。我调用了一个更复杂的函数,它在没有确定的时间段后结束。
    猜你喜欢
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多