用Python实现win10画图程序拖动鼠标画各种形状多边形功能

win10画图程序在工具栏中有许多按钮,按钮显示的图形就是各种不同形状的多边形,见下图。单击选中某按钮,就能拖动鼠标画这种形状多边形。本文介绍用Python实现win10画图程序这个功能的方法。
在这里插入图片描述
所谓拖动鼠标画各种形状多边形,是在鼠标左键按下时,保存被点击处鼠标坐标为A,在画这个多边形期间A一直不变。在鼠标左键按下并移动时,得到鼠标当前坐标为B,计算机要以坐标A和B为变量,经过某公式计算得到多边形各点坐标,画出多边形。每次鼠标移动,都要删除前边所画的多边形,画出新多边形。鼠标抬起,拖动画多边形结束。这就要求编写一段程序,给定Canvas上两点坐标,能画出指定多边形。
坐标A和B可看作矩形左上角和右下角的坐标,多边形要画在这个矩形中。这个矩形如下图,左上角坐标为(x0,y0),右下角坐标为(x1,y1),矩形宽w=(x1-x0),矩形高h=(y1-y0)。矩形中的所有点坐标都可用公式(x,y)=(x0+m*w,y0+n*h)计算得到,m和n取值范围为0-1。公式中计算多边形不同顶点坐标的m和n都不相同,可把计算多边形不同顶点坐标的m和n保存到列表中,格式为:a=[[m1,n1],[m2,n2],…],列表长度为多边形的顶点数,这个列表要预先完成,不同图形有不同的列表值,即列表定义了某种形状多边形。可用字典组成多边形图形库,格式为:{图形名:该图形列表,…}。
以画菱形为例,菱形4个顶点是A、B、C、D。A点坐标=(x0+0.5w,y0+0*h);B点坐标=(x0+1*w,y0+0.5h),C点坐标=(x0+0.5w,y0+1*h),D点坐标=(x0+0*w,y0+0.5*h)。把点A、B、C、D的m和n用列表记录:a=[[0.5,0],[1,0.5],[0.5,1],[0,0.5]]。
在这里插入图片描述
由此可定义一个方法drawPolygon,根据给定列表和Canvas上两点坐标,即方法参数(x,y,x1,y1),可画出指定形状的图形。选择列表a,但(x,y,x1,y1)不同,画出的虽然都是菱形,但菱形的宽和高不相同。不选择列表a,而选择其它列表,画出的就不是菱形而是其它类图形,例如,选择六边形的列表,画出不同形状的六边形。方法定义如下:

a=[[0.5,0],[1,0.5],[0.5,1],[0,0.5]]
def drawPolygon(x,y,x1,y1):    #(x,y)是矩形左上角坐标,(x1,y1)是右下角坐标
    w,h=x1-x,y1-y
    points=[]
    for m,n in a:
        points.append([x+m*w,y+n*h])
    cv.create_polygon(points, outline="green",fill="yellow",tags=('L'))

为了实现拖动鼠标画多边形,首先要为事件绑定事件函数如下:

cv.bind("<ButtonPress-1>",StartMove)  #绑定鼠标左键按下事件
cv.bind("<ButtonRelease-1>",StopMove) #绑定鼠标左键松开事件
cv.bind("<B1-Motion>", OnMotion)      #绑定鼠标左键被按下时移动鼠标事件

在鼠标左键按下事件函数StartMove中,保存点击处鼠标坐标为矩形左上角坐标,该坐标在画多边形期间一直不变。

first_x,first_y = event.x,event.y

在鼠标左键按下并移动事件函数OnMotion中,先删除前边画的多边形,然后在新的位置画多边形。

cv.delete('L')
drawPolygon(first_x,first_y,event.x,event.y)   #(event.x,event.y)鼠标移动坐标

在鼠标左键抬起事件函数StopMove中,先删除前边画的多边形,然后在新的位置画多边形。还必须删除tags为’L’的实例中这个为’L’的tag。因重新画新的多边形时,还要用令tags=(‘L’),不删除就会同时操作以前所画的多边形。

cv.delete('L')
drawPolygon(first_x,first_y,event.x,event.y)
cv.dtag('L','L')

完整代码如下:

import tkinter as tk
root = tk.Tk()
root.geometry('300x300')
cv = tk.Canvas(root, height=300, width=300,bg='silver')
cv.pack()
a=[[0.5,0],[1,0.5],[0.5,1],[0,0.5]]
def drawPolygon(x,y,x1,y1):
    w,h=x1-x,y1-y
    points=[]
    for m,n in a:
        points.append([x+m*w,y+n*h])
    cv.create_polygon(points, outline = "green", fill = "yellow",tags=('L'))
def StartMove(event):    
    global first_x,first_y
    first_x,first_y = event.x,event.y    
def StopMove(event):
    global first_x,first_x
    cv.delete('L')
    drawPolygon(first_x,first_y,event.x,event.y)
    cv.dtag('L','L')    
def OnMotion(event):
    global first_x,first_x
    cv.delete('L')
    drawPolygon(first_x,first_y,event.x,event.y)
cv.bind("<ButtonPress-1>",StartMove)  #绑定鼠标左键按下事件
cv.bind("<ButtonRelease-1>",StopMove) #绑定鼠标左键松开事件
cv.bind("<B1-Motion>", OnMotion)      #绑定鼠标左键被按下时移动鼠标事件
root.mainloop()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值