我有一个运行在实时数据上的python 3脚本,它调用分类函数,返回0或1.我想要的是一个窗口根据分类器返回的内容显示图像。
以下是我的分类器脚本的简单版本:
from random import randint
import time
def classifier():
time.sleep(4)
return randint(0,1)
while True:
classification=classifier()
这是我到目前为止为视觉效果提出的脚本:
import tkinter as tk
from PIL import Image,ImageTk
root = tk.Tk()
img1=ImageTk.PhotoImage(Image.open('left.jpg'))
img2=ImageTk.PhotoImage(Image.open('right.jpg'))
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master, bg="")
self.pack()
self.create_widgets()
def create_widgets(self):
self.arrow=tk.Label(self, image=img1)
self.arrow.image=img1 #must keep this otherwise will be discarded
self.arrow.pack()
self.pack()
def updateImg(img):
app.arrow.config(image=img)
app.arrow.image=img
app.arrow.pack()
app = Application(master=root)
app.mainloop()
我的问题是连接两个脚本,以便分类值确定实时显示的图像。从理论上讲,我希望能够从分类器脚本
中调用updateImg答案 0 :(得分:0)
当您在GUI代码中使用其他代码,然后在其他代码中使用GUI代码时更容易 - 它被称为“GUI包装器”。
GUI的问题在于它必须运行mainloop
,它始终有效(直到关闭窗口)并且您无法运行其他循环。您可以使用thread
同时运行其他循环,但tkinter
不是线程安全的,并且更改其他thead中的小部件可能会产生问题
您可以使用root.after
定期运行一些代码,然后两个循环没有问题,因为mainloop
会为您运行它。
import tkinter as tk
from PIL import Image,ImageTk
from random import randint, randrange
import time
# --- classes ---
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master, bg="")
self.pack()
self.create_widgets()
def create_widgets(self):
# create empty label
self.arrow = tk.Label(self)
self.arrow.pack()
def update_image(self, img):
# set image in label
self.arrow.config(image=img)
# because image is assigned to global list `imgs`
# so this command may not be needed
self.arrow.image = img
# --- functions ---
def classifier():
# return randint(0, len(imgs)-1) # with -1
return randrange(0, len(imgs)) # without -1
def update_loop():
# run your classifier from other file
selected = classifier()
# get image from list
img = imgs[selected]
# update image in window
app.update_image(img)
# run it again after 4000ms
root.after(4000, update_loop)
# --- main ---
root = tk.Tk()
# list with images (create after creating `root`)
imgs = [
ImageTk.PhotoImage(Image.open('left.jpg')),
ImageTk.PhotoImage(Image.open('right.jpg')),
]
# creacte app
app = Application(root)
# run it first time
update_loop()
# start "engine"
app.mainloop()
答案 1 :(得分:0)
这就是我使用它的原因!
import tkinter as tk
from PIL import Image,ImageTk
from threading import Thread
from queue import Queue
import time
from random import randint
q=Queue() #both threads can access the queue
def GUIthread(): #all GUI actions take place in this thread
root = tk.Tk()
img1=ImageTk.PhotoImage(Image.open('left.jpg'))
img2=ImageTk.PhotoImage(Image.open('right.jpg'))
def updateImage(classification):
if classification ==1:
root.arrow.config(image=img2)
root.arrow.image=img2
root.arrow.pack()
else:
root.arrow.config(image=img1)
root.arrow.image=img1
root.arrow.pack()
def checkQueue():
classification=q.get()
updateImage(classification)
q.task_done()
root.after(1000,checkQueue)
root.arrow=tk.Label(image=img1)
root.arrow.image=img1
root.arrow.pack()
root.after(1, checkQueue)
root.mainloop()
def classifier(): #mimics a thread that needs to be run continuously (collecting live data)
while 1:
time.sleep(2)
q.put(randint(0,1))
t=Thread(target=GUIthread)
t.start()
classifier()