Класс PhotoImage в Tkinter. Добавление изображений на виджеты
Иногда бывает необходимо, чтобы на кнопку, холст или другой элемент интерфейса была наложена уже имеющаяся картинка (которая хранится на диске).
В Python для работы с изображениями часто используют библиотеку Pillow. Однако, если ничего сложного не требуется, в самом Tkinter есть средства, позволяющие добавлять готовые картинки на виджеты. Одним из таковых является класс PhotoImage
, который поддерживает графические форматы PNG, GIF, PGM, PPM.
При создании экземпляра в конструктор можно передать адрес/имя файла (это не единственный вариант использования PhotoImage
):
img = PhotoImage(file='hello.png')
После этого объект img присваивается свойству image
таких виджетов как кнопка, метка и др. Также его можно передать в метод create_image
холста:
from tkinter import * root = Tk() img1 = PhotoImage(file='stefan.png') img2 = PhotoImage(file='AlphaEdge.png') img3 = PhotoImage(file='smile.gif') b = Label(width=216, height=50, image=img3, borderwidth=2, relief=GROOVE) c = Canvas(width=256, height=256, bg='white',) c.create_image(1, 1, anchor=NW, image=img2) c.create_image(128, 128, image=img1) b.pack(padx=20, pady=20) c.pack() root.mainloop()
По умолчанию метод create_image
принимает координаты точки холста, в которой будет размещен центр изображения. Однако с помощью параметра anchor
можно изменить точку, для которой указывается координата. Так в примере выше для img2 указано, что координата (1, 1) применяется для верхнего левого угла (north-west).
Когда в конструктор метки передается image
, то ее ширина и высота измеряются уже не в знакоместах, а в пикселях.
Если мы захотим разместить в метке текст с картинкой, просто добавить свойство text
не получится. Картинка "победит", и надписи вы не увидите. Чтобы и то, и то отображались одновременно, надо использовать опцию compound
, присвоив ей место, где должна появляться картинка: CENTER
(изображение будет подложено под текст), TOP
, BOTTOM
, LEFT
, RIGHT
.
from tkinter import * root = Tk() img = PhotoImage(file='basn.png') a = Label(image=img, text='Hello World', compound=TOP, bg='lightyellow') b = Button(image=img, text='Hello World', compound=LEFT, height=50) a.pack(padx=20, pady=20) b.pack(padx=20, pady=20) root.mainloop()
Если надо, чтобы виджет подстраивался под размеры изображения, не обязательно указывать для него параметры ширины и высоты. Они будут сконфигурированы соответственно размеру картинки.
from tkinter import * root = Tk() img2 = PhotoImage(file='basn.png') Button(image=img2).pack() img = PhotoImage(file='Spock.svg.png') Label(image=img, bg='lightyellow', text='Hello Land and Ocean and Sky', compound=TOP).pack(ipadx=10) root.mainloop()
Для холста подобное не работает. Без указания размера, последний будет иметь значения по-умолчанию (380x267 пикселей). Однако с помощью методов width
и height
экземпляра PhotoImage
мы можем получить размер картинки и использовать эти значения при конфигурации холста.
from tkinter import * root = Tk() img = PhotoImage(file='Spock.svg.png') w = img.width() h = img.height() c = Canvas(width=w+50, height=h+50, bg='gray') c.create_image(w//2+25, h//2+5, image=img) c.pack(padx=10, pady=10) root.mainloop()
Здесь, создавая холст, к ширине и высоте изображения мы добавляем по 50 пикселей, картинка устанавливается по центру по горизонтали и ближе к верхнему краю по вертикали.
Если требуется изменить размер изображения, то следует обратить внимание на библиотеку Pillow, так как с объектом PhotoImage
подобные операции выполнить затруднительно. Так с помощью метода zoom
можно увеличивать только на кратную величину (целочисленную).
Практическая работа
Видоизмените программу из практической работы урока про радиокнопки таким образом, чтобы отображался не только текст, но и связанная с ним картинка. Вместо метки можно использовать холст.
Курс с примерами решений практических работ: pdf-версия