views:

115

answers:

2

I am currently writing a fsm editor with tkinter. But, I stuck on connecting two states. I have two questions:

1) How can make the transition arrow growable according to mouse movement?

2) How can I stick the starting point of the arrow on a state and the end point of the arrow on another state?

PS. Do you think the documentation of tkinter is good enough?

+2  A: 

Tkinter is perfectly fine for this sort of application. In the past I've worked on tools that were boxes connected with arrows that stayed connected as you move the boxes around (which is what I think you are asking about). Don't let people who don't know much about Tkinter sway you -- it's a perfectly fine toolkit and the canvas is very flexible.

The solution to your problem is simple math. You merely need to compute the coordinates of the edges or corners of boxes to know where to anchor your arrows. To make it "grow" as you say, simply make a binding on mouse movements and update the coordinates appropriately.

To make the line growable all you have to do is adjust the coordinates of the line each time the mouse moves. The easiest thing to do is make liberal use of canvas tags. With the tags you can know which arrows connect to which boxes so that when you move the box you adjust the coordinates of any arrows that point to or from it.

Bryan Oakley
+2  A: 

My tkinter skills are pretty green, but here's a somewhat poorly coded example that shows the concept. Basically, use tags to associate lines with boxes, and simply adjust the coordinates appropriately when the user moves the mouse.

Run the example, then click and drag from within the beige box.j

Of course, for production code you need to make a more general solution, but hopefully this shows you how easy it is to create a box with arrows that adjust as you move the box around.

from Tkinter import *

class CanvasDemo(Frame):
    def __init__(self, width=200, height=200):
        Frame.__init__(self, root)
        self.canvas = Canvas(self)
        self.canvas.pack(fill="both", expand="1")
        self.canvas.create_rectangle(50, 25, 150, 75, fill="bisque", tags="r1")
        self.canvas.create_line(0,0, 50, 25, arrow="last", tags="to_r1")
        self.canvas.bind("<B1-Motion>", self.move_box)
        self.canvas.bind("<ButtonPress-1>", self.start_move)

    def move_box(self, event):
        deltax = event.x - self.x
        deltay = event.y - self.y
        self.canvas.move("r1", deltax, deltay)
        coords = self.canvas.coords("to_r1")
        coords[2] += deltax
        coords[3] += deltay
        self.canvas.coords("to_r1", *coords)
        self.x = event.x
        self.y = event.y

    def start_move(self, event):
        self.x = event.x
        self.y = event.y

root = Tk()
canvas = CanvasDemo(root)
canvas.pack()
mainloop()
Bryan Oakley
good example.. at least gave me the idea;) thanks!
israkir