В библиотеке tkinter графические изображения отображаются за счет создания независимых объектов PhotoImage или BitmapImage и прикрепления их к другим виджетов путем установки атрибута image. Кнопки, метки, холсты, текстовые виджеты и меню — все они могут выводить изображения, связывая таким способом готовые графические объекты. Для иллюстрации сценарий в примере 8.36 выводит картинку на кнопке.
Пример 8.37. PP4E\Gui\Tour\imgButton.py
gifdir = “../gifs/” from tkinter import * win = Tk()
igm = PhotoImage(file=gifdir + “ora-pp.gif”)
Button(win, image=igm).pack()
win.mainloop()
Трудно было бы придумать более простой пример: этот сценарий всего лишь создает объект PhotoImage для GIF-файла, хранящегося в другом каталоге, и связывает его с параметром image виджета Button. Результат изображен на рис. 8.37.
Рис. 8.37. Сценарий imgButton в действии
Объект PhotoImage и его собрат BitmapImage просто загружают графические файлы и позволяют прикреплять полученные изображения к другим типам виджетов. Чтобы открыть файл с картинкой, его имя необходимо передать в атрибуте file этих виджетов изображений. Несмотря на всю простоту, прикрепление изображений к кнопкам может найти применение во множестве ситуаций — в главе 9, например, мы будем использовать эту простую идею при реализации кнопок для панелей инструментов в нижней части окна.
Виджеты Canvas — универсальные поверхности для вывода графики, подробнее обсуждаемые в следующей главе, тоже могут выводить картинки. Забегая вперед, в качестве предварительного знакомства отмечу, что холсты (объекты Canvas) достаточно просты в обращении, чтобы привести их в примере. Пример 8.38 выводит окно, изображенное на рис. 8.38.
Рис. 8.38. Изображение на холсте
Пример 8.38. PP4E\Gui\Tour\imgCanvas.py
gifdir = “../gifs/” from tkinter import * win = Tk()
img = PhotoImage(file=gifdir + “ora-lp4e.gif”)
can = Canvas(win)
can.pack(fill=BOTH)
can.create_image(2, 2, image=img, anchor=NW) # координаты x, y win.mainloop()
Размеры кнопок автоматически изменяются в соответствии с размерами изображений, холсты свои размеры не изменяют (потому что в холсты можно добавлять объекты, как будет показано в главе 9). Чтобы размер холста соответствовал размерам изображения, нужно установить его размер, исходя из значений, возвращаемых методами width и height объектов изображений, как в примере 8.39. Эта версия сценария при необходимости делает холст больше или меньше, чем размер, устанавливаемый по умолчанию; позволяет передавать имя графического файла в аргументе командной строки и может использоваться в качестве простой утилиты просмотра изображений. Окно, создаваемое этим сценарием, изображено на рис. 8.39.
Пример 8.39. PP4E\Gui\Tour\imgCanvas2.py
gifdir = “../gifs/” from sys import argv from tkinter import * filename = argv[1] if len(argv) > 1 else ‘ora-lp4e.gif’ # имя файла # в командной строке?
Рис. 8.39. Изменение размера холста соответственно картинке
win = Tk()
img = PhotoImage(file=gifdir + filename)
can = Canvas(win)
can.pack(fill=BOTH)
can.config(width=img.width(), height=img.height()) # размер соответственно can.create_image(2, 2, image=img, anchor=NW) # картинке win.mainloop()
Чтобы просмотреть другое изображение, нужно запустить этот сценарий, передав ему имя другого файла (попробуйте сами, на своем компьютере):
C:\…\PP4E\Gui\Tour> imgCanvas2.py ora-ppr-german.gif
Вот и все. В главе 9 будет показано, как помещать изображения в элементы меню, в кнопки на панели инструментов, приведены другие примеры с объектом Canvas и дружественный к изображениям виджет Text. В последующих главах они встретятся в программе просмотра слайдов (PyView), графическом редакторе (PyDraw) и в других. В графических интерфейсах Python/tkinter очень легко добавлять графику.
Однако начав всерьез использовать графические изображения, вы наверняка наткнетесь на два подводных камня, о которых я хочу предупредить заранее:
Поддерживаемые типы файлов
В настоящее время виджет PhotoImage поддерживает только файлы форматов GIF, PPM и PGM, а BitmapImage поддерживает файлы растровых изображений .xbm в стиле X Window. В последующих версиях количество поддерживаемых форматов может расшириться, и, конечно же, вы можете предварительно преобразовать свои изображения в указанные форматы. Но как будет показано далее в этой главе, поддержку дополнительных форматов изображений легко можно обеспечить с помощью открытого пакета PIL и его класса PhotoImage.
Берегите свои фотографии!
В отличие от других виджетов, tkinter изображение будет безвозвратно утрачено, если соответствующий объект изображения будет утилизирован сборщиком мусора. Это значит, что необходимо сохранять явные ссылки на объекты с графикой в течение всего времени, когда они могут понадобиться программе (например, присвоить их долгоживущей переменной, атрибуту объекта или компоненту структуры данных). Интерпретатор не сохраняет автоматически ссылку на графическое изображение, даже если оно связано с другими компонентами графического интерфейса, отображающими его. Кроме того, методы деструкторов объектов изображений стирают их из памяти. Мы уже видели раньше, что переменные tkinter тоже ведут себя неожиданным образом при уничтожении, но для графики этот эффект еще неприятнее и еще более вероятен. В будущих версиях Python такое поведение может измениться; при этом существуют веские причины не держать в памяти большие графические файлы неопределенно долгое время. На данный же момент элементы с графикой таковы, что если не используются, то могут быть утеряны.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011