Рассмотрим такой пример:
from tkinter import * from random import randrange as rnd, choice import time root = Tk() root.geometry('800x600') canv = Canvas(root,bg='white') canv.pack(fill=BOTH,expand=1) colors = ['red', 'orange', 'yellow', 'green', 'blue'] def paint(event): canv.delete(ALL) x = event.x y = event.y r = rnd(10,70) color = choice(colors) canv.create_oval(x-r,y-r,x+r,y+r,fill = color) canv.bind('<Button-1>',paint) mainloop()
Что происходит?
canv.bind('<Button-1>',paint)
связывает событие «Button-1», т.е. щелчок левой кнопкой мыши на Canvas и вызов функции paint, т.е. теперь paint будет вызываться когда мы будем щелкать мышкой в разных местах Canvas, а event.x, event.y поможет нам узнать координаты щелчка.
Измените одну строку, но не запускайте сразу. Motion – это событие, которое возникает при перемещении мыши. Как вы думаете, что произойдет? Проверьте ваше предположение, запустив программу.
canv.bind('<Motion>',paint)
А теперь удалите canv.delete(ALL)
. И опять подумайте, к чему это должно привести и только потом запускайте.
Еще немного поиграем с мышью: в следующем примере будет очень много нового, понять будет непросто. Однако, это забавно и стоит того, чтобы попробовать прямо сейчас.
# -*- coding: utf-8 -*- from tkinter import * from random import randrange as rnd import time root = Tk() root.geometry('800x600') canv = Canvas(root,bg='white') canv.pack(fill=BOTH,expand=1) tail = [] # создать список (пока пустой) def paint(event): global tail # если эту строку убрать, то значение tail не будет сохраняться между вызовами функции x = event.x y = event.y tail.append((x,y)) # добавить в список очередную пару координат. Если бы мы добавляли одно значение, то обошлись бы без второй пары скобок. tail = tail[-20:] # оставить в списке только последние 20 элементов r = 20 canv.delete(ALL) # удалить все с экрана for x,y in tail: # перебрать весь список и для каждой пары x,y нарисовать круг canv.create_oval(x-r,y-r,x+r,y+r,fill='lightgreen') canv.bind('<Motion>',paint) mainloop()
Черную окантовку окружности лучше убрать:
canv.create_oval(x-r,y-r,x+r,y+r,fill='lightgreen',width=0)
И еще один прием:
# -*- coding: utf-8 -*- from tkinter import * from random import randrange as rnd import time root = Tk() root.geometry('800x600') canv = Canvas(root,bg='white') canv.pack(fill=BOTH,expand=1) tail = [] # создать список (пока пустой) def paint(event): global tail # если эту строку убрать, то значение tail не будет сохраняться между вызовами функции x = event.x y = event.y tail.append((x,y)) # добавить в список очередную пару координат. Если бы мы добавляли одно значение, то обошлись бы без второй пары скобок. tail = tail[-20:] # оставить в списке только последние 20 элементов r = 2 canv.delete(ALL) # удалить все с экрана for x,y in tail: # перебрать весь список и для каждой пары x,y нарисовать круг r += 1 canv.create_oval(x-r,y-r,x+r,y+r,fill='lightgreen',width=0) canv.bind('<Motion>',paint) mainloop()
Наоборот тоже забавно:
r = 30 canv.delete(ALL) # удалить все с экрана for x,y in tail: # перебрать весь список и для каждой пары x,y нарисовать круг r -= 1 canv.create_oval(x-r,y-r,x+r,y+r,fill='lightgreen',width=0)
global
? (см. справочник – область видимости)2. Как работает
tail = tail[-20:]
? (см. справочник — списки)
Если вам не нравится, что изменения на экране происходят только после того, как будет перемещена мышь, то посмотрите на другой вариант: мышь оставляет след (без задержки)