2016-06-21 50 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()更安全()

相關問題