События холстов

sobytiya holstov Экскурсия по tkinter, часть 2

Подобно виджетам Text и Listbox виджет Canvas не имеет параметра настройки command для назначения обработчика событий. Вместо этого программы, содержащие холсты, обычно используют другие виджеты (такие как кнопки с миниатюрами в примере 9.15) или низкоуровневый метод bind, чтобы установить обработчики щелчков мышью, нажатий клавиш и других событий (как в примере 9.14 реализации холста с прокруткой). Пример 9.16 берет за основу последний подход и демонстрирует, как привязать события самого холста, чтобы реализовать некоторые наиболее типичные операции рисования.

Пример 9.16. PP4E\Gui\Tour\canvasDraw.py

реализует возможность рисования эластичных фигур на холсте при перемещении указателя мыши с нажатой правой кнопкой; версии этого сценария, дополненные тегами и анимацией, вы найдете в файлах canvasDraw_tags*.py

from tkinter import * trace = False

class CanvasEventsDemo:

def __init__(self, parent=None):

canvas = Canvas(width=300, height=300, bg=’beige’)

canvas.pack()

canvas.bind(‘<ButtonPress-1>’, self.onStart) # щелчок

canvas.bind(‘<B1-Motion>’, self.onGrow) # и вытягивание canvas.bind(‘<Double-1>’, self.onClear) # удалить все canvas.bind(‘<ButtonPress-3>’, self.onMove) # перемещать последнюю self.canvas = canvas

self.drawn = None

self.kinds = [canvas.create_oval, canvas.create_rectangle]

def onStart(self, event):

self.shape = self.kinds[0]

self.kinds = self.kinds[1:] + self.kinds[:1] # начало вытягивания self.start = event

self.drawn = None

def onGrow(self, event): # удалить и перерисовать

canvas = event.widget

if self.drawn: canvas.delete(self.drawn)

objectId = self.shape(self.start.x, self.start.y, event.x, event.y) if trace: print(objectId)

self.drawn = objectId

def onClear(self, event):

event.widget.delete(‘all’) # использовать тег all

def onMove(self, event):

if self.drawn: # передвинуть в позицию

if trace: print(self.drawn) # щелчка

canvas = event.widget diffX, diffY = (event.x self.start.x), (event.y self.start.y) canvas.move(self.drawn, diffX, diffY) self.start = event

if __name__ == ‘__main__’:

CanvasEventsDemo() mainloop()

Этот сценарий перехватывает и обрабатывает три действия, выполняемые мышью:

Очистка холста

Чтобы удалить все имеющееся на холсте, сценарий привязывает событие двойного щелчка левой кнопкой к методу delete холста с тегом all — встроенным тегом, который автоматически ассоциируется с каждым объектом на экране. Обратите внимание, что доступ к виджету холста, на котором выполнен щелчок, осуществляется через объект события, передаваемый обработчику (он также доступен через self.canvas).

Вытягивание фигур

При нажатии левой кнопки мыши и перетаскивании (перемещении при нажатой кнопке) создается прямоугольник или овал. Этот прием часто называется вытягиванием фигуры — фигура увеличивается и сжимается как резиновая, и окончательный ее размер и положение определяются позицией указателя мыши, где будет отпущена кнопка мыши.

Чтобы выполнить такую работу с помощью tkinter, нужно всякий раз, когда возникает событие перетаскивания, стирать старую фигуру и рисовать новую. Обе операции, удаления и рисования, выполняются настолько быстро, что возникает эффект эластичного вытягивания. Конечно, чтобы начертить фигуру в соответствии с текущим положением указателя мыши, нужна начальная точка, а чтобы удалить фигуру перед тем, как вычерчивать новую, нужно запоминать идентификатор объекта, нарисованного последним. Здесь участвуют два события: исходное событие нажатия кнопки сохраняет начальные координаты (точнее, объект события нажатия кнопки, который содержит начальные координаты), а события перемещения указателя мыши стирают прежнюю фигуру и рисуют новую от начальных координат до новых координат мыши, сохраняя идентификатор нового объекта для операции стирания в следующем событии.

Перемещение объектов

При щелчке правой кнопкой мыши (кнопкой 3) сценарий сразу перемещает объект, нарисованный последним, в то место, где произведен щелчок. Аргумент события event дает координаты (X,Y) щелчка, из которых вычитаются начальные координаты последнего нарисованного объекта, чтобы получить смещения (X,Y), передаваемые методу move холста (напомню, что метод move ожидает получить смещения, а не координаты). Не следует забывать о необходимости сначала пересчитать координаты события, если холст прокручен.

В итоге после взаимодействия с пользователем получается окно, подобное изображенному на рис. 9.27. При вытягивании объектов сценарий поочередно вычерчивает овалы и прямоугольники. Установите в сценарии глобальную переменную trace и вы увидите в stdout идентификаторы новых объектов, вычерчиваемых при вытягивании и перемещении. Этот снимок экрана получен после вытягивания и перемещения нескольких объектов, что невозможно понять, только глядя на снимок — запустите пример на своем компьютере, чтобы лучше ощутить выполняемые им операции.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий