Python Tkinter睡眠/未按预期工作后

Python Tkinter睡眠/未按预期工作后,python,tkinter,Python,Tkinter,因此,我想做的是,脚本B中有一个函数,它将在脚本a中调用。因此,该函数将通过打印在控制台上显示一些输出,但我想的是,输出也应该显示在小部件上,脚本a是我所有GUI操作发生的地方 所以我所做的是,我把一个函数X作为参数传递给脚本B中的函数Y,因此,当输出被打印到函数Y中时,我只是将其引用到一个变量中,并将该变量传递给脚本a的函数X。。。我把它当作论点。因此,该函数只是将输出插入文本小部件 但问题是,函数Y是在单击按钮后调用的,由于某种原因,按钮会冻结一段时间,然后立即显示最终输出。但这不是我想要的

因此,我想做的是,脚本B中有一个函数,它将在脚本a中调用。因此,该函数将通过打印在控制台上显示一些输出,但我想的是,输出也应该显示在小部件上,脚本a是我所有GUI操作发生的地方

所以我所做的是,我把一个函数X作为参数传递给脚本B中的函数Y,因此,当输出被打印到函数Y中时,我只是将其引用到一个变量中,并将该变量传递给脚本a的函数X。。。我把它当作论点。因此,该函数只是将输出插入文本小部件

但问题是,函数Y是在单击按钮后调用的,由于某种原因,按钮会冻结一段时间,然后立即显示最终输出。但这不是我想要的。我希望在控制台中显示输出的同时,以这种方式一个接一个地显示输出。但是,当在命令参数中传递的整个函数完成运行时,按钮小部件似乎会恢复

为了解决这个问题,我尝试使用sleep和after函数,但它们似乎对我帮助不大。因此,我试着用一种更简单的方式来重现我的问题,我试着通过睡眠和休息来解决问题,但它们似乎都不适合我

下面是代码,虽然它们与我的问题不完全匹配,但我希望它们能够更清楚地解释我的问题

假设我们有两个脚本A和B

在脚本A中-

from time import sleep

# will output a number every 1 second on the console
def Show(number, Function):    
    while(number < 5):
        sleep(1)            # Wait specified time
        number += 1         # Some random operation, here incrementing the number by 1

        print(number)       # On console
        Function(number)    # On widget
所以我的观点是,我想在任何小部件上显示数字(在我真正的问题中,它是一个文本小部件),与它实际发生的时间相同,即在控制台上显示

更新:这不是实际问题,只是我实际问题的简化版本。所以,不要认为我试图使这段代码过于复杂。当我使用经过训练的NN训练分类器时,每次迭代都会在控制台上打印输出。因此,我想要实现的是,在正在进行的循环过程中,同时在文本小部件上打印输出。

更新2:它终于按我希望的那样工作了。答案是使用Mike描述的线程:D

sleep()
tkinter
不能相处。而
时也没有。sleep和while的问题是,它们会阻塞主循环直到它们完成,因此在它们完成之前,GUI中不会有任何更新。也就是说,我认为您正在使这段代码变得更加复杂。您有两个函数,可以简单地在一个函数中完成,您将函数传递给函数。比需要复杂得多

每次调用print时,您也会打包一个新标签。请尽量按照PEP8标准命名函数。标准函数和变量的所有带下划线的\u low\u

方法
after()
专门设计用于处理tkinter中的定时事件,主要用于替换GUI中的
sleep

这是您的代码简化版,使用
after()

将tkinter作为tk导入
def delay_和_print():
全局数
如果数字小于5:
打印(数字)
label.config(text=number)
数字+=1
root.after(1000,延迟和打印)
root=tk.tk()
数字=0
按钮(root,text='Start',command=delay\u和\u print).pack()
label=tk.label(根,文本=“”)
label.pack()
root.mainloop()
下面是一个使用线程的示例:

import tkinter as tk
import threading
from time import sleep


def delay_and_print():
    global number
    if number < 100:
        print(number)
        label.config(text=number)
        number += 1
        sleep(2)
        delay_and_print()


def start_thread():
    thread = threading.Thread(target=delay_and_print)
    thread.start()


def do_something():
    print('Something')


root = tk.Tk()
number = 0
tk.Button(root, text='Start', command=start_thread).pack()
tk.Button(root, text='some other button to test if app is responsive while loop is going!', command=do_something).pack()
label = tk.Label(root, text='')
label.pack()
root.mainloop()
将tkinter作为tk导入
导入线程
从时间上导入睡眠
def delay_和_print():
全局数
如果数字小于100:
打印(数字)
label.config(text=number)
数字+=1
睡眠(2)
延迟打印和打印()
def start_thread():
线程=线程。线程(目标=延迟和打印)
thread.start()
定义做某事():
打印(‘某物’)
root=tk.tk()
数字=0
按钮(root,text='Start',command=Start\u thread).pack()
tk.Button(root,text='someotherbutton,用于测试应用程序在循环进行时是否响应!',command=do\u something.pack()
label=tk.label(根,文本=“”)
label.pack()
root.mainloop()

不要将
睡眠
与tkinter一起使用。如果需要的话,可以在
之后使用
,或者在线程中使用sleep。不,我必须使用循环。记得我说过我用的是我的问题的一个非常简化的版本。因为在我的问题中,我有一个脚本,它使用经过训练的神经网络来训练分类器,并且在每次迭代之后,在这个脚本中,结果都会打印在控制台上。所以我想把结果打印在一个文本小部件上。是的,我知道我在示例中使用了一个标签,但它只是为了快速演示我的问题。显然我不会这么做:)如果必须使用循环,那么需要在()之后合并
after()
,或者如果必须使用某种while语句或某个进程密集型循环,那么就需要使用线程。另外,这并不明显,因为很多帖子都比lol差得多。谢谢,线程示例真的很有帮助。我想我能弄明白。一旦我的实际代码按预期工作,就会更新。
import tkinter as tk


def delay_and_print():
    global number
    if number < 5:
        print(number)
        label.config(text=number)
        number += 1
        root.after(1000, delay_and_print)


root = tk.Tk()
number = 0
tk.Button(root, text='Start', command=delay_and_print).pack()
label = tk.Label(root, text='')
label.pack()
root.mainloop()
import tkinter as tk
import threading
from time import sleep


def delay_and_print():
    global number
    if number < 100:
        print(number)
        label.config(text=number)
        number += 1
        sleep(2)
        delay_and_print()


def start_thread():
    thread = threading.Thread(target=delay_and_print)
    thread.start()


def do_something():
    print('Something')


root = tk.Tk()
number = 0
tk.Button(root, text='Start', command=start_thread).pack()
tk.Button(root, text='some other button to test if app is responsive while loop is going!', command=do_something).pack()
label = tk.Label(root, text='')
label.pack()
root.mainloop()