如何在按下GPIO按钮后使用Tkinter重新加载图片?

时间:2016-06-21 21:58:26

标签: python python-3.x tkinter raspberry-pi gpio

我有以下脚本基于另一个Stackoverflow问题的解决方案。我有一个带有图片的tkinter GUI,当有一个新图片时应该刷新。

class App(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.start()

    def callback(self):
        self.root.quit()

    def run(self):
        self.root = Tk()
        self.root.geometry("{0}x{1}+0+0".format(800,800))

        files = sorted(os.listdir(os.getcwd()),key=os.path.getmtime)

        Label(self.root,image = ImageTk.PhotoImage(Image.open(files[-1]).resize((300, 200)))).grid(row = 1, column = 0)

        Label(self.root, text=files[-1]).grid(row=0, column=0)
        self.root.mainloop()

    def update(self):

        files = sorted(os.listdir(os.getcwd()),key=os.path.getmtime)

        img1 = self.ImageTk.PhotoImage(self.Image.open(files[-1]).resize((300, 200)))
        Label(self.root,image = img1).grid(row = 1, column = 0)

        Label(self.root, text=files[-1]).grid(row=0, column=0)

        self.root.update()

app = App()        
app.update()

我收到此错误:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/PIL/ImageTk.py", line 176, in paste
    tk.call("PyImagingPhoto", self.__photo, block.id)
_tkinter.TclError: invalid command name "PyImagingPhoto"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./mainloop.py", line 98, in <module>
    app.update()
  File "./mainloop.py", line 79, in update
    img1 = ImageTk.PhotoImage(Image.open(files[-1]).resize((300, 200)))
  File "/usr/lib/python3/dist-packages/PIL/ImageTk.py", line 115, in __init__
    self.paste(image)
  File "/usr/lib/python3/dist-packages/PIL/ImageTk.py", line 182, in paste
    _imagingtk.tkinit(tk.interpaddr(), 1)
OverflowError: Python int too large to convert to C ssize_t

我做错了什么?使用文件名创建标签确实有效。文件名是有效文件。当脚本不在thread.Threading部分内部时脚本可以正常工作。当按下Raspberry GPIO按钮时,我想用最新的图片更新屏幕(脚本将拍摄带有camara的新照片)。所以屏幕应该加载最新拍摄的照片。

1 个答案:

答案 0 :(得分:0)

tkinter 线程安全(默认情况下)。处理GUI的所有操作必须在主线程中完成。您可以使用事件回调来执行您所要求的操作,但除非您实现了一个提供给主循环的事件队列,否则线程可以并且将会破坏tkinter。

此外,堆栈跟踪似乎指向此处的代码 - 堆栈跟踪根本不与显示的代码相交。

此外,调用root.update()通常是一个坏主意 - 它启动另一个本地事件循环,它可能能够为另一个事件循环广告调用另一个root.update()。 root.update_idletasks()比完全root.update()

更安全