如何在TopLevel窗口中调用函数后更新标签?

时间:2017-12-19 22:27:04

标签: python tkinter lambda

我试图在python中构建一个顶层窗口,其中有一个名为" text"的标签。它的textvariable被称为" v"。如您所见,在dialogBox()中有3个函数调用。我希望程序做的是标签" text"显示短语"事件一",等待一秒钟,显示短语"事件二",等待一秒钟,然后显示短语"事件三"。而不是这样做,顶层窗口打开,仅显示"事件三"。

我怀疑这是一个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()

3 个答案:

答案 0 :(得分:1)

你非常接近,但你最好的选择是使用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()电话粗暴地告诉图形用户界面,"停止您正在做的所有事情并立即为我做这件事!"这还允许您查看event1,event2,event3消息。但是after()实际上是更好,更合适的方法。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

在此处查看演示,也可以使用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()