Графический интерфейс – необходимый компонент любого современного приложения. Он значительно облегчает использование программы, управление ее настройками и выполнение любых других действий. Существует несколько библиотек, позволяющих на практике реализовывать работу графического интерфейса в Python. Но самой простой, безусловно, является Tkinter. Она позволяет создавать окна и добавлять на них привычные каждому графические элементы: надписи, кнопки. Поскольку Tkinter – свободное ПО, то эта библиотека регулярно обновляется и дополняется. Это позволяет ее использовать по максимуму. Сегодня мы более подробно поговорим об окне в этой оболочке. В том числе, о том, как осуществлять его настройку и обработку событий.
Как обрабатывать события с мыши и клавиатуры?
Любое приложение с графическим интерфейсом может реагировать на события. Без этого никуда. Именно от него зависит возможность вообще взаимодействовать с окном приложения.
Что такое событие? Это функция, которая выполняется каждый раз, когда выполняется определенное действие или появляется определенное условие, связанное с графическим интерфейсом.
С событиями сталкивался каждый пользователь, когда нажимал клавиши на клавиатуре или выполнял клик мышью по элементам. Например, параметр command – это типичный обработчик событий виджета Button. После того, как кнопка будет нажата, выполняется функция, которая прописывается в том параметре.
Чтобы вызывать некоторые события, никаких действий человек и не требуется. Примером такого служит изменение фокуса ввода.
Как проверить, привязано ли конкретное событие к элементу окна? Для этого необходимо использовать функцию bind. Приведем пример, который демонстрирует, как осуществляется привязка событий мыши к Frame.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
frame = tk.Frame(self, bg=»green»,
height=100, width=100)
frame.bind(«<Button-1>», self.print_event)
frame.bind(«<Double-Button-1>», self.print_event)
frame.bind(«<ButtonRelease-1>», self.print_event)
frame.bind(«<B1-Motion>», self.print_event)
frame.bind(«<Enter>», self.print_event)
frame.bind(«<Leave>», self.print_event)
frame.pack(padx=50, pady=50)
def print_event(self, event):
position = «(x={}, y={})».format(event.x, event.y)
print(event.type, «event», position)
if __name__ == «__main__»:
app = App()
app.mainloop()
Обработка событий осуществляется с помощью метода print_event(), который определяет расположение курсора в консоли и тип события, а далее выводит соответствующие данные в консоль. Если вы попробуете выполнить этот код и пошевелить зеленый квадрат с помощью мыши, то увидите, что в консоли будет регулярно появляться информация о том, что это за событие.
Приведем еще один пример. Он продемонстрирует, как работает программа с одним полем ввода и несколькими привязками. Первая из них активируется, на текстовое поле переходит фокус, а второе – если нажимается кнопка.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
entry = tk.Entry(self)
entry.bind(«<FocusIn>», self.print_type)
entry.bind(«<Key>», self.print_key)
entry.pack(padx=20, pady=20)
def print_type(self, event):
print(event.type)
def print_key(self, event):
args = event.keysym, event.keycode, event.char
print(«Знак: {}, Код: {}, Символ: {}».format(*args))
if __name__ == «__main__»:
app = App()
app.mainloop()
Сначала в приложении активируется событие FocusIn, которое срабатывает на появление фокуса в поле ввода.
В том числе, события активируются и с непечатаемыми символами типа клавиш стрелок или кнопки Backspace.
Отслеживание событий: принцип работы
Метод bind, который используется для отслеживания событий, используется с тремя аргументами:
- Событие, которое должно отслеживаться.
- Функция, которая выполняется при активации события.
- Строка Add, использование которой – необязательно.
Первый аргумент должен содержать событие формата <modifier-type-detail>.
Модификаторы также использовать необязательно. С их помощью можно задать дополнительные особенности события типа нажатия вспомогательных кнопок, двойного, тройного осуществления события и так далее.
Приведем их подробный перечень.
- Shift – при нажатии клавиши Shift вместе с событием, которое происходит.
- Alt – задает срабатывание события при условии, что одновременно с ним нажата клавиша Alt.
- Control – если нажимается кнопка Control на клавиатуре.
- Lock – при нажатии клавиши Lock на клавиатуре.
- Shift – если в момент активации события одновременно нажимается кнопка Shift.
- Double – двойная активация события.
- Triple – тройная активация события
События могут быть следующих типов:
- ButtonPress или Button – это те события, активация которых осуществляется, когда человек нажимает кнопку мыши.
- ButtonRelease – аналогичное, на первый взгляд, предыдущему событие за тем лишь исключением, что его обработка осуществляется не в момент нажатия кнопки, а в момент, когда пользователь отпускает кнопку мыши. Разницу между ними можно заметить, лишь если понаблюдать за каждым из вариантов. Если используется только один из этих обработчиков, то разницу можно будет и не заметить.
- Enter – событие, которое активируется при перемещении курсора мыши на виджет.
- Leave – событие, обратное предыдущему. Активируется, если мышь покидает границы элемента.
- FocusIn – событие, активация которого происходит при попадании фокуса ввода в текстовое поле.
- FocusOut – аналогично предыдущим, это обратное по значению событие. Оно активируется, когда фокус исчезает из поля ввода.
- KeyPress или Key – событие для нажатия кнопки.
- KeyRelease – событие для отпущенной кнопки.
- Motion – событие при перемещении мыши.
Еще параметр – это detail. Его использование необязательно. С его помощью можно конкретизировать событие. Допустим, человек кликнул левой кнопкой мыши, и получил результат. И щелкнул правой кнопкой. И также получил результат. А что, если нам надо сделать так, чтобы обработчик события вызывался исключительно при нажатии правой кнопки мыши? В этом случае необходимо передать этому параметру значение 3.
Кстати, можно также настроить отдельные обработчики событий для левой и средней кнопок. Для этого необходимо использовать значения 1 и 2 соответственно.
Если необходимо передать параметры события, то также используется функция callback. Ее работу также проще всего продемонстрировать для событий мыши.
Так, чтобы передать текущее положение мыши в пикселях, необходимо использовать атрибуты x и y, которые обозначают горизонтальную и вертикальную оси соответственно.
Также можно поставить координаты относительно верхнего левого угла экрана. Для этого используются x_root и y_root. Если же необходимо получить номер кнопки мыши, которая была нажата, используется атрибут num. Числа указаны выше.
Хорошо, а как нам получить параметры события, связанного с клавиатурой. Для этого используются такие атрибуты:
- char. Это та клавиша, которая была нажата, которая передается в строчном формате.
- keysym. Это нажатая пользователем клавиша, которая передается в виде символа, изображенном на самой клавише.
- keycode. Это код, соответствующий клавише, которая была нажата.
Независимо от того, какого типа событие в вашем случае, у него есть атрибут widget, который делает отсылку к тому элементу, который сгенерировал событие, а также type, определяющий тип события.
Если используется функция callback, то рекомендуется всегда определять для нее метод. Дело в том, что ссылка на объект будет всегда, и через нее очень легко будет получить доступ к необходимому атрибуту элемента.
Параметр add может содержать пустую строку типа “», чтобы заменить функцию callback при условии, что перед этим была привязка. Также можно использовать знак +, чтобы добавить функцию обратного вызова и сохранить старые.
Кроме приведенных выше типов событий есть и другие. Но они заслуживают отдельного рассмотрения. Приведем пару примеров для наглядности:
- <Destroy>. Это событие означает уничтожение элемента.
- <Configure>. А это используется, если надо изменить размер или положение определенного элемента.
Чтобы ознакомиться с полным перечнем событий, необходимо изучить документацию Tcl/Tk.
Как настроить иконки, названия и размер основного окна
Основное отличие Tk от всех остальных виджетов в том, как осуществляется его настройка. Например, можно настроить иконку, используя метод iconbitmap(), в качестве аргумента которого использовать ссылку на .ico файл. Он должен располагаться в той же папке, что и скрипт.
Кроме замены иконок, можно также осуществлять настройку названия окна. Для этого используется метод title(), в качестве аргумента которого указывается сам заголовок, оформленный в виде строки.
Ну и, наконец, третий метод, с помощью которого мы можем задать размеры окна, является одновременно самым сложным из всех перечисленных выше. Называется он geometry() и принимает один аргумент в виде строки. Но чтобы метод работал, он должен соответствовать шаблону {width}x{height}+{of set_x}+{of set_y}.
Все мы знаем, что в любой программе количество окон может быть больше, чем одно. В этом случае необходимо подключить класс Toplevel и обратиться к нему, чтобы получить все требуемые для их управления методы.
А чтобы перевести программу в полноэкранный режим, вместо метода geometry() используется state(“zoomed”). Обратите внимание, что состояние должно быть указано именно, как zoomed.