Python Tkinter Gui有时会因运行更多线程而冻结
目前我有3个函数作为线程运行,其中两个只有在按下按钮时才运行。现在如果我把代码放大Python Tkinter Gui有时会因运行更多线程而冻结,python,python-3.x,tkinter,python-multithreading,Python,Python 3.x,Tkinter,Python Multithreading,目前我有3个函数作为线程运行,其中两个只有在按下按钮时才运行。现在如果我把代码放大 添加更多线程和函数 创建更多标签和按钮 增加函数的大小 Tkinter窗口将冻结并“滞后”。我已经从在线资源中实现了线程,但不确定是否以最有效的方式实现了GUI 下面是如何做一些类似于我的文章的事情,在你询问一个例子后,我在评论中提到了你 import tkinter as tk import tkinter.font import threading import time def funct1(): i
下面是如何做一些类似于我的文章的事情,在你询问一个例子后,我在评论中提到了你
import tkinter as tk
import tkinter.font
import threading
import time
def funct1():
i = 0
while True:
i+=1
time.sleep(5)
def funct2():
i = 0
while True:
i+=2
time.sleep(5)
label2.config(text=i)
def funct3():
i = 0
while True:
time.sleep(5)
i+=2
label3.config(text=i)
thread1 = threading.Thread(target=funct1)
thread2 = threading.Thread(target=funct2)
thread3 = threading.Thread(target=funct3)
thread1.start()
mainwindow = tk.Tk()
HEIGHT = 700
WIDTH = 800
canvas = tk.Canvas(mainwindow, height = HEIGHT, width = WIDTH)
canvas.pack()
frame = tk.Frame(mainwindow, bg='#08030D') #inside box
frame.place(relx=0, rely=0.1, relwidth = 0.95, relheight = 0.6)
start2=tk.Button(frame, text = "to Start 2", bg='#292230',fg='white',command = thread2.start)
start2.place(relx=0, rely=0.06, relwidth = 0.2, relheight = 0.05)
label2 = tk.Label(frame,text = "state", bg='gray')
label2.place(relx=0.45, rely=0.12, relwidth = 0.07, relheight = 0.05)
start3=tk.Button(frame, text = "to Start 3", bg='#292230',fg='white',command = thread3.start)
start3.place(relx=0, rely=0.12, relwidth = 0.2, relheight = 0.05)
label3 = tk.Label(frame,text = "state ", bg='gray')
label3.place(relx=0.45, rely=0.18, relwidth = 0.07, relheight = 0.05)
mainwindow.mainloop()
为什么您希望标签或按钮定期显示?换言之,你的代码的哪一部分应该实现这一点?很抱歉造成混淆,我编辑了标题。我的意思是当添加更多线程时,Tkinter会冻结。这段代码中没有添加任何标签,但当我实际添加标签时,它也会随着按钮一起冻结。我没有看到可能冻结或变得无响应的元素。我能看到的唯一错误是
RuntimeError:通过多次单击按钮,线程只能启动一次。这个GUI还有其他组件没有提到吗?您的完整代码是否从线程发出了与Tkinter相关的调用?这是不允许的,你必须从主线程开始做所有的事情。我的实际代码只是这个版本的一个放大版本,有更多的标签和按钮来启动更多的线程。同样在我的实际代码中,threads函数正在执行更多的任务,比如从thread函数中重命名标签。
import queue
import sys
import tkinter as tk
import tkinter.font
import threading
import time
WIDTH, HEIGHT = 800, 700
LABEL2_MSGID, LABEL3_MSGID = 2, 3
def funct1():
i = 0
while True:
i += 1
time.sleep(5)
def funct2():
i = 0
while True:
i += 2
time.sleep(5)
msg_queue.put((LABEL2_MSGID, i)) # Put a message in queue.
def funct3():
i = 0
while True:
time.sleep(5)
i += 2
msg_queue.put((LABEL3_MSGID, i)) # Put a message in queue.
def process_incoming():
""" Handle any messages currently in the queue. """
while msg_queue.qsize():
try:
msg = msg_queue.get_nowait()
# Check contents of message and do whatever is needed to the GUI.
msg_id, text = msg
if msg_id == LABEL2_MSGID:
label2.config(text=text)
elif msg_id == LABEL3_MSGID:
label3.config(text=text)
else:
pass # Unknown identifier.
except queue.Empty:
# Shouldn't happen, but if it does, just ignore it.
pass
def periodic_call():
""" Check every 200 ms if there is something new in the queue. """
mainwindow.after(200, periodic_call)
process_incoming()
if not running:
# This is the brutal stop of the system. You may want to do some
# cleanup before actually shutting it down.
sys.exit(1)
thread1 = threading.Thread(target=funct1, daemon=True)
thread2 = threading.Thread(target=funct2, daemon=True)
thread3 = threading.Thread(target=funct3, daemon=True)
mainwindow = tk.Tk()
msg_queue = queue.Queue() # For inter-thread communications.
canvas = tk.Canvas(mainwindow, height=HEIGHT, width=WIDTH)
canvas.pack()
frame = tk.Frame(mainwindow, bg='#08030D') # Inside box.
frame.place(relx=0, rely=0.1, relwidth=0.95, relheight=0.6)
start2 = tk.Button(frame, text="to Start 2", bg='#292230', fg='white', command=thread2.start)
start2.place(relx=0, rely=0.06, relwidth=0.2, relheight=0.05)
label2 = tk.Label(frame, text="state", bg='gray')
label2.place(relx=0.45, rely=0.12, relwidth=0.07, relheight=0.05)
start3 = tk.Button(frame, text="to Start 3", bg='#292230', fg='white', command=thread3.start)
start3.place(relx=0, rely=0.12, relwidth=0.2, relheight=0.05)
label3 = tk.Label(frame, text="state ", bg='gray')
label3.place(relx=0.45, rely=0.18, relwidth=0.07, relheight=0.05)
running = True
thread1.start() # Start background thread that doesn't affect the GUI.
periodic_call() # Start checking and processing messages from other threads.
mainwindow.mainloop()