我正在为数学应用程序设计GUI。由于计算通常需要一些时间,因此我想将临时结果输出到新的tkinter窗口中的文本字段,该窗口将在启动计算时打开。
我已经打开了一个新窗口并进行了计算,但是结果将在计算结束后打印出来。
我准备了一个简短的代码片段,展示了我的方法:
import tkinter as tk
import threading
import time as t
class CalculationDialog(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
self.root = tk.Tk()
self.textField = tk.Text(self.root)
self.bCloseDialog = tk.Button(self.root, text="Close", state=tk.DISABLED, command=self.root.destroy)
self.textField.grid(row=1, column=0)
self.bCloseDialog.grid(row=2, column=0)
def callback(self):
self.root.quit()
def run(self):
self.root.protocol("WM_DELETE_WINDOW", self.callback)
self.root.mainloop()
def calculate():
app = CalculationDialog()
# Conduct calculation and output to textfield of app
func(app.textField,0)
def func(output,input):
for i in range(input,100):
result = i**2
output.insert(tk.END,str(result)+"\n")
t.sleep(0.1)
main = tk.Tk()
buttonCalc = tk.Button(main,text="Calculate",command=calculate)
buttonCalc.pack(side=tk.TOP)
main.mainloop()
有人建议我缺少什么吗?
有时我会出错,说CalculationDialog
没有属性root
。
但是,并非总是会出现此错误。
欢呼
答案 0 :(得分:2)
以@HenryYik答案为基础,该答案显示了正确的方法,但是在尝试连续单击RuntimeError
多次时抛出calculate
:
RuntimeError: threads can only be started once
以下示例弹出一个显示中间结果的tk.Toplevel
,并允许重复单击calculate
按钮。它会产生尽可能多的顶级窗口,并显示尽可能多的中间结果。
每个新线程均由唯一编号标识;线程完成后,将输出控制台输出。
计算完成后,close
上的Toplevel
按钮将变为活动状态。
import tkinter as tk
import threading
import time
def func(thread_number=[0]): # note: the mutable default arg creates a closure that keeps track of the thread number.
global thr
local_thread_number = thread_number[0]
thread_number[0] += 1
def close():
thr = None
top.destroy()
top = tk.Toplevel(root)
text_field = tk.Text(top)
close_btn = tk.Button(top, text="Close", state=tk.DISABLED, command=close)
text_field.grid(row=1, column=0)
close_btn.grid(row=2, column=0)
for i in range(1, 100):
result = i**2
if i % 10 == 0:
text_field.insert(tk.END, str(result)+"\n")
time.sleep(0.05)
print(f'thread {local_thread_number} done!')
close_btn.config(state=tk.NORMAL)
def get_and_start_thread():
global thr
thr = threading.Thread(target=func)
thr.start()
root = tk.Tk()
thr = None
button_calc = tk.Button(root,text="Calculate",command=get_and_start_thread)
button_calc.pack(side=tk.TOP)
root.mainloop()
答案 1 :(得分:1)
您需要线程执行计算的函数func
。现在,您正在线程化另一个Tk实例和一些小部件的创建。
可能是这样的:
import tkinter as tk
import threading
import time as t
def func():
frame = tk.Frame(root)
frame.pack()
textField = tk.Text(frame)
bCloseDialog = tk.Button(frame, text="Close", state=tk.DISABLED, command=root.destroy)
textField.grid(row=1, column=0)
bCloseDialog.grid(row=2, column=0)
for i in range(1,100):
result = i**2
textField.insert(tk.END,str(result)+"\n")
t.sleep(0.1)
root = tk.Tk()
thr = threading.Thread(target=func)
buttonCalc = tk.Button(root,text="Calculate",command=thr.start)
buttonCalc.pack(side=tk.TOP)
root.mainloop()