📄 arrow.py
字号:
from Tkinter import *
class ArrowEditor:
def __init__(self, master, width=500, height=350):
Label(master, text="This widget allows you to experiment "
"with different widths and arrowhead shapes for lines "
"in canvases. To change the line width or the shape "
"of the arrowhead, drag any of the three boxes "
"attached to the oversized arrow. The arrows on the "
"right give examples at normal scale. The text at "
"the bottom shows the configuration options as you'd "
"enter them for a canvas line item.",
wraplength="5i", justify=LEFT).pack(side=TOP)
self.control=Frame(master)
self.control.pack(side=BOTTOM, fill=X, padx=2)
Button(self.control, text='Quit', command=master.quit).pack()
self.canvas = Canvas(master, width=width, height=height,
relief=SUNKEN, borderwidth=2)
self.canvas.pack(expand=YES, fill=BOTH)
self.a = 8 # Setup default values
self.b = 10
self.c = 3
self.width = 2
self.motionProc = None
self.x1 = 40
self.x2 = 350
self.y = 150
self.smallTips = (5,5,2)
self.bigLine = 'SkyBlue2'
self.boxFill = ''
self.activeFill = 'red'
self.arrowSetup() # Draw default arrow
self.canvas.tag_bind('box', '<Enter>', lambda e, s=self:
s.canvas.itemconfig(CURRENT, fill='red'))
self.canvas.tag_bind('box', '<Leave>', lambda e, s=self:
s.canvas.itemconfig(CURRENT, fill=''))
self.canvas.tag_bind('box1', '<1>', lambda e, s=self:
s.motion(s.arrowMove1))
self.canvas.tag_bind('box2', '<1>', lambda e, s=self:
s.motion(s.arrowMove2) )
self.canvas.tag_bind('box3', '<1>', lambda e, s=self:
s.motion(s.arrowMove3))
self.canvas.tag_bind('box', '<B1-Motion>', lambda e,
s=self: s.motionProc(e))
self.canvas.bind('<Any-ButtonRelease-1>', lambda e,
s=self: s.arrowSetup())
def motion(self, func):
self.motionProc = func
def arrowMove1(self, event):
newA = (self.x2+5-int(self.canvas.canvasx(event.x)))/10
if newA < 0: newA = 0
if newA > 25: newA = 25
if newA != self.a:
self.canvas.move("box1", 10*(self.a-newA), 0)
self.a = newA
def arrowMove2(self, event):
newB = (self.x2+5-int(self.canvas.canvasx(event.x)))/10
if newB < 0: newB = 0
if newB > 25: newB = 25
newC = (self.y+5-int(self.canvas.canvasx(event.y)+ \
5*self.width))/10
if newC < 0: newC = 0
if newC > 20: newC = 20
if newB != self.b or newC != self.c:
self.canvas.move("box2", 10*(self.b-newB),
10*(self.c-newC))
self.b = newB
self.c = newC
def arrowMove3(self, event):
newW = (self.y+2-int(self.canvas.canvasx(event.y)))/5
if newW < 0: newW = 0
if newW > 20: newW = 20
if newW != self.width:
self.canvas.move("box3", 0, 5*(self.width-newW))
self.width = newW
def arrowSetup(self):
tags = self.canvas.gettags(CURRENT)
cur = None
if 'box' in tags:
for tag in tags:
if len(tag) == 4 and tag[:3] == 'box':
cur = tag
break
self.canvas.delete(ALL)
self.canvas.create_line(self.x1, self.y, self.x2, self.y,
width=10*self.width,
arrowshape=(10*self.a, 10*self.b, 10*self.c),
arrow='last', fill=self.bigLine)
xtip = self.x2-10*self.b
deltaY = 10*self.c+5*self.width
self.canvas.create_line(self.x2, self.y, xtip, self.y+deltaY,
self.x2-10*self.a, self.y, xtip, self.y-deltaY,
self.x2, self.y, width=2, capstyle='round',
joinstyle='round')
self.canvas.create_rectangle(self.x2-10*self.a-5, self.y-5,
self.x2-10*self.a+5, self.y+5,
fill=self.boxFill, outline='black',
tags=('box1', 'box'))
self.canvas.create_rectangle(xtip-5, self.y-deltaY-5,
xtip+5, self.y-deltaY+5,
fill=self.boxFill, outline='black',
tags=('box2', 'box'))
self.canvas.create_rectangle(self.x1-5,
self.y-5*self.width-5, self.x1+5,
self.y-5*self.width+5, fill=self.boxFill,
outline='black', tags=('box3', 'box'))
if cur:
self.canvas.itemconfig(cur, fill=self.activeFill)
self.canvas.create_line(self.x2+50, 0, self.x2+50,
1000, width=2)
tmp = self.x2+100
self.canvas.create_line(tmp, self.y-125, tmp, self.y-75,
width=self.width, arrow='both',
arrowshape=(self.a, self.b, self.c))
self.canvas.create_line(tmp-25, self.y, tmp+25, self.y,
width=self.width, arrow='both',
arrowshape=(self.a, self.b, self.c))
self.canvas.create_line(tmp-25, self.y+75, tmp+25, self.y+125,
width=self.width, arrow='both',
arrowshape=(self.a, self.b, self.c))
tmp = self.x2+10
self.canvas.create_line(tmp, self.y-5*self.width, tmp,
self.y-deltaY, arrow='both', arrowshape=self.smallTips)
self.canvas.create_text(self.x2+15, self.y-deltaY+5*self.c,
text=self.c, anchor=W)
tmp = self.x1-10
self.canvas.create_line(tmp, self.y-5*self.width, tmp,
self.y+5*self.width, arrow='both',
arrowshape=self.smallTips)
self.canvas.create_text(self.x1-15, self.y,
text=self.width, anchor=E)
tmp = self.y+5*self.width+10*self.c+10
self.canvas.create_line(self.x2-10*self.a, tmp, self.x2, tmp,
arrow='both', arrowshape=self.smallTips)
self.canvas.create_text(self.x2-5*self.a, tmp+5,
text=self.a, anchor=N)
tmp = tmp+25
self.canvas.create_line(self.x2-10*self.b, tmp, self.x2, tmp,
arrow='both', arrowshape=self.smallTips)
self.canvas.create_text(self.x2-5*self.b, tmp+5,
text=self.b, anchor=N)
self.canvas.create_text(self.x1, 310, text="width=%d" % \
self.width, anchor=W, font=('Verdana', 18))
self.canvas.create_text(self.x1, 330,
text="arrowshape=(%d,%d,%d)" % \
(self.a, self.b, self.c),
anchor=W, font=('Verdana', 18))
if __name__ == '__main__':
root = Tk()
root.option_add('*Font', 'Verdana 10')
root.title('Arrow Editor')
arrow = ArrowEditor(root)
root.mainloop()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -