tkinter.PhotoImage updated nicht das Bild bzw entfernt es

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Meeper
User
Beiträge: 15
Registriert: Donnerstag 14. Februar 2013, 17:41

Hey Leute,
Ich versuche, in einer GUI ein Bild mithilfe des tkinter.PhotoImage anzuzeigen (funktioniert auch), und dieses Bild im Fenster anschließend zu updaten auf ein anderes Bild, das man mithilfe eines Filedialogs auswählen soll. Ja, ich habe brav GIFs verwendet, und jedes Bild das ich getestet habe funktioniert auch wenn man es einzeln in einem Fenster oder dem Label eines Fensters erzeugt. Nur wenn man es updaten soll, wird es nicht mehr angezeigt.
Der lauffertige Code steht unten, die Probleme sind kommentiert.

Code: Alles auswählen

import tkinter as tk
import tkinter.filedialog as filedialog

master=tk.Tk()

img_var=tk.StringVar()
img_var.set('test.gif')

img_label=tk.Label(master) #Label auf dem das Bild angezeigt wird
img_label.grid()

image1=tk.PhotoImage(file=img_var.get())
img_label['image']=image1 #erzeugt das Bild im Label

def browse_image(): #öffnet einen Bildauswahldialog
    browse=filedialog.askopenfilename()
    if browse=="":return None #Klick auf "Abbrechen"
    img_var.set(browse)
#bis hierhin funktioniert alles, auch wenn das Bild im Fenster dann nicht auf das neue Bild upated; logisch, schließlich wird das PhotoImage nicht geupdated
#wenn wir jetzt also das PhotoImage manuell updaten, dann müsste doch eigentlich im Label im master anschließend das neue Bild zu sehen sein, oder?
    image1=tk.PhotoImage(file=img_var.get())
#es ändert sich immer noch nichts, also sagen wir dem Label nochmal, dass es ein neues Bild bekommen hat
    img_label["image"]=image1
#und ab hier updated zwar das Fenster, aber das Bild wird nicht mehr angezeigt :/
#auffällig ist übrigens dass das Label trotzdem die Abmessungen des neuen Bildes annimmt... wenn man aufs alte bild zurückschaltet ändert es auch die Größe
#wieder zurück, aber auch das alte Bild wird dann nicht mehr angezeigt.

choose_img=tk.Button(master,text="Browse Image...",command=browse_image)
choose_img.grid()
Falls ihr wisst, wie man tkinter dazu kriegt, das Bild ordentlich zu updaten, lasst es mich bitte wissen :D
Danke und schönen Tag noch ;)
Schorlem
User
Beiträge: 40
Registriert: Dienstag 3. Juni 2014, 16:37

Das liegt daran, dass du in der Funktion "browse_image" der Variable "image1" keinen *neuen* Wert zuweist, sondern eine *neue*, lokale erstellst, die nur innerhalb der Funktion gültig ist. Daher wird die lokale Variable beim Verlassen der Funktion gelöscht, weshalb auch keine Referenz mehr auf das neue Bild existiert und somit wird nichts angezeigt. Probier mal, am Anfang der Funktion "global image1" hinzuschreiben ;)

Globale Variablen sind allerdings böse und es ist eh sinnvoller, bei einer GUI einen objektbasierten Lösungsweg anzugehen.
Diese Nachricht wurde maschinell erstellt und ist daher ohne Unterschrift gültig.
Meeper
User
Beiträge: 15
Registriert: Donnerstag 14. Februar 2013, 17:41

Danke für den Tipp :D
Sorry falls das jetzt noobhaft kommt, aber mit objektbasiert meinst du doch eine Klasse zu erstellen, richtig? :)
Schorlem
User
Beiträge: 40
Registriert: Dienstag 3. Juni 2014, 16:37

Jupp, ist die übliche Vorgehensweise bei GUIs.
Diese Nachricht wurde maschinell erstellt und ist daher ohne Unterschrift gültig.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Meeper: auf Bilder muß man immer eine Referenz behalten, sonst räumt der Garbage-Collector von Python das Bild einfach weg. Am besten speicherst Du die Referenz direkt als Attribut im Label:

Code: Alles auswählen

import tkinter as tk
import tkinter.filedialog as filedialog

def browse_image(img_var, img_label):
    browse = filedialog.askopenfilename()
    if browse:
        img_var.set(browse)
        img_label.image = tk.PhotoImage(file=img_var.get())
        img_label["image"] = img_label.image

def main():
    master = tk.Tk()
    img_var = tk.StringVar()
    img_var.set('test.gif')

    img_label = tk.Label(master)
    img_label.grid()

    img_label.image = tk.PhotoImage(file=img_var.get())
    img_label['image'] = img_label.image

    choose_img = tk.Button(master, text="Browse Image...",
        command = lambda: browse_image(img_var, img_label))
    choose_img.grid()
    master.mainloop()

if __name__ == '__main__':
    main()
Antworten