python - 如何通过 python Tkinter 绘制智能拖放折线?
问题描述
我做了一个类来创建一条由线条组成的多段线,可以拖放。但是有以下两个问题:
如果有一种聪明的方法可以让折线在我移动时自动绕过对象(例如矩形)?
如果有任何聪明的方法来选择一条线并改变它的位置但保持所有线连接?
'''
from tkinter import *
class polyline:
def __init__(self,coords,canvas):
self.lines_list = []
self.canvas = canvas
self.selected = False
self.x_list,self.y_list = [],[]
for i in range(len(coords)-1):
self.lines_list.append(canvas.create_line(coords[i][0],coords[i][1], coords[i+1][0],coords[i+1][1]))
self.get_diagonal_coords()
def get_diagonal_coords(self):
self.x_list,self.y_list = [],[]
for i in self.lines_list:
coord = self.canvas.coords(i)
self.x_list.append(coord[0])
self.x_list.append(coord[2])
self.y_list.append(coord[1])
self.y_list.append(coord[3])
self.x_min = min(self.x_list)
self.y_min = min(self.y_list)
self.x_max = max(self.x_list)
self.y_max = max(self.y_list)
# print self.x_min,self.y_min
def move(self,move_dis):
self.get_diagonal_coords()
if self.x_min+move_dis[0] > 10 and self.y_min+move_dis[1] > 10 and self.x_max +move_dis[0]< canvas.winfo_width()-10 and self.y_max +move_dis[1]<canvas.winfo_height()-10:
for l in self.lines_list:
self.canvas.move(l,move_dis[0],move_dis[1])
# print self.x_list
def goto(self,destination):
self.get_diagonal_coords()
move_dis = (destination[0]-self.x_min,destination[1]-self.y_min)
self.move(move_dis)
self.get_diagonal_coords()
def select(self,coord):
self.get_diagonal_coords()
if coord[0]>self.x_min and coord[1]>self.y_min and coord[0]<self.x_max and coord[1]<self.y_max:
self.selected = True
return False
master = Tk()
canvas = Canvas(master, width=500, height=500)
canvas.pack()
# canvas.create_line(20,200,1,200)
global p
p = polyline([(10,200),(50,200),(50,300),(150,300),(150,360)],canvas)
def onclick_handler(event):
global p,start
start = (event.x-p.x_min, event.y-p.y_min)
pass
p.select((event.x, event.y))
def on_drag_motion(event):
global p,start
# print p.selected
if p.selected:
p.goto((event.x-start[0], event.y-start[1]))
def onrelease_handler(event):
global p
p.selected = False
canvas.bind("<Button-1>", onclick_handler)
canvas.bind("<B1-Motion>", on_drag_motion)
canvas.bind("<ButtonRelease-1>", onrelease_handler)
master.mainloop()
'''
解决方案
from tkinter import *
class draw_polyline:
def __init__(self,canvas,vertical):
self.lines_list = []
self.canvas = canvas
self.vertical = vertical
self.click_num = 0
pass
def start_draw_line(self,event):
x1,y1,x,y = event.x,event.y,event.x,event.y
if self.click_num == 0:
if self.vertical:
self.lines_list.append(self.canvas.create_line(x1,y1,x1,y))
else:
self.lines_list.append(self.canvas.create_line(x1,y1,x,y1))
else:
l = self.lines_list[self.click_num-1]
coords = self.canvas.coords(l)
if self.vertical:
self.lines_list.append(self.canvas.create_line(coords[2],coords[3],coords[2],y+5))
else:
self.lines_list.append(self.canvas.create_line(coords[2],coords[3],x+5,coords[3]))
canvas.bind("<B1-Motion>", self.move_and_draw)
canvas.bind("<ButtonRelease-1>", self.onrelease_handler)
def onrelease_handler(self,event):
self.vertical = not self.vertical
self.click_num+=1
def in_the_range(self,l,coord):
coords = self.canvas.coords(l)
x_min,x_max = min(coords[0],coords[2]),max(coords[0],coords[2])
y_min,y_max = min(coords[1],coords[3]),max(coords[1],coords[3])
x_in_range = coord[0]>x_min-3 and coord[0]<x_max+3
y_in_range = coord[1]>y_min-3 and coord[1]<y_max+3
return x_in_range and y_in_range
def move_and_draw(self,event):
if len(self.lines_list)>0:
l = self.lines_list[self.click_num]
coords = self.canvas.coords(l)
x1,y1,x,y = coords[0],coords[1],event.x,event.y
if self.vertical:
if y-y1<5:
y = int(y+5*abs(y-y1)/((y-y1)+1e-9))
self.canvas.coords(l,x1,y1,x1,y)
else:
if x-x1<5:
x = int(x+5*abs(x-x1)/((x-x1)+1e-9))
self.canvas.coords(l,x1,y1,x,y1)
def onclick_handler(self,event):
self.canvas.bind("<Button-1>", self.start_draw_line)
def start_draw(self):
self.canvas.bind("<Button-1>", self.start_draw_line)
master = Tk()
canvas = Canvas(master, width=500, height=500)
canvas.pack()
p = draw_polyline(canvas = canvas,vertical=True)
p.start_draw()
master.mainloop()
推荐阅读
- powershell - $c.length 只输出一吨,而不是长度
- if-statement - 将包含多行单元格的表格展开为完整表格
- java - 如何获取活动视图中蒙版下的裁剪图像的 x 和 y 坐标?
- angular8 - TypeError:reducerManager.addFeatures 不是函数
- github - 有没有办法通知 GitHub 用户我的一个存储库中的更新?
- asp.net - 在 asp.net 的更新面板中写入和读取 cookie
- sql - SQL 使用通配符替换列值
- python-3.x - 是否可以继承 setup() 和 tearDown() 方法?
- angular - 离子页面不显示后退按钮
- http - 更改标头 HTTP 服务器 [SharePoint Online]