使用通过TKinter

时间:2018-11-14 14:13:53

标签: python tkinter python-imaging-library tk

我正在尝试构建一个tkinter按钮,该按钮将图像作为对象内部的背景。为什么第二种实现不起作用没有任何意义!

这里有3个非常简单的例子;谁能解释第二个实施不起作用的原因?

(Python 3.6.4 :: Anaconda,Inc。)

1。全局创建的按钮。

像魅力一样工作...

from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
def cb():
    print("Hello World")
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=cb, image=image)
b.pack()
w.mainloop()

2。在具有背景图片的对象A内部创建的按钮

该按钮在单击时不起作用,并且不显示图像:(。显然有问题,但我不理解...

from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
    def __init__(self, w):
        image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
        b = Button(w, text="text", command=self.cb, image=image)
        b.pack()

    def cb(self):
        print("Hello World")

a = A(w)
w.mainloop()

3。在对象A内创建的没有背景图像的按钮

按钮正常工作,但我也想显示图像

from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
    def __init__(self, w):
        image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
        b = Button(w, text="text", command=self.cb)#, image=image)
        b.pack()

    def cb(self):
        print("Hello World")

a = A(w)
w.mainloop()

2 个答案:

答案 0 :(得分:2)

您在这里有2个问题。

第一个问题是__init__之后没有保存图像。您可能知道您需要保存对图像的引用才能在tkinter中使用它。您可能不知道在类中,如果不将图像分配给class属性,它将不会在__init__之后保存图像。

因此,要解决第一个问题,您需要对此进行更改:

image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))

对此:

# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))

您在这里可能没有注意到的第二个问题是,加载图像时不会显示您的文本。这是因为您需要添加参数compound才能使tkinter在按钮中同时显示图像和文本。也就是说,您还需要更新image参数以包含新的self.image

所以改变这个:

b = Button(w, text="text", command=self.cb, image=image)

对此:

# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)

结果:

enter image description here

答案 1 :(得分:1)

我想我了解发生了什么。由于链接的问题,第二种情况是,image方法完成后,您的__init__被垃圾回收了。结果,您的映像不再对根应用程序可用,因此无法将其绑定到该映像。 解决它的方法是使它成为一个类属性:

class A():
    def __init__(self, w):
        self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
        b = Button(w, text="text", command=self.cb, image=self.image)
        b.pack()

    def cb(self):
        print("Hello World")