2016-06-21 52 views
0

我有以下基于另一个Stackoverflow问题的解决方案的脚本。我有一个tkinter图形用户界面,当拍摄新图像时应该刷新。如何在GPIO按钮按下后用Tkinter重新加载图片?

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 

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

回答

0

tkinter是不是线程安全(默认情况下)。处理GUI的所有操作都必须在主线程中完成。你可以使用事件回调来做你所要求的事情,但是线程可以并且会破坏tkinter,除非你实现了一个事件队列,它馈入到主循环中。

此外,堆栈跟踪似乎并不指向您的代码 - 堆栈跟踪与所提供的代码完全不相交。

此外,调用root.update()通常是一个糟糕的主意 - 它启动另一个本地事件循环,可能会为另一个事件循环ad infinium调用另一个root.update()。 root.update_idletasks()比完整的root.update()更安全()

相关问题