用于切换显示图像的 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 函数的主要内容,如果未能解决你的问题,请参考以下文章

用于在画布上显示图像的简单 websocket

openCV—Python——载入显示和保存图像

Python 绘图时用到的各种函数

UITableViewCell 图像在选择之前不显示

启动图像不适用于资产目录

无法用kivy显示图像