[英]Why does Tkinter image not show up if created in a function?
此代碼有效:
import tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root.mainloop()
它向我展示了圖像。
現在,這段代碼可以編譯但沒有顯示圖像,我不知道為什么,因為它是相同的代碼,在 class 中:
import tkinter
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root = tkinter.Tk()
test = Test(root)
root.mainloop()
變量photo
是一個局部變量,它在類實例化后收集垃圾。 保存對照片的引用,例如:
self.photo = tkinter.PhotoImage(...)
如果您在“tkinter image doesn't display”上進行谷歌搜索,第一個結果是這樣的:
為什么我的 Tkinter 圖像沒有出現? (常見問題解答目前尚未過時)
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
def open_img():
global img
path = r"C:\.....\\"
img = ImageTk.PhotoImage(Image.open(path))
panel = Label(root, image=img)
panel.pack(side="bottom", fill="both")
but1 = Button(root, text="click to get the image", command=open_img)
but1.pack()
root.mainloop()
只需將 global 添加到 img 定義中即可
問題是 Python 通過稱為垃圾收集的過程自動刪除對變量的引用。 解決方案是保存參考或創建新參考。
以下是方法:
self
增加引用計數並保存引用。import tkinter
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
self.photo = tkinter.PhotoImage(file = './test.gif') # Changes here
canvas.create_image(0, 0, image=self.photo) # Changes here
root = tkinter.Tk()
test = Test(root)
root.mainloop()
import tkinter
l=[]
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
l.append(photo)
canvas.create_image(0, 0, image=photo)
root = tkinter.Tk()
test = Test(root)
root.mainloop()
使用方法 2 時,您可以像我一樣制作一個全局列表,也可以在類中使用列表。 兩者都會起作用。
一些有用的鏈接:
根據經驗,無論何時在縮進代碼塊中創建圖像,都需要保護對該圖像的引用。 這是因為 python 的自動垃圾收集,當它銷毀/離開該框架/頁面/縮進代碼塊時,它會收集引用計數為 0 的所有內容。
處理它的規范方法是在全局命名空間的某處有一個圖像列表,並將您的圖像引用添加到該列表。 這很方便但效率不高,應該用於小型應用程序。
import tkinter as tk
global_image_list = []
global_image_list.append(tk.PhotoImage(file = 'test.png'))
正如 Bryan 在他的回答中所建議的那樣,一種更有效的方法是將一個屬性綁定到為您保存該引用的小部件或類。 如果你做self.image
或widget.image
之前分配的widget = tk.Widget(..
被銷毀並收集垃圾。
import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text='test')
label.image = tk.PhotoImage(file = 'test.png')
label.configure(image=label.image)
只需將global photo
添加為函數內的第一行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.