簡體   English   中英

如何用線程更新 tkinter gui 標簽?

[英]how to update tkinter gui label with a thread?

我是 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>", lambda event: window.attributes("-fullscreen",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,width=200,height=300)
    middle_middle=Frame(window,width=300,height=300)
    middle_right=Frame(window,width=300,height=300)
    bottom_left=Frame(window,width=0,height=200)
    bottom_middle=Frame(window,width=300,height=200)
    bottom_right=Frame(window,width=300,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',font=("Arial Bold Italic",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.

也可以看看:

隊列.隊列
“collections.deque 是另一種實現
具有快速原子 append() 和 popleft() 的無界隊列
不需要鎖定的操作。”
集合.deque
線程.Thread

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM