2016-06-21 16 views
0

Ich habe das folgende Skript basierend auf einer Lösung einer anderen Stackoverflow-Frage. Ich habe eine tkinter-GUI mit einem Bild, das aktualisiert werden sollte, wenn ein neues genommen wird.Wie kann ich nach dem Drücken der GPIO-Taste ein Bild mit Tkinter laden?

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() 

ich diesen Fehler:

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 

Was mache ich falsch? Das Erstellen eines Labels mit dem Dateinamen funktioniert. Der Dateiname ist eine gültige Datei. Das Skript funktioniert, wenn es nicht innerhalb des thread.Threading-Teils ist. Ich möchte den Bildschirm mit dem neuesten Bild aktualisieren, wenn eine Raspberry GPIO-Taste gedrückt wird (das Skript wird ein neues Foto mit einer Kamera aufnehmen). Der Bildschirm sollte also mit dem neuesten Bild geladen werden.

Antwort

0

tkinter ist nicht Thread-Safe (standardmäßig). Alle Operationen, die mit der GUI zu tun haben, müssen im Hauptthread durchgeführt werden. Sie können tun, was Sie fragen, verwenden Rückrufe für Ereignisse, aber Threading kann und wird tkinter brechen, es sei denn, Sie implementieren eine Ereigniswarteschlange, die in die Hauptschleife füttert.

Darüber hinaus scheint der Stack-Trace auf Ihren Code hier nicht zu zeigen - dass Stack-Trace den dargestellten Code überhaupt nicht schneidet.

Außerdem ist das Aufrufen von root.update() generell eine schlechte Idee - es startet eine andere lokale Ereignisschleife, die möglicherweise eine andere root.update() für eine weitere Ereignisschleife ad infinium aufrufen kann. root.update_idletasks() ist viel sicherer als eine vollständige root.update()