如何解决如何使用线程更新tkinter gui标签?
我是Python tkinter的新手。我已经为gui编写了以下代码。我想用从Rabbitmq收到的正文消息更新标签1。但是,一旦我的gui被填充,即使我在正文中收到不同的消息,我也面临问题,但是它无法更新。一旦我关闭了gui,那么它又有了新的价值。我希望我的gui tkinter窗口保持不变,并且在接收到正文中的新消息时应该刷新标签。
import tkinter
from PIL import ImageTk,Image as PILImage
import datetime as dt
from tkinter import *
import pika
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch,method,properties,body):
global myval
print(" [x] Received %r" % body)
window=Tk()
window.attributes('-fullscreen',True)
window.bind("<F11>",lambda event: window.attributes("-fullscreen",not window.attributes("-fullscreen")))
window.bind("<Escape>",False))
top_left=Frame(window,width=200,height=200)
top_middle=Frame(window,width=550,height=200)
top_right=Frame(window,width=250,height=200)
middle_left=Frame(window,height=300)
middle_middle=Frame(window,width=300,height=300)
middle_right=Frame(window,height=300)
bottom_left=Frame(window,width=0,height=200)
bottom_middle=Frame(window,height=200)
bottom_right=Frame(window,height=200)
top_left.grid(row=0,column=0)
top_middle.grid(row=0,column=1)
top_right.grid(row=0,column=2,sticky=E+W)
middle_left.grid(row=1,column=0,padx=100,pady=100)
middle_middle.grid(row=1,column=1)
middle_right.grid(row=1,column=2)
bottom_left.grid(row=2,column=0)
bottom_middle.grid(row=2,column=1)
bottom_right.grid(row=2,column=2)
dte=Label(top_left,text="Date: "f"{dt.datetime.now():%a,%d/ %m/ %Y}",fg="black",font=("Arial Bold ",12 ))
dte.place(x=0,y=40)
lbl=Label(top_middle,text="Welcome to Smartcards Division",fg='#3333ff',font=("Arial Bold Italic",24 ))
lbl.place(x=0,y=30)
logo_path="logo.jpg"
logo = ImageTk.PhotoImage((PILImage.open(logo_path)).resize((280,100),PILImage.ANTIALIAS))
logo_panel = Label(top_right,image = logo)
logo_panel.place(x=10,y=30)
string_clsname=str(body.decode())
lblxt=StringVar()
lbl1=Label(middle_left,textvariable=lblxt,fg='#ff6600',16))
lblxt.set("Hello "+string_clsname+" Sir")
lbl1.place(x=0,y=100)
path = "NewPicture_Copy.jpg"
image = ImageTk.PhotoImage((PILImage.open(path)).resize((250,250),PILImage.ANTIALIAS))
panel = Label(middle_middle,image = image,borderwidth=5,relief="ridge")
panel.pack()
lbl2=Label(bottom_middle,text="\u00a9"+"2020-Smartcards Division",fg='black',font=("Helvetica",8))
lbl2.place(x=0,y=0)
window.title('Image Classification')
window.mainloop()
channel.basic_consume(
queue='hello',on_message_callback=callback,auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
解决方法
在基本级别上,您需要:
- 单独的执行线程,
用于单独的任务(必须同时运行)。 - 线程彼此通信的一种方式;
同时避免比赛条件
(例如在一个线程中修改变量,
而另一个线程正在读取它。
在这里您可以例如使用互斥锁/锁,消息传递等。
import tkinter as tk
from collections import deque
from threading import Thread
from random import randint
from time import sleep
# Starting out (this is the main/gui thread).
root = tk.Tk()
label = tk.Label(root,text='Original text')
label.pack()
# Means of communication,between the gui & update threads:
messageQueue = deque()
# Create a thread,that will periodically emit text updates.
def emitText(): # The task to be called from the thread.
while(True): # Normally should check some condition here.
messageQueue.append(f'Random number: {randint(0,100)}')
sleep(1) # Simulated delay (of 1 sec) between updates.
# Create a separate thread,for the emitText task:
thread = Thread(target=emitText)
# Cheap way to avoid blocking @ program exit: run as daemon:
thread.setDaemon(True)
thread.start() # "thread" starts running independently.
# Moving on (this is still the main/gui thread).
# Periodically check for text updates,in the gui thread.
# Where 'gui thread' is the main thread,# that is running the gui event-loop.
# Should only access the gui,in the gui thread/event-loop.
def consumeText():
try: label['text'] = messageQueue.popleft()
except IndexError: pass # Ignore,if no text available.
# Reschedule call to consumeText.
root.after(ms=1000,func=consumeText)
consumeText() # Start the consumeText 'loop'.
root.mainloop() # Enter the gui event-loop.
另请参阅:
queue.Queue
“ collections.deque是
的替代实现
快速原子append()和popleft()的无界队列
不需要锁定的操作。“
collections.deque
threading.Thread
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。