1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| import Tkinter as tk
class Node:
_instances = {}
@classmethod
def create(cls, x, y, radius=25, color='grey'):
node = Node(x, y, radius, color)
cls._instances[node.iid] = node
return node
@classmethod
def get(cls, iid):
return cls._instances.get(iid, None)
def __init__(self, x, y, radius, color):
x0, y0, x1, y1 = x - radius, y - radius, x+radius, y+radius
self.iid = canvas.create_oval(
x0, y0, x1, y1,
fill=color,
tags='node',
activeoutline='green',
activewidth=3)
self.center = x, y
self.radius = radius
self.edges = []
def add_edge(self, node):
x0, y0 = self.center
x1, y1 = node.center
iid = canvas.create_line(x0, y0, x1, y1, tags='edge')
canvas.lower(iid, 'node')
self.edges.append(iid)
node.edges.append(iid)
def moveto(self, x, y):
cx, cy = self.center
for iid in self.edges:
x0, y0, x1, y1 = canvas.coords(iid)
if (cx, cy) == (x0, y0):
coords = x, y, x1, y1
elif (cx, cy) == (x1, y1):
coords = x0, y0, x, y
else:
raise ValueError('center mismatch with edge coords')
canvas.coords(iid, *coords)
canvas.move(self.iid, x - cx, y - cy)
self.center = x, y
bound_function = None
def on_b1_press(event):
global bound_function
iid = canvas.find_withtag('current')[0]
node = Node.get(iid)
bound_function = canvas.bind('<Motion>', lambda e: node.moveto(e.x, e.y))
def on_b1_release(event):
global bound_function
if bound_function:
canvas.unbind('<Motion>', bound_function)
bound_function = None
if __name__ == '__main__':
root = tk.Tk()
canvas = tk.Canvas(width=500, height=500)
canvas.pack(fill='both', expand=1)
canvas.tag_bind('node', '<ButtonPress-1>', on_b1_press)
canvas.tag_bind('node', '<ButtonRelease-1>', on_b1_release)
n0 = Node.create(150, 50, color='red')
n1 = Node.create(150, 250, color='blue')
n2 = Node.create(350, 50, color='green')
n0.add_edge(n1)
n2.add_edge(n1)
tk.mainloop() |