Базовая идея
Я использую протокол MQTT
(брокер: реализация Mosquitto и Client через Eclipse Paho) для получения периодических данных.Я хочу показать изображение после получения определенного числа х в данных и изменить изображение, если я получу другое число у.
С точки зрения непрофессионала, я получаю некоторые данные в формате JSON с интервалом в 10 секунд и хочу отобразить или изменить изображение в соответствии с полученными данными.
Код
from tkinter import *
from PIL import ImageTk, Image
import datetime
import paho.mqtt.client as mqtt
import json
root = Tk()
canvas = Canvas(root, width=500, height=500)
canvas.pack()
def drawImage(payload):
pic = payload['camera']
canvas.delete("all")
img = ImageTk.PhotoImage(Image.open(str(pic) + ".png"))
canvas.create_image(20, 20, anchor=NW, image=img)
root.mainloop()
def on_connect(client, userdata, flags, rc):
print("Connected with result code " + str(rc))
client.subscribe("home/camera")
def on_message(client, userdata, msg):
t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
payload = json.loads(msg.payload)
print("Data received at: {0} || Topic: {1} || Message: {2}".format(t, msg.topic, str(msg.payload)))
drawImage(payload)
client = mqtt.Client(client_id="cameratester")
client.on_connect = on_connect
client.on_message = on_message
client.connect("127.0.0.1", 1883, 60)
client.loop_forever()
Краткое объяснение того, как работает код:
При получении новых данных on_message
вызывается, который в свою очередь вызывает функцию drawImage
, которая рисует изображение.
Проблема
Изображение отображается после получения первого сообщения, но кажется, что код зависает там.Мой клиент не принимает другие входящие сообщения.После закрытия окна изображения строка кода print("Data received at: {0} || Topic: {1} || Message: {2}".format(t, msg.topic, str(msg.payload)))
снова начинает выполняться, но изображение не отображается.
Некоторые исследования
После прохождения платоры по How to change image in Tkinter
вопросам на StackOverflow, например this и this ,стало очевидно, что root.mainloop()
является блокирующим вызовом, и поток не будет выполняться дальше, пока окно не будет закрыто.Было упомянуто, что если я хочу изменить изображение, мне нужно назначить обратный вызов для события, например нажать кнопку и сделать panel.configure(image=img2)
, чтобы изменить изображение.
Но так как мой дизайн неУ меня есть кнопки, я не могу следовать методологии обратного вызова кнопок.
Итак, как я могу инициировать изменение изображения в окне Tkinter при получении данных от издателя (MQTT)?
Если я не использую Tkinter, какой-нибудь другой пакет лучше подходит для этого требования?Или я что-то упустил очень простой.
Пожалуйста, совет.