用于切换显示图像的 Python 函数
Posted
技术标签:
【中文标题】用于切换显示图像的 Python 函数【英文标题】:Python function to switch image displayed 【发布时间】:2018-06-29 04:49:26 【问题描述】:我有一个在实时数据上运行的 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
【问题讨论】:
假设您的图像位于标签中,只需更新标签以使用带有label_instance.config(image=new_image)
的新图像。如果您想要一个具体的答案,您必须向我们展示minimal reproducible example。
我已经更新了这个问题,希望它更清楚!
【参考方案1】:
在 GUI 代码中使用其他代码,然后在其他代码中使用 GUI 代码会更容易 - 它被称为“GUI 包装器”。
GUI 的问题是它必须运行mainloop
,它一直有效(直到你关闭窗口)并且你不能运行其他循环。您可以使用thread
同时运行其他循环,但tkinter
不是线程安全的,更改其他线程内的小部件可能会产生问题
您可以使用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()
【讨论】:
感谢您的帮助!不幸的是,在分类器脚本需要持续运行时,这对我不起作用。我使用线程和队列来代替它,将在上面发布【参考方案2】:这就是我得到它的工作!
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()
【讨论】:
以上是关于用于切换显示图像的 Python 函数的主要内容,如果未能解决你的问题,请参考以下文章