0

我有一个用于训练神经网络的工作代码。现在我想创建一个 TkInter gui,以便能够即时更改参数。我想它就像一个遥控器。但我正在努力获得响应式界面。一个 epoch 的训练将需要几分钟,而我无法拦截。

我见过很多使用 .after() 方法来更新 gui 上的时钟的例子,这很好,因为更新不需要几分钟。当回调需要几分钟时,我无法让它工作。

我用最少的代码重新创建了我的问题:

from time import sleep
import tkinter as tk

def trainEpoch(i):
    print ("Training", i)
    sleep(1) #in reality more like sleep(300)

def clickBtn():
    print ("Button pressed")

root = tk.Tk()
btn = tk.Button(root, text="Click Me", command=clickBtn)
btn.grid(column=0, row=0)
for i in range (5):
    trainEpoch(i)
print ("finished" )
root.mainloop()

此代码首先“训练”网络,然后创建一个响应式 TkInter 窗口(我完全理解)。为了清楚起见,我希望有以下行为:我希望 gui 在培训开始之前打开,并且在培训进行时可以点击。我不在乎它后来是否被破坏。

我需要线程来解决这种问题吗?

最好的问候,狮子座

4

1 回答 1

1

您不能在与 tkinter 相同的线程中使用睡眠。由于 tkinter 是单线程的,您将阻止主循环执行任何操作,直到睡眠完成。

这是一个after()用于在不阻塞 tkinter 应用程序的情况下执行相同任务的示例。

import tkinter as tk


def train_epoch(i):
    if i <= 5:
        print("Training", i)
        i += 1
        root.after(2000, lambda i=i: train_epoch(i))
    else:
        print("finished")


def click_btn():
    print("Button pressed")


root = tk.Tk()
tk.Button(root, text="Click Me", command=click_btn).grid(column=0, row=0)
train_epoch(1)
root.mainloop()

结果:

在此处输入图像描述

如果您需要使用线程,您可以与 tkinter 和线程函数之间的全局命名空间中的变量进行交互。

看这个例子:

import tkinter as tk
import threading
import time


def train_epoch():
    global some_var
    while some_var <= 5:
        print(some_var)
        time.sleep(0.5)


def click_btn():
    global some_var
    some_var += 1
    print("Button pressed")


root = tk.Tk()
some_var = 0
tk.Button(root, text="Click Me", command=click_btn).pack()
thread = threading.Thread(target=train_epoch)
thread.start()

root.mainloop()
于 2019-10-07T19:18:31.247 回答