Используйте кнопку изображения, определенную внутри объекта с помощью TKinter - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь создать кнопку 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 голосов
/ 14 ноября 2018

У вас 2 проблемы здесь.

Первая проблема - изображение не сохраняется после __init__. Вы, вероятно, знаете, что вам нужно сохранить ссылку на изображение для использования в tkinter. Вы можете не знать, что в классе, если вы не назначите изображение атрибуту класса, оно не сохранит изображение после __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 отображал изображение и текст в кнопке. Тем не менее, вам также необходимо обновить аргумент изображения, чтобы включить новый 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

0 голосов
/ 14 ноября 2018

Кажется, я понял, что случилось.Благодаря связанному вопросу, что происходит во втором случае, это то, что ваш 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")
...