通过按钮和画布在python中显示图像

通过按钮和画布在python中显示图像,python,image,canvas,tkinter,Python,Image,Canvas,Tkinter,我是python的乞丐,特金特。我编写了一个代码,通常应该在画布中显示图像 发生的情况是,主框架(gui)与菜单栏一起显示,然后当我单击load image时,gui窗口缩小(我猜是100x100),但其中没有显示任何内容 你能给我解释一下为什么会发生这种情况,以便我能理解错误发生的地方,以及如何纠正它吗 # -*- coding:utf-8 -*- # Imports from tkinter import Tk, Menu, Canvas from PIL import Image, Ima

我是python的乞丐,特金特。我编写了一个代码,通常应该在画布中显示图像

发生的情况是,主框架(gui)与菜单栏一起显示,然后当我单击load image时,gui窗口缩小(我猜是100x100),但其中没有显示任何内容

你能给我解释一下为什么会发生这种情况,以便我能理解错误发生的地方,以及如何纠正它吗

# -*- coding:utf-8 -*-
# Imports
from tkinter import Tk, Menu, Canvas
from PIL import Image, ImageTk

# Function definitions
def deleteImage(canvas):
    canvas.delete("all")
    return

def loadImage(canvas, img):
    filename = ImageTk.PhotoImage(img)
    canvas.image = filename
    canvas.create_image(0,0,anchor='nw',image=filename)
    return

def quitProgram():
    gui.destroy()
# Main window
gui = Tk()

# Inside the main gui window
#Creating an object containing an image
# A canvas with borders that adapt to the image within it
img = Image.open("fleur.jpg")
canvas = Canvas(gui,height=img.size[0],width=img.size[0])
canvas.pack()

# Menu bar
menubar = Menu(gui)
# Adding a cascade to the menu bar:
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Files", menu=filemenu)
# Adding a load image button to the cascade menu "File"
filemenu.add_command(label="Load an image", command=loadImage)
# Adding a delete image button to the cascade menu "File"
filemenu.add_command(label="Delete image", command=deleteImage)
filemenu.add_separator()
filemenu.add_command(label="Quit", command=quitProgram)
menubar.add_separator()
menubar.add_cascade(label="?")

# Display the menu bar
gui.config(menu=menubar)
gui.mainloop()
编辑: 第二个问题是,我想在主gui窗口中创建画布和图像,并将它们作为参数传递给菜单按钮(请参见上面的代码,其中img和画布是与函数
loadImage
分开创建的)。将括号放在
命令=loadImage()
中本身就产生了一个问题

另一点在我脑海中提出了一个问题:关于第一个问题,通过保持对
filename=ImageTk.PhotoImage(img)
的引用解决了这个问题。由于引用是局部变量,所以在函数中保留引用通常不是毫无意义的吗?

正如effbot的页面中所述,您必须保留图像的引用以确保它不会被垃圾收集

必须在Python程序中保留对图像对象的引用, 要么将其存储在全局变量中,要么将其附加到 另一个物体

注意:当PhotoImage对象被Python垃圾收集时(例如。 当您从将图像存储在本地 变量),即使图像由 Tkinter小部件

为了避免这种情况,程序必须保留对图像的额外引用 对象一种简单的方法是将图像分配给小部件 属性,如下所示:

您的
loadImage()
方法应该如下所示

def loadImage():
    img = Image.open("fleur.jpg")
    filename = ImageTk.PhotoImage(img)
    canvas = Canvas(gui,height=100,width=100)
    canvas.image = filename  # <--- keep reference of your image
    canvas.create_image(0,0,anchor='nw',image=filename)
    canvas.pack()
def loadImage():
img=Image.open(“fleur.jpg”)
filename=ImageTk.PhotoImage(img)
画布=画布(gui,高度=100,宽度=100)
canvas.image=filename#如effbot页面中所述,您必须保留图像的引用,以确保它不会被垃圾收集

必须在Python程序中保留对图像对象的引用, 要么将其存储在全局变量中,要么将其附加到 另一个物体

注意:当PhotoImage对象被Python垃圾收集时(例如。 当您从将图像存储在本地 变量),即使图像由 Tkinter小部件

为了避免这种情况,程序必须保留对图像的额外引用 对象一种简单的方法是将图像分配给小部件 属性,如下所示:

您的
loadImage()
方法应该如下所示

def loadImage():
    img = Image.open("fleur.jpg")
    filename = ImageTk.PhotoImage(img)
    canvas = Canvas(gui,height=100,width=100)
    canvas.image = filename  # <--- keep reference of your image
    canvas.create_image(0,0,anchor='nw',image=filename)
    canvas.pack()
def loadImage():
img=Image.open(“fleur.jpg”)
filename=ImageTk.PhotoImage(img)
画布=画布(gui,高度=100,宽度=100)

canvas.image=filename#感谢您的回答,它提供了信息,但不幸的是,它没有产生我想要的结果。现在图像从一开始就被加载了,我想要的是,当我点击“加载图像”按钮时加载一个图像。@Aetos您能检查一下您的
文件菜单中
loadImage
旁边是否有图像。添加命令(…,command=loadImage)
行吗?通常,这条线应该是这样的。不是
filemenu.add_command(…,command=loadImage())
.Spot on:)现在我将编辑该线程以包含一些附加内容。感谢您的回答,它提供了信息,但不幸的是它没有产生我想要的结果。现在图像从一开始就被加载了,我想要的是,当我点击“加载图像”按钮时加载一个图像。@Aetos您能检查一下您的
文件菜单中
loadImage
旁边是否有图像。添加命令(…,command=loadImage)
行吗?通常,这条线应该是这样的。不是
filemenu.add_命令(…,command=loadImage())
.Spot on:)现在我要编辑线程以包含一些附加内容。要向命令添加参数,请检查此处。是的,虽然不是第一个解决方案。我必须使用functools库中的分部,它的工作方式如下:
filemenu.add_命令(label=“Load an image”,command=partial(loadImage,canvas,img))
要在命令中添加参数,请检查这里。是的,虽然不是第一个解决方案。我必须使用functools库中的分部,它的工作方式如下:
filemenu.add_命令(label=“Load an image”,command=partial(loadImage,canvas,img))