本程序用36条Python语句实现在Canvas上用拖动鼠标方法画直线、矩形和椭圆(圆)这3种基本图形,是用Python实现win10的画图程序的相应功能。win10的画图程序除了能画直线、矩形和椭圆(圆)这3种基本图形,还可以画其它复杂图形,将在另一篇博文介绍实现画其它复杂图形的方法。现以画椭圆(圆)为例说明实现基本思路。首先为事件绑定事件函数如下:
cv.bind("<ButtonPress-1>",StartMove) #绑定鼠标左键按下事件
cv.bind("<ButtonRelease-1>",StopMove) #绑定鼠标左键松开事件
cv.bind("<B1-Motion>", OnMotion) #绑定鼠标左键被按下时移动鼠标事件
在鼠标左键按下事件函数StartMove中,首先保存点击处鼠标坐标为矩形左上角坐标,该坐标在画圆期间一直不变。然后创建一个小圆。cv是Canvas实例。注意tags=(‘L’),通过它能操作这个圆。
first_x,first_y = event.x,event.y #(event.x,event.y)鼠标单击处坐标
cv.create_oval(event.x,event.y,event.x+2,event.y+2,tags=('L'))
在鼠标左键按下并移动事件函数OnMotion中,用Canvas方法coords移动、变形、放大或缩小这个矩形。方法coords功能是按照指定左上角和右下角坐标的矩形重画圆。请注意,是通过tags=(‘L’)重画这个圆。如tags=(‘L’)代表一个矩形,那么就重画矩形,如代表一条直线,就重画直线。换句话讲,无论在事件函数StartMove中创建的是直线、矩形或椭圆(圆),只要其tags=(‘L’),下边语句都能完成对这个图形的移动、变形、放大或缩小。
cv.coords('L',first_x,first_y,event.x,event.y)
在鼠标左键抬起事件函数StopMove中,固定图形,还必须删除tags为’L’的实例中这个为’L’的tag。因重新创建新的直线、矩形或椭圆(圆)时,还要用令tags=(‘L’),不删除就会同时操作旧的图形。
cv.coords('L',first_x,first_y,event.x,event.y)
cv.dtag('L','L')
具体代码如下:
import tkinter as tk
root = tk.Tk()
root.geometry('300x410')
cv = tk.Canvas(root, height=300, width=300,bg='silver')
cv.pack()
def StartMove(event):
global first_x,first_y
if var.get()=='stop':
return
first_x,first_y = event.x,event.y
if var.get()=='line':
cv.create_line(event.x,event.y,event.x+2,event.y+2,tags=('L'))
elif var.get()=='rectangle':
cv.create_rectangle(event.x,event.y,event.x+2,event.y+2,tags=('L'))
elif var.get()=='oval':
cv.create_oval(event.x,event.y,event.x+2,event.y+2,tags=('L'))
def StopMove(event):
global first_x,first_x
if var.get()=='stop':
return
cv.coords('L',first_x,first_y,event.x,event.y)
if ((abs(event.x-first_x)+abs(event.y-first_y))<6):#避免在窗体点一下,出一个点
cv.delete('L')
cv.dtag('L','L')
def OnMotion(event):
global first_x,first_x
if var.get()=='stop':
return
cv.coords('L',first_x,first_y,event.x,event.y)
var = tk.StringVar()
tk.Radiobutton(root,text = '线',variable=var,value = 'line').pack()
tk.Radiobutton(root,text = '矩形',variable=var,value = 'rectangle').pack()
tk.Radiobutton(root,text = '圆',variable=var,value = 'oval').pack()
tk.Radiobutton(root,text = '停止画图',variable=var,value = 'stop').pack()
cv.bind("<ButtonPress-1>",StartMove) #绑定鼠标左键按下事件
cv.bind("<ButtonRelease-1>",StopMove) #绑定鼠标左键松开事件
cv.bind("<B1-Motion>", OnMotion) #绑定鼠标左键被按下时移动鼠标事件
root.mainloop()