我正在尝试在python中构建一个顶层窗口,其中有一个名为“text”的标签。它的textvariable称为“v”。如您所见,在dialogBox()中有3个函数调用。我希望程序做的是让标签“text”显示短语“Event one”,等待一秒钟,显示短语“Event 2”,等待一秒钟,然后显示短语“Event 3”。而不是这样做,顶层窗口打开,仅显示“事件三”。
我怀疑这是一个lambda问题,但我仍然不确定如何在Tkinter中使用它。
from tkinter import*
import time
def event1():
v.set("Event one")
def event2():
v.set("Event two")
def event3():
v.set("Event three")
def dialogueBox():
top = Toplevel()
global v
top.minsize(400,0)
top.maxsize(700,300)
top.title("Toplevel test")
v = StringVar()
text = Label(top,textvariable = v)
text.pack()
event1()
time.sleep(1)
event2()
time.sleep(1)
event3()
root = Tk()
email = StringVar()
password = StringVar()
title = Label(root,text="Root window",font = 11)
title.pack()
label1 = Label(root,text = "Username")
label1.pack()
field1 = Entry(root,textvariable = email)
field1.pack()
label2 = Label(root,text = "Password")
label2.pack()
field2 = Entry(root,show = "*",textvariable = password)
field2.pack()
button = Button(root,text = "Get data",command = dialogueBox)
button.pack()
root.mainloop()
你非常接近,但你最好的选择是使用after()
方法。
这是您修改后的代码,添加了评论:
from tkinter import*
import time
def event1():
v.set("Event one")
root.after(1000, event2) # NEW
def event2():
v.set("Event two")
root.after(1000, event3) # NEW
def event3():
v.set("Event three")
def dialogueBox():
top = Toplevel()
global v
top.minsize(400,0)
top.maxsize(700,300)
top.title("Toplevel test")
v = StringVar()
text = Label(top,textvariable = v)
text.pack()
event1()
#time.sleep(1)
#event2()
#time.sleep(1)
#event3()
root = Tk()
email = StringVar()
password = StringVar()
title = Label(root,text="Root window",font = 11)
title.pack()
label1 = Label(root,text = "Username")
label1.pack()
field1 = Entry(root,textvariable = email)
field1.pack()
label2 = Label(root,text = "Password")
label2.pack()
field2 = Entry(root,show = "*",textvariable = password)
field2.pack()
button = Button(root,text = "Get data",command = dialogueBox)
button.pack()
root.mainloop()
唯一真正的变化是使用来自after
的event1()
方法来调用event2()
,并从event2()
调用event3()
。通过这些after()
调用,你的dialogueBox()
中的最后4行消失了。
怎么了? Tkinter是一个GUI,事件驱动的系统。它不喜欢坐在那里等待任何事情。在您睡觉时,资源被浪费,GUI无法刷新和更新。通过使用after()
方法,GUI可以继续做它最擅长的事情:等待事件和输入。 after()
方法安排事件稍后发生。到那时,事件就会得到处理。 after()
的第一个arg是以ms(毫秒)为单位的时间延迟。第二个arg是一个函数名,在指定的时间延迟后调用。
现在,我说after()
是你最好的选择,但还有另一种方法可以做到这一点,尽管不那么“礼貌”。您可以将.update()
方法调用添加到dialogueBox()
,如下所示:
def dialogueBox():
top = Toplevel()
global v
top.minsize(400,0)
top.maxsize(700,300)
top.title("Toplevel test")
v = StringVar()
text = Label(top,textvariable = v)
text.pack()
event1()
text.update() # NEW -- RUDE!
time.sleep(1)
event2()
text.update() # NEW -- RUDE!
time.sleep(1)
event3()
.update()
粗鲁地告诉GUI,“停止你正在做的一切,现在就为我做这件事!”这还允许您查看event1,event2,event3消息。但after()
真的是更好,更好的方法来做到这一点。
在event1()
使用root.after(1000, event2)
,它将在event2
后一秒运行event1
你必须从sleep()
删除event2()
和函数event3()
dialog_box()
import tkinter as tk
# --- functions ---
def event1():
v.set("Event one")
root.after(1000, event2) # run event2 after 1000ms (1s)
def event2():
v.set("Event two")
root.after(1000, event3) # run event3 after 1000ms (1s)
def event3():
v.set("Event three")
root.after(1000, close_it) # run close_it after 1000ms (1s)
def close_it():
top.destroy() # close TopLevel window
def dialogue_box():
global v
global top
top = tk.Toplevel()
top.minsize(400,0)
top.maxsize(700,300)
top.title("Toplevel test")
v = tk.StringVar()
text = tk.Label(top, textvariable=v)
text.pack()
event1() # run event1 at once
# --- main ---
root = tk.Tk()
email = tk.StringVar()
password = tk.StringVar()
title = tk.Label(root, text="Root window", font=11)
title.pack()
label1 = tk.Label(root, text="Username")
label1.pack()
field1 = tk.Entry(root, textvariable=email)
field1.pack()
label2 = tk.Label(root, text="Password")
label2.pack()
field2 = tk.Entry(root, show="*", textvariable=password)
field2.pack()
button = tk.Button(root, text="Get data", command=dialogue_box)
button.pack()
root.mainloop()
看看此后的演示,还有itertools“show off”
from tkinter import *
import time
from itertools import cycle
label_iter = cycle(('Event One', 'Event Two', 'Event Three'))
def change_label():
v.set(next(label_iter))
root.after(1000, change_label)
def dialogueBox():
top = Toplevel()
global v
top.minsize(400,0)
top.maxsize(700,300)
top.title("Toplevel test")
v = StringVar()
text = Label(top,textvariable = v)
text.pack()
root.after(1000, change_label)
root = Tk()
email = StringVar()
password = StringVar()
title = Label(root,text="Root window",font = 11)
title.pack()
label1 = Label(root,text = "Username")
label1.pack()
field1 = Entry(root,textvariable = email)
field1.pack()
label2 = Label(root,text = "Password")
label2.pack()
field2 = Entry(root,show = "*",textvariable = password)
field2.pack()
button = Button(root,text = "Get data",command = dialogueBox)
button.pack()
root.mainloop()