ЛАБОРАТОРНАЯ РАБОТА №13
Тема: Разработка графического интерфейса
Цель:
Рассмотрение способов создания классов, объектов и их использования
ОГЛАВЛЕНИЕ
1 Пользовательский графический интерфейс
1.1 Создание окна
1.2 Общие свойства и методы виджетов
1.3 Системные методы
1.4 Основные виджеты
1.5 Упаковщики
1.6 Привязка событий
2 Разработка графического интерфейса
2.1 Создание окна, рамки и кнопок
2.2 Обработка событий
2.3 Работа с текстом
2.4 Использование флажков
2.5 Использование переключателей
Индивидуальные задания
Оглавление
1 Пользовательский графический интерфейс
Графический пользовательский интерфейс GUI (Graphical User Interface) – это разновидность
пользовательского интерфейса, в котором элементы интерфейса (меню, кнопки, значки, списки и т. п.),
представленные пользователю на дисплее, исполнены в виде графических изображений. В отличие от
интерфейса командной строки (типа старого DOS системы Windows), в GUI пользователь имеет свободный
доступ ко всем элементам интерфейса экрана и может ими управлять с помощью клавиатуры или мыши.
Библиотека tkinter (от англ. Tk interface) – это встроенная
графическая библиотека на основе средств Tk, широко распространенная в мире GNU/Linux и других
UNIX-подобных систем, которая портирована (переведена), в частности, на Microsoft Windows и Apple
Mac OS). Tk (от англ. Toolkit – «набор инструментов», «инструментарий») –
кроссплатформенная библиотека базовых элементов графического интерфейса, распространяемая с
открытыми исходными текстами.
Библиотека tkinter входит в стандартный дистрибутив языка Python (до
версии Python 3.0 именовалась Tkinter). В tkinter стандартизированные компоненты графического
интерфейса, с которыми взаимодействует пользователь, называются виджетами (widget, от англ. window
gadget).
Оглавление
1.1 Создание окна
Для подключения модуля tkinter используется форма
import
tkinter
from
*,
позволяющая использовать все имена модуля без указания префикса tkinter.
Tk() является базовым классом любого
tkinter приложения. При создании объекта этого класса запускается
интерпретатор tcl/tk и создается виджетами наивысшего уровня. Обычно им
является основное окно приложения. tkinter является событийно-ориентированной библиотекой. В
приложениях такого типа имеется главный цикл обработки событий. В tkinter такой цикл запускается
методом mainloop(). Для явного выхода из интерпретатора и завершения
цикла обработки событий используется метод quit().
Таким образом минимальное приложение на Tkinter будет таким:
import
tkinter
from
*
root = Tk()
root.mainloop()
Оглавление
1.2 Общие свойства и методы виджетов
Все виджеты в Tkinter обладают некоторыми общими свойствами. Опишем их, перед тем как перейти к
рассмотрению конкретных виджетов. Виджеты создаются вызовом конструктора соответствующего класса.
Первый аргумент (как правило неименованный, но можно использовать имя master) – это
родительский виджет, в который будет помещен (упакован) текущий виджет. Родительский виджет можно
не указывать, в таком случае будет использовано главное окно приложения. Далее следуют именованные
аргументы, конфигурирующие виджет.
Виджеты обладают следующими методами:
- configure() или config() – используются для конфигурирования (задания параметров)
виджетов во время исполнения программы (хотя виджеты могут быть сконфигурированы во время создания).
Параметры конфигурирования также могут быть заданы как значения ключей словаря виджета;
- cget() – является обратным методу config() – предназначен для получения
информации о конфигурации виджета;
- destroy – уничтожает виджет и всех его потомков. Если необходимо только на время
спрятать какой-либо виджет, то лучше пользоваться упаковщиком grid() и методом grid_remove() (это
позволяет сохранять взаимное расположение виджетов);
- Методы семейства grab_ предназначены для управления потоком события. Виджет, захвативший
поток будет получать все события окна или приложения:
- grab_set – передать поток данному виджету;
- grab_set_global – передать глобальный поток данному виджету. В этом случае все события
на дисплее будут передаваться этому виджету. Следует пользоваться очень осторожно, т.к. остальные
виджеты всех приложений не будут получать события;
- grab_release – освободить поток;
- grab_status - узнать текущий статус потока событий для виджета. Возможные значения: None,
"local" или "global";
- grab_current – получить виджет, который получает поток;
- Методы семейства focus_ используются для управления фокусом ввода с клавиатуры. Виджет,
имеющий фокус, получает все события с клавиатуры:
- focus (синоним focus_set) – передать фокус виджету;
- focus_force – передать фокус, даже если приложение не имеет фокуса. Используйте
осторожно, поскольку это может раздражать пользователей;
- focus_get – возвращает виджет, на который направлен фокус, либо None, если такой
отсутствует;
- focus_displayof – возвращает виджет, на который направлен фокус на том дисплее, на
котором размещен виджет, либо None, если такой отсутствует;
- focus_lastfor – возвращает виджет, на который будет направлен фокус, когда окно с этим
виджетом получит фокус;
- tk_focusNext – возвращает виджет, который получит фокус следующим (обычно смена фокуса
происходит при нажатии клавиши Tab). Порядок следования определяется последовательностью упаковки
виджетов;
- tk_focusPrev – то же, что и focusNext, но в обратном порядке;
- tk_focusFollowsMouse – устанавливает, что виджет будет получать фокус при наведении на
него мышки. Вернуть нормальное поведение достаточно сложно.
Оглавление
1.3 Системные методы
Эти методы не являются виджет-специфичными, т.е. хотя они являются методами виджетов они влияют
на работу интерпретатора tcl/tk:
- after, after_idle и after_cancel – таймеры, с помощью этих методов можно отложить
выполнение какого-нибудь кода на определенное время:
- after – принимает два аргумента: время в миллисекундах и функцию, которую надо выполнить
через указанное время. Возвращает идентификатор, который может быть использован в after_cancel;
- after_idle – принимает один аргумент: функцию, которая будет выполнена после завершения
всех отложенных операций (после того, как будут обработаны все события). Возвращает идентификатор,
который может быть использован в after_cancel;
- after_cancel – принимает один аргумент: идентификатор задачи, полученный предыдущими
функциями, и отменяет это задание;
- update и update_idletasks – функции для работы с очередью задач. Их выполнение
вызывает обработку отложенных задач:
- update_idletasks – выполняет задачи, обычно откладываемые "на потом", когда приложение
будет простаивать. Это приводит к прорисовке всех виджетов, расчету их расположения и т.д. Обычно
эта функция используется если были внесены изменения в состояние приложения, и необходимо, чтобы
эти изменения были отображены на экране немедленно, не дожидаясь завершения сценария;
- update – обрабатывает все задачи, стоящие в очереди. Обычно эта функция используется во
время "тяжёлых" расчетов, когда необходимо чтобы приложение оставалось отзывчивым на действия
пользователя;
- eval и evalfile – недокументированные функции для выполнения кода на tcl. eval
позволяет выполнить строку на языке программирования tcl, а evalfile - выполнить код, записанный в
файл.
В качестве аргументов принимают соответственно строку и путь к файлу. Данные функции полезны при
использовании дополнительных модулей, написанных на tcl.
Оглавление
1.4 Основные виджеты
К основным виджетам можно отнести:
- Toplevel – окно верхнего уровня. Обычно используется для создания многоконных
программ, а также для диалоговых окон. Имеет следующие методы:
- title() – заголовок окна;
- overrideredirect – указание оконному менеджеру игнорировать это окно. Аргументом
является True или False. В случае, если аргумент не указан – получаем текущее значение. Если
аргумент равен True, то такое окно будет показано оконным менеджером без обрамления (без заголовка
и бордюра). Может быть использовано, например, для создания splashscreen при старте программы;
- iconify() / deiconify() – свернуть / развернуть окно;
- withdraw() – "спрятать" (сделать невидимым) окно. Для того, чтобы снова показать его
надо использовать метод deiconify();
- minsize() и maxsize() – минимальный / максимальный размер окна. Методы принимают два
аргумента – ширина и высота окна. Если аргументы не указаны - возвращают текущее значение
- state() – получить текущее значение состояния окна. Может возвращать следующие значения:
normal (нормальное состояние), icon (показано в виде иконки), iconic (свернуто), withdrawn
(не показано), zoomed (развернуто на полный экран, только для Windows и Mac OS X);
- resizable() – может ли пользователь изменять размер окна. Принимает два аргумента –
возможность изменения размера по горизонтали и по вертикали. Без аргументов возвращает текущее
значение;
- geometry() – устанавливает геометрию окна в формате ширинаxвысота+x+y (пример:
geometry("600x400+40+80") – поместить окно в точку с координатам 40,80 и установить размер в
600x400). Размер или координаты могут быть опущены (geometry("600x400") – только изменить
размер, geometry("+40+80") - только переместить окно);
- transient() – сделать окно зависимым от другого окна, указанного в аргументе. Будет
сворачиваться вместе с указанным окном. Без аргументов возвращает текущее значение;
- protocol() – получает два аргумента: название события и функцию, которая будет
вызываться при наступлении указанного события. События могут называться WM_TAKE_FOCUS (получение
фокуса), WM_SAVE_YOURSELF (необходимо сохраниться, в настоящий момент является устаревшим),
WM_DELETE_WINDOW (удаление окна);
- tkraise() (синоним lift()) и lower() – поднимает (размещает поверх всех других окон) или
опускает окно. Методы могут принимать один необязательный аргумент: над/под каким окном разместить
текущее;
- grab_set() – устанавливает фокус на окно, даже при наличии открытых других окон;
- grab_release() – снимает монопольное владение фокусом ввода с окна;
Эти же методы могут быть использованы для корневого (root) окна.
- Button – обыкновенная кнопка, основными свойствами которой являются:
- text – текст, отображенный на кнопке;
- width, height – соответственно, ширина и высота кнопки;
- bg – цвет кнопки (сокращенно от background);
- fg – цвет текста на кнопке (сокращенно от foreground);
- font – шрифт и его размер;
- Label – это виджет, предназначенный для отображения какой-либо надписи без
возможности редактирования пользователем. Имеет те же свойства, что и перечисленные свойства
кнопки;
- Entry – это виджет, позволяющий пользователю ввести (или вывести с помощью метода
insert()) одну строку текста. Имеет дополнительное свойство bd (сокращенно от borderwidth),
позволяющее регулировать ширину границы:
- borderwidth – ширина бордюра элемента ( bd - сокращение от borderwidth);
- width – задает длину элемента в знакоместах;
- Text – это виджет, который позволяет пользователю ввести (или вывести с помощью
метода insert()) многострочный текст. Имеет дополнительное свойство wrap, отвечающее за перенос
(чтобы, например, переносить по словам, нужно использовать значение WORD;
- Listbox – это виджет, который представляет из себя список, из элементов которого
пользователь может выбирать один или несколько пунктов. Имеет дополнительное свойство selectmode,
которое, при значении SINGLE, позволяет пользователю выбрать только один элемент списка, а при
значении EXTENDED – любое количество;
- Frame (рамка) – предназначен для организации виджетов внутри окна;
- Checkbutton – это виджет, который позволяет отметить „галочкой“ определенный пункт
в окне. При использовании нескольких пунктов нужно каждому присвоить свою переменную;
- Radiobutton выполняет функцию, схожую с функцией виджета Checkbutton. Разница в том,
что в виджете Radiobutton пользователь может выбрать лишь один из пунктов. Реализация этого виджета
несколько иная, чем виджета Checkbutton. В этом виджете используется уже одна переменная. В
зависимости от того, какой пункт выбран, она меняет свое значение. Самое интересное, что если
присвоить этой переменной какое-либо значение, поменяется и выбранный виджет;
- Scale (шкала) – это виджет, позволяющий выбрать какое-либо значение из заданного
диапазона. Имеет свойства:
- orient – как расположена шкала на окне. Возможные значения: HORIZONTAL, VERTICAL
(горизонтально, вертикально);
- length – длина шкалы;
- from_ – с какого значения начинается шкала;
- to – каким значением заканчивается шкала;
- tickinterval – интервал, через который отображаются метки шкалы;
- resolution – шаг передвижения (минимальная длина, на которую можно передвинуть движок);
- Scrollbar – дает возможность пользователю "прокрутить" другой виджет (например
текстовое поле) и часто бывает полезен. Использование этого виджета достаточно нетривиально.
Необходимо сделать две привязки: command полосы прокрутки привязываем к методу xview/yview виджета,
а xscrollcommand/yscrollcommand виджета привязываем к методу set полосы прокрутки.
Оглавление
1.5 Упаковщики
Упаковщик (менеджер геометрии, менеджер расположения) – это специальный механизм, который
размещает (упаковывает) виджеты на окне. В tkinter есть три упаковщика: pack(),
place() и grid().
Обратите внимание, что в одном виджете можно использовать только один тип упаковки, при смешивании
разных типов упаковки программа, скорее всего, не будет работать. Разберем каждый из них по порядку:
- pack() – имеет максимальные функциональные возможности. При его применении можно
указать следующие аргументы:
- side ("left"/"right"/"top"/"bottom") – к какой стороне должен примыкать размещаемый
виджет;
- fill (None/"x"/"y"/"both") – необходимо ли расширять пространство предоставляемое
виджету;
- expand (True/False) – необходимо ли расширять сам виджет, чтобы он занял все
предоставляемое ему пространство;
- in_ – явное указание в какой родительский виджет должен быть помещен;
Кроме основной функции у виджетов есть дополнительные методы для работы с упаковщиками:
- pack_configure() – синоним для pack();
- pack_slaves() (синоним slaves()) – возвращает список всех дочерних упакованных виджетов
- pack_info – возвращает информацию о конфигурации упаковки;
- pack_propagate() (синоним propagate()) (True/False) – включает/отключает распространении
информации о геометрии дочерних виджетов. По умолчанию виджет изменяет свой размер в соответствии
с размером своих потомков. Этот метод может отключить такое поведение (pack_propagate(False)).
Это может быть полезно, если необходимо, чтобы виджет имел фиксированный размер и не изменял его по
прихоти потомков;
- pack_forget() (синоним forget()) - удаляет виджет и всю информацию о его расположении из
упаковщика. Позднее этот виджет может быть снова размещен;
- grid() – упаковщик представляет собой таблицу с ячейками, в которые помещаются
виджеты. Имеет следующие аргументы:
- row – номер строки, в который помещаем виджет;
- rowspan – сколько строк занимает виджет;
- column – номер столбца, в который помещаем виджет;
- columnspan – сколько столбцов занимает виджет;
- padx / pady – размер внешней границы (бордюра) по горизонтали и вертикали;
- ipadx / ipady – размер внутренней границы (бордюра) по горизонтали и вертикали. Разница
между pad и ipad в том, что при указании pad расширяется свободное пространство, а при ipad
расширяется помещаемый виджет;
- sticky ("n", "s", "e", "w" или их комбинация) – указывает к какой границе "приклеивать"
виджет. Позволяет расширять виджет в указанном направлении. Границы названы в соответствии со
сторонами света. "n" (север) – верхняя граница, "s" (юг) – нижняя, "w" (запад) –
левая, "e" (восток) – правая;
- in_ – явное указание в какой родительский виджет должен быть помещен;
Для каждого виджета указываем, в какой он находится строке, и в каком столбце. Если нужно,
указываем, сколько ячеек он занимает (если, например, нам нужно разместить три виджета под одним,
необходимо "растянуть" верхний на три ячейки).
- Дополнительные функции:
- grid_configure() – синоним для grid();
- grid_slaves() (синоним slaves()) – см. pack_slaves();
- grid_info() – см. pack_info();
- grid_propagate() (синоним propagate()) – см. pack_propagate();
- grid_forget() (синоним forget()) – см. pack_forget();
- grid_remove() – удаляет виджет из-под управления упаковщиком, но сохраняет информацию
об упаковке. Этот метод удобно использовать для временного удаления виджета;
- grid_bbox() (синоним bbox()) – возвращает координаты (в пикселях) указанных столбцов и
строк;
- grid_location() (синоним location()) – принимает два аргумента: x и y (в пикселях).
Возвращает номер строки и столбца в которые попадают указанные координаты, либо -1 если координаты
попали вне виджета;
- grid_columnconfigure() (синоним columnconfigure()) и grid_rowconfigure() (синоним
rowconfigure()) – важные функции для конфигурирования упаковщика. Методы принимают номер
строки/столбца и аргументы конфигурации. Список возможных аргументов:
minsize – минимальная ширина/высота строки/столбца; weight
– "вес" строки/столбца при увеличении размера виджета. 0 означает, что строка/столбец не
будет расширяться. Строка/столбец с "весом" равным 2 будет расширяться вдвое быстрее, чем с
весом 1;
uniform – объединение строк/столбцов в группы. Строки/столбцы
имеющие одинаковый параметр uniform будут расширяться строго в соответствии со своим весом;
pad – размер бордюра. Указывает, сколько пространства будет
добавлено к самому большому виджету в строке/столбце;
- place представляет собой простой упаковщик, позволяющий размещать виджет в фиксированном
месте с фиксированным размером. Также он позволяет ука зывать координаты размещения в
относительных единицах для реализации "резинового" размещения. При использовании этого упаковщика,
необходимо указывать координаты каждого виджета. Имеет аргументы:
- anchor ("n", "s", "e", "w", "ne", "nw", "se", "sw" или "center") – какой угол или
какая сторона размещаемого виджета будет указана в аргументах x/y/relx/rely. По умолчанию "nw"
– левый верхний угол;
- bordermode ("inside", "outside", "ignore") – определяет в какой степени будут
учитываться границы при размещении виджета;
- in_ – явное указание в какой родительский виджет должен быть помещен;
- x и y – абсолютные координаты (в пикселях) размещения виджета;
- width и height – абсолютные ширина и высота виджета;
- relx и rely – относительные координаты (от 0.0 до 1.0) размещения виджета;
- relwidth и relheight – относительные ширина и высота виджета;
- Дополнительные функции:
- place_slaves(), place_forget(), place_info() – см. описание аналогичных методов
упаковщика pack;
-
Относительные и абсолютные координаты (а также ширину и высоту) можно комбинировать. Так например,
relx=0.5, x=-2 означает размещение виджета в двух пикселях слева от центра родительского виджета,
relheight=1.0, height=-2 – высота виджета на два пикселя меньше высоты родительского виджета;
Оглавление
1.6 Привязка событий
Для большинства виджетов, реагирующих на действие пользователя, активацию виджета (например,
нажатие кнопки) можно привязать к функции обработчику этого события, используя опцию command.
К таким виджетам относятся: Button, Checkbutton, Radiobutton, Spinbox, Scrollbar, Scale.
Например: button = Button(command=callback). Такой способ является
предпочтительным и наиболее удобным способом привязки.
Другим способом привязки является использование метода
bind(), который привязывает событие к какому-либо действию (нажатие
кнопки мыши, нажатие клавиши на клавиатуре и т.д.). bind() принимает три
аргумента:
- название события;
- функцию, которая будет вызвана при наступлении события;
- третий аргумент (необязательный) – строка "+" – означает, что эта привязка
добавляется к уже существующим. Если третий аргумент опущен или равен пустой строке –
привязка замещает все другие привязки данного события к виджету.
Метод bind() возвращает идентификатор привязки, который может быть
использован в функции unbind(). Обратите внимание, что если
bind() привязан к окну верхнего уровня, то Tkinter будет обрабатывать
события всех виджетов этого окна (см. также bind_all() ниже).
Функция, которая вызывается при наступлении события, должна принимать
один аргумент – это объект класса Event(), в котором описано
наступившее событие. Объект класса Event() имеет следующие атрибуты
(в скобках указаны события, для которых этот атрибут установлен):
- serial – серийный номер события (все события);
- num – номер кнопки мыши (ButtonPress, ButtonRelease);
- focus – имеет ли окно фокус (Enter, Leave);
- height и width – ширина и высота окна (Configure, Expose);
- keycode – код нажатой клавиши (KeyPress, KeyRelease);
- state – состояние события (для ButtonPress, ButtonRelease, Enter, KeyPress,
КeyRelease, Leave, Motion – в виде числа); для Visibility – в виде строки);
- time – время наступления события (все события);
- x и y – координаты мыши;
- x_root и y_root – координаты мыши на экране (ButtonPress, ButtonRelease, KeyPress,
KeyRelease, Motion);
- char – набранный на клавиатуре символ (KeyPress, KeyRelease);
- send_event – см. документацию по X/Windows;
- keysym – набранный на клавиатуре символ (KeyPress, KeyRelease);
- keysym_num – набранный на клавиатуре символ в виде числа (KeyPress, KeyRelease);
- type – тип события в виде числа (все события);
- widget – виджет, который получил событие (все события);
- delta – изменение при вращении колеса мыши (MouseWheel).
Эта функция может возвращать строки "continue" и "break". Если функция возвращает "continue" то
Tkinter продолжит обработку других привязок этого события, если "break" - обработка этого события
прекращается. Если функция ничего не возвращает (возвращает None), то обработка событий
продолжается (т.е. это эквивалентно возвращению "continue").
Есть три формы названия событий. Самый простой случай это символ
ASCII. Так описываются события нажатия клавиш на клавиатуре:
widget.bind("z", callback). callback
вызывается каждый раз, когда будет нажата клавиша "z".
Второй способ длиннее, но позволяет описать больше событий. Он имеет
следующий синтаксис: <modifier-modifier-type-detail>. Название события
заключено в угловые скобки. Внутри имеются ноль или более модификаторов, тип события и
дополнительная информация (номер нажатой клавиши мыши или символ клавиатуры). Поля разделяются
дефисом или пробелом. Приведем пример одновременного нажатия Ctrl+Shift+q:
widget.bind("", callback) (в данном примере
KeyPress можно убрать).
Третий способ позволяет привязывать виртуальные события - события,
которые генерируются самим приложением. Такие события можно создавать самим, а потом привязывать
их. Имена таких событий помещаются в двойные угловые скобки: <<Paste>>. Есть некоторое
количество уже определенных виртуальных событий.
Список модификаторов:
- Control;
- Alt;
- Shift;
- Lock;
- Extended;
- Button1, B1 – нажата первая (левая) кнопка мыши;
- Button2, B2 – вторая (средняя) кнопка мыши;
- Button3, B3 – третья (правая);
- Button4, B4 – четвертая;
- Button5, B5 – пятая;
- Mod1, M1, Command;
- Mod2, M2, Option;
- Mod3, M3;
- Mod4, M4;
- Mod5, M5;
- Meta, M;
- Double – двойной щелчок мыши (например, );
- Triple – тройной;
- Quadruple – четверной.
Типы событий (здесь перечислены все возможные типы событий, для самых часто используемых дано
описание):
- Activate, Deactivate;
- MouseWheel – прокрутка колесом мыши;
- KeyPress, KeyRelease – нажатие и отпускание клавиши на клавиатуре;
- ButtonPress, ButtonRelease, Motion – нажатие, отпускание клавиши мыши, движение
мышью;
- Configure – изменение положения или размера окна;
- Map, Unmap – показывание или сокрытие окна (например, в случае
сворачивания/разворачивания окна пользователем);
- Visibility;
- Expose – событие генерируется, когда необходимо все окно или его часть
перерисовать;
- Destroy – закрытие окна;
- FocusIn, FocusOut – получение или лишение фокуса;
- Enter, Leave – Enter генерируется когда курсор мыши "входит" в окно, Leave –
когда "уходит" из окна;
- Property;
- Colormap;
- MapRequest, CirculateRequest, ResizeRequest, ConfigureRequest, Create;
- Gravity, Reparent, Circulate.
Дополнительные методы:
- bind_all – создает привязку для всех виджетов приложения. Отличие от привязки к
окну верхнего уровня заключается в том, что в случае привязки к окну привязываются все виджеты
этого окна, а этот метод привязывает все виджеты приложения (у приложения может быть несколько
окон);
- bind_class – создает привязку для всех виджетов данного класса;
- unbind – отвязать виджет от события. В качестве аргумента принимает идентификатор,
полученный от метода bind;
- unbind_all – то же, что и unbind, только для метода bind_all;
- unbind_class – то же, что и unbind, только для метода bind_class.
Для работы с изображениями в tkinter имеется два класса –
BitmapImage и PhotoImage.
BitmapImage представляет собой простое двухцветное изображение,
PhotoImage PhotoImage – полноцветное изображение.
Конструктор класса BitmapImageпринимает
следующие аргументы:
- background и foreground – цвета фона и переднего плана для изображения. Поскольку
изображение двухцветное, то эти параметры определяют соответственно черный и белый цвет;
- file и maskfile – пути к файлу с изображением и к маске (изображению, указывающему
какие пиксели будут прозрачными);
- data и maskdata – вместо пути к файлу можно указать уже загруженные в память
данные изображения. Данная возможность удобна для встраивания изображения в программу.
Пример:
from Tkinter import *
data = '''#define image_width 15
#define image_height 15
static unsigned char image_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x30, 0x0c, 0x60, 0x06,
0x60, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x60, 0x06, 0x60, 0x06, 0x30, 0x0c,
0x38, 0x1c, 0x00, 0x00, 0x00, 0x00 };'''
root=Tk()
image = BitmapImage(data=data, background='red', foreground='green')
button=Button(root, image=image)
button.pack()
root.mainloop()
PhotoImage позволяет использовать
полноцветное изображение. Кроме того у этого класса есть несколько (достаточно примитивных) методов
для работы с изображениями. PhotoImage гарантированно понимает форматы
GIF и PPM/PGM (под Windows дополнительно PNG).
Аргументы конструктора:
- file – путь к файлу с изображением.;
- data – вместо пути к файлу можно указать уже загруженные в память данные
изображения.
Изображения в формате GIF могут быть закодированы с использование base64. Данная возможность удобна
для встраивания изображения в программу;
- format – явное указание формата изображения;
- width, height – ширина и высота изображения;
- gamma – коррекция гаммы;
- palette – палитра изображения.
Оглавление
2 Разработка приложения с использованием ООП и графического интерфейса
2.1 Создание окна, рамки и кнопок
В качестве первого примера создания пользовательского приложения с использоваением графической
библиотеки tkinter рассмотрим программу
gui1.py, в которой создается пользовательское окно, а в нем –
рамка с тремя кнопками:
from
tkinter
import
*
class
My_frame
(Frame):
''' Рамка с тремя кнопками '''
def
__init__
(self,master):
super
().__init__(master)
self.grid()
self.create_widgets()
def
create_widgets
(self):
''' Создает три кнопки '''
self.bt1=Button(self,text=
'Кнопка №1'
, fg=
'blue'
, font=
'12'
)
self.bt1.grid()
self.bt2=Button(self)
self.bt2.grid()
self.bt2[
'text'
]=
'Кнопка №2'
self.bt2[
'fg'
]=
'blue'
self.bt2[
'font'
]=
'12'
self.bt3=Button(self)
self.bt3.grid()
self.bt3.config(text=
'Кнопка №3'
, fg=
'blue'
, font=
'12'
)
)
root=Tk()
#Создание базового окна
root.title(
'Рамка с кнопками'
)
root.geometry(
'230x95+800+200'
)
app=My_frame(root)
root.mainloop()
Для запуска программы gui1.py на
выполнение непосредственно из лабораторной работы используется ссылка:
IE:gui1.pyw. Для правильной работы ссылки необходимо:
- применять только браузер Internet Explorer;
- использовать специальную запускающую программу go1.js –
new ActiveXObject("WScript.shell")).run(PYTHON\\LAB13\\gui1.pyw"
- прописать в ссылке путь к программе go1.js;
- хранить файлы с программами gui1.pyw и go1.js в папке "LAB13".
В программе gui1.py подключение модуля
tkinter осуществляется с использованием формы
from tkinter import *. При этом имена всех классов и методов модуля
помещаются в пространство имен программы и обращение к ним происходит без добавления префикса
tkinter.
На базе класса Frame модуля
tkinter создается пользовательский класс
My_frame, который описывает рамку, содержащую три кнопки. При создании
конструктора этого класса используется встроенная функция super(),
которая предназначена для наследования методов родителького класса при их перегрузке. Таким
образом, к методам конструктора класса Frame() объекта
master добавляются методы:
grid() – для размещения рамки, и
create_widgets() – для создания кнопок в рамке.
Кнопки в виде объектов bt1,
bt2 и bt3 создаются с использованием класса
Button модуля tkinter. Хотя кнопки создаются в
этом примере одинаковые, способы задания параметров кнопки: text –
указывающего название кнопки, fg и font –
задающих соответственно цвет (blue) и размеры (12 пикселей) символов, используются разные:
- для кнопки №1 – непосредственно при ее создании;
- для кнопки №2 – задаются с помощью ключей словаря экземпляра класса Button;
- для кнопки №3 – с помощью метода config().
После описания класса в программе gui1.py:
- создается пользовательское окно, обычно именуемое root;
- указываются имя этого окна – 'Рамка с кнопками' и его размеры и расположение на экране:
- длина – 230 пикселей;
- ширина – 85 пикселей;
- смещение по горизонтали – 800 пикселей;
- смещение по вертикали – 200 пикселей;
- в этом окне создается рамка, свойства которой описаны в классе My_frame();
- запускается цикл обработки событий (хотя в этом примере события не обрабатываются).
При выполнении программы IE: gui1.pyw на экране появляется окно с заданными
графическими объектами.
Оглавление
2.2 Обработка событий
В качестве примера обработки событий, т.е. действий пользователя над виджетами, приведена
программа gui2.py, в которой также, как и в программе
gui1.py, создается пользовательский класс
My_frame2, описывающий рамку, которая, однако, имеет следующие отличия:
- содержит только одну кнопку
- для этой кнопки кроме параметра text, указывающего ее начальное название, задаются также
следующие параметры:
- command – указывает метод – обработчик события для кнопки (self.count);
- width – задает длину кнопки (30);
- bg – задает цвет фона (#efffef');
- fg – задает цвет символов;(blue)
- font – задает размер символов (6mm);
- содержит метод count(), который по каждому щелчку по кнопке увеличивает значение переменной
bt_clicks на единицу и изменяет в названии кнопки число выполненных по ней щелчков.
from
tkinter
import
*
class
My_frame2
(Frame):
Рамка с кнопкой, подсчитывающей события '''
def
__init__
(self,master):
super
().__init__(master)
self.grid()
self.bt_clicks=0
self.create_widgets()
def
create_widgets
(self):
''' Создает кнопку '''
self.bt1=Button(self,text=
'Число щелчков: 0'
,
command=self.count,
width=
'20'
,
height=
'2'
,
bg=
'#efffef'
,
fg=
'blue'
,
font=
'arial 14'
)
self.bt1.grid()
def
count
(self):
self.bt_clicks+=1
self.bt1[
'text'
]=
'Число щелчков: '
+
str
(self.bt_clicks)
root=Tk()
root.title(
'Обработка событий'
)
root.geometry(
'240x60+800+300'
)
app2=My_frame2(root)
root.mainloop()
После запуска программы
IE: gui2.pyw на экране появляется окно с кнопкой, имеющей заданные параметры.
После каждого щелчка мышкой по кнопке в ее наименовании число щелчков увеличивается на 1.
Оглавление
2.3 Работа с текстом
В качестве примера работы с тестом при использовании графического интерфейса приведена
программа gui3.py:
from
tkinter
import
*
class
My_frame3
(Frame):
''' Рамка для работы с текстом '''
def
__init__
(self,master):
super
().__init__(master)
self.grid()
self.create_widgets()
def
create_widgets
(self):
''' Создает 2 метки, текстовое поле, текстовую область и кнопку '''
#метка-инструкция
self.ins_lb=Label(self, text=
'Как прожить до 100 лет?'
, fg=
'blue'
, font=
'arial 14'
)
self.ins_lb.grid(row=0, column=0, columnspan=2,sticky=W)
#метка-пароль
self.ps_lb=Label(self, text=
'Пароль'
, fg=
'blue'
, font=
'arial 10'
)
self.ps_lb.grid(row=1, column=0,
sticky=W)
#текстовое поле для ввода пароля
self.ps_ent=Entry(self
, bg=
'#f0f0ff'
, font=
'arial 10'
)
self.ps_ent.grid(row=1, column=1,
sticky=E)
#создание текстовой области, куда будет
помещен ответ
self.txt=Text(self, width=30, height=4, wrap=WORD, bg=
'#f0f0ff'
, font=
'arial 10''
)
self.txt.grid(row=2, column=0, columnspan=2)
#кнопка отправки сообщения
self.bt=Button(self,text=
'Узнать секрет'
, fg=
'blue'
, bd=
'5'
, font=
'arial 12'
,
command=self.reveal)
self.bt.grid(row=3, column=0, sticky=W)
def
reveal
(self):
contents=self.ps_ent.get()
if
contents==
'secret'
):
message=
'Чтобы прожить до 100 лет, надо сначала '
\
'прожить 99 лет и 11 месяцев, а потом вести себя '
\
'очень-очень осторожно.'
else
:
message=
'Вы ввели неправильный пароль.'
self.secret_txt.delete(0.0,END)
self.secret_txt.insert(0.0,message)
root=Tk()
root.title(
'Работа с текстом'
)
root.geometry(
''250x160+850+300'
)
app3=My_frame3(root)
root.mainloop()
В программе gui3.py описан класс
My_frame3, в котором с помощью метода
create_widgets() создаются следующие виджеты:
- неизменяемые сообщения (метки) на базе класса Label:
- 'Чтобы узнать секрет долголетия введите пароль' (объект ins_lb);
- 'Пароль' (объект ps_lb);
- текстовое поле для ввода пароля на базе класса Entry (объект ps_ent);
- кнопка с сообщением (надписью) 'Узнать секрет' на базе класса Button (объект submit_bt);
- текстовая область для помещения ответа на базе класса Text (объект secret_txt), которая
имеет следующие параметры:
- ширина (width) – 35 символов;
- высота (height) – 5 рядков;
- перенос по границе слева (WORD))
Помимо метода create_widgets() в классе
My_frame3 также описан обработчик щелчка по кнопке 'Узнать секрет'
– метод reveal(), который:
- получает с помощью метода get() из текстового поля ps_ent введенный пользователем пароль;
- сравнивает его с паролем 'secret' и формирует сообщение, соответствующее результату
сравнения: либо приводится "секрет долголения", либо сообщается о том, что пароль введен
неправильно;
- очищает текстовую область ответа (secret_txt);
- помещает туда сформированное сообщение.
Отметим использование в этой программе метода grid(), который
осуществляет размещение (упаковку) графических элементов на рамке. В отличие от программ
gui1.py и gui2.py, где метод
grid() использовался без параметров и, следовательно, виджеты
располагались по усматрению интерпретатора, в программе gui3.py
явным образом указано расположение элементов. При использовании метода
grid() поле рамки изображается в виде решетки, состоящей из рядков и
колонок. Для указания местоположения виджета использованы следующие параметры:
- row – указывает номер рядка;
- column – указывает номер колонки;
- columnspan – указывает размер ячейки в колонках (по умолчанию – 1);
- sticky – указывает выравнивание данных относительно границ ячейки:
- N – по верхней границе;
- E – по правой границе;
- S – по нижней границе;
- W – по левой границе.
При выполнении программы IE: gui3.pyw на экране появляется окно с
описанными выше виджетами. При вводе в текстовое поле 'Пароль' неправильного пароля в текстовой
области появляется сообщение "Вы ввели неправильный пароль.". А при вводе слова "secret" –
появляется сообщение "Чтобы прожить до 100 лет, надо сначала прожить 99 лет и 11 месяцев, а потом
вести себя очень-очень осторожно."
Оглавление
2.4 Использование флажков
В качестве примера работы с флажками при использовании tkinter
приведена программа gui4.py:
from
tkinter
import
*
class
My_frame4
(Frame):
''' Использование флажков '''
def
__init__
(self,master):
super
(My_frame4, self).__init__(master)
self.grid()
self.create_widgets()
def
create_widgets
(self):
''' Создает три флажка '''
#метка-описание
Label(self,
text=
'Укажите любимые телепередачи'
, font=
'arial 13'
, fg=
'blue'
).grid(row=0, column=0,sticky=W)
#метка-инструкция
Label(self,
text=
'Выберете все, что нравится'
, font=
'arial 11'
, fg=
'blue'
).grid(row=1, column=0,sticky=W)
#флажок 'Футбол'
self.likes_football=BooleanVar()
Checkbutton(self,text=
'Футбол'
,
variable=self.likes_football,
command=self.update_text
).grid(row=2, column=0,sticky=W)
#флажок 'История'
self.likes_history=BooleanVar()
Checkbutton(self,text=
'История'
,
variable=self.likes_history,
command=self.update_text
).grid(row=3, column=0,sticky=W)
#флажок 'Природа'
self.likes_nature=BooleanVar()
Checkbutton(self,text=
'Природа'
,
variable=self.likes_nature,
command=self.update_text
).grid(row=4, column=0,sticky=W)
#текстовая область с результатом
self.results_txt=Text(self, fg=
'blue'
, font=
'arial 11'
width=40, height=5, wrap=WORD)
self.results_txt.grid(row=5, column=0, columnspan=3)
def
update_text
(self):
likes=
''
if
self.likes_football.get():
likes+=
'Вам нравится футбол\n'
if
self.likes_history.get():
likes+=
'Вас привлекает история\n'
if
self.likes_nature.get():
likes+=
'Вам небезразлична природа\n'
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,likes)
root=Tk()
root.title(
'Использование флажков'
)
root.geometry(
'270x185+800+200'
)
app4=My_frame4(root)
root.mainloop()
В отличие от программ gui1.py,
gui2.py и gui3.py в программе
gui4.py при создании объектов меток
(класс Label) используется более короткая форма – без указания имен
объектов. Это допускается делать в тех случаях, когда имена этих объектов в дальнейшем не
используются в описании класса.
Другой особенностью программы gui4.py
является использование флажков – графических элементов класса
Checkbutton, при помощи которых осуществляетя выбор (от одной до трех)
телепередач:
- о футболе;
- об истории;
- о природе.
При этом для каждого флажка:
- указывается переменная класса BooleanVar, соответственно:
- likes_football;
- likes_history;
- likes_nature.
- создается с использованием короткой формы (т.е. без указания имени) объект класса
Checkbutton и задаются следующие значения его параметров:
- для text – наименование флажка (соответственно, "Футбол", "История" и "Природа");
- для command – наименование функции (update_text), которая обрабатывает события,
связанные с изменением состояния флажка (т.е. выбран флажок или нет);
- для variable, отражающего текущее состояние флажка, – имя переменной, с которой этот
параметр связывается(соответственно likes_football, likes_history или likes_nature).
Обработчик update_text() выполняет следующие действия:
- последовательно анализирует состояние переменных
likes_football, likes_history и
likes_nature и в зависимости от значения переменной
(True или False) добавляет или не добавляет к
переменной likes значение, соответственно, 'Вам нравится футбол',
'Вас привлекает история' или 'Вам небезразлична природа';
- очищает текстовое поле results_txt;
- выводит в текстовое поле results_txt значение переменной likes.
При выполнении программы IE: gui4.pyw на экране появляется окно со
следующими виджетами:
- меткой-описанием "Укажите любимые телепередачи";
- меткой-инструкцией "Выберете все, что нравится";
- флажками:
- "Футбол";
- "История";
- "Природа";
- текстовой областью для вывода результатов выбора.
При щелчке по любому флажку в текстовую область выводится соответствующее отмеченному флажку
сообщение. При повторном щелчке отметка с флажка снимается и сообщение, указанное для данного
флажка, удаляется из текстовой области.
Оглавление
2.5 Использование переключателей
В качестве примера работы с переключателями при использовании tkinter
приведена программа gui5.py:
from
tkinter
import
*
class
My_frame5
(Frame):
''' Использование переключателей '''
def
__init__
(self,master):
super
(My_frame5, self).__init__(master)
self.grid()
self.create_widgets()
def
create_widgets
(self):
''' Создает переключатель '''
#метка-инструкция
Label(self,
text=
'Укажите любимую телепередачу'
, fg=
'blue'
, font=
'arial 13'
).grid(row=0, column=0,sticky=W)
self.favorite=StringVar()
self.favorite.set(
None
)
#положение переключателя 'Футбол'
Radiobutton(self,text=
'Футбол'
,
variable=self.favorite,
value=
'о футболе'
command=self.update_text
).grid(row=1, column=0,sticky=W)
#положение переключателя 'История'
Radiobutton(self,text=
'История'
,
variable=self.favorite,
value=
'об истории'
command=self.update_text
).grid(row=2, column=0,sticky=W)
#положение переключателя 'Природа'
Radiobutton(self,text=
'Природа'
,
variable=self.favorite,
value=
'о природе'
command=self.update_text
).grid(row=3, column=0,sticky=W)
#текстовая область для результата
self.results_txt=Text(self, fg=
'blue'
, font=
'arial 10'
, width=40, height=5, wrap=WORD)
self.results_txt.grid(row=4, column=0, columnspan=3)
def
update_text
(self):
message=
"Ваша любимая телепередача - "
message+=self.favorite.get()
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,message)
root=Tk()
root.title(
'Использование переключателя'
)
root.geometry(
'310x120+800+200'
)
app=My_frame5(root)
root.mainloop()
В отличие от программы gui4.py, в которой
может осуществляться выбор нескольких телепередач, в программе gui5.py
можно выбрать только одну телепередачу. Поэтому вместо трех флажков класса
Checkbutton используется один переключатель с тремя положениями,
наименования которых соответствуют наименованиям флажков.
При этом выполняются следующие действия:
- указывается атрибут self.favorite класса StringVar для хранения наименования выбранного
положения переключателя (при его создании указывается значение None);
- для каждого положения переключателя создается объект класса Radiobutton и указываются
значения его параметров:
- для text – наименование положения переключателя (соответственно, "Футбол", "История" и
"Природа");
- для command – наименование функции (update_text), которая обрабатывает события,
связанные с изменением состояния переключателя;
- для variable, отражающего текущее состояние переключателя, – self.favorite (имя
атрибута, с которыи этот параметр связывается;
- для value – значение выбранного положения переключателя, соответственно, 'о футболе',
'об истории' или 'о природе'.
Обработчик update_text() выполняет следующие действия:
- задает начальное значение переменной message ("Ваша любимая телепередача - ");
- используя атрибут self.favorite и метод get() получает значение выбранного положения
переключателя и добавляет его к значению переменной message;
- очищает текстовое поле results_txt;
- выводит в текстовое поле results_txt значение переменной message.
При выполнении программы IE: gui5.pyw на экране появляется окно со
следующими виджетами:
- меткой-инструкцией "Укажите любимую телепередачу";
- переключателем, имеющем три состояния:
- "Футбол";
- "История";
- "Природа";
- текстовой областью для вывода результата выбора.
При щелчке по одному из положений переключателя в текстовой области появляется соответствующее
сообщение.
Оглавление
Индивидуальные задания
Разработать программу на языке Python, в которой на базе модуля
tkinter разработан графический интерфейс, имеющий несколько окон:
- окно с кнопкой (объект Button), надпись на которой меняется по каждому щелчку и содержит
следующую информацию – номер щелчка и число, которое определяется согласно колонке
"Число" табл. №1:
- 1 – очередное простое число (начиная с 1);
- 2 – очередное число Фибоначчи (начиная с 1);
- 3 – очередное простое число вида 2 n - 1 (начиная с n = 1);
- окно, содержащее:
- текстовое поле (объект Text), куда выводится начало некоторого небольшого сообщения
(рассказа и т.п.);
- поле ввода пароля (объект Entry);
- кнопку для продолжения вывода сообщения (объект Button);
- второе текстовое поле (объект Text), куда выводится неожиданное (смешное) завершение сообщения
(при правильном вводе пароля) или сообщение о неправильном вводе пароле;
- метки (объект Label) – при необходимости;
- окно, содержащее:
- пять флажков (объекты Checkbutton), задающие согласно колонке "Флажки" табл. №1:
1 – числа 1, 2, 4, 8 и 16;
2 – 5 букв кириллицы (на усмотрение студента);
2 – 5 английских букв (на усмотрение студента);
- текстовое поле, куда помещается результат:
для чисел – сумма заданных чисел;
для букв – слово, состоящее из выбранных букв;
- окно, содержащее:
- переключатели (объекты Radiobutton), задающие согласно колонке "Переключатели"
табл. №1:
1 – изменяемые типы;
2 – неизменяемые типы;
3 – контейнеры;
4 – последовательности;
- текстовое поле, куда помещается результат – пример литерала для выбранного класса.
Таблица 1 – Перечень индивидуальных заданий
Номер п/п | Число | Флажкий | Переключатели
|
---|
1 | 1 | 3 | 1
|
2 | 2 | 1 | 2
|
3 | 3 | 2 | 3
|
4 | 1 | 3 | 4
|
5 | 2 | 1 | 1
|
6 | 3 | 2 | 2
|
7 | 1 | 3 | 3
|
8 | 2 | 1 | 4
|
9 | 3 | 2 | 1
|
10 | 1 | 3 | 2
|
11 | 2 | 1 | 3
|
12 | 3 | 2 | 4
|
13 | 1 | 3 | 1
|
14 | 2 | 1 | 2
|
15 | 3 | 2 | 3
|
16 | 1 | 3 | 4
|
17 | 2 | 1 | 1
|
18 | 3 | 2 | 2
|
19 | 1 | 3 | 3
|
20 | 2 | 1 | 4
|
Оглавление