~nch/glue

cb6e03c825517561514fc8b4a9c5eb07479ce995 — nc 1 year, 4 months ago
add draggable labels
1 files changed, 79 insertions(+), 0 deletions(-)

A glue.py
A  => glue.py +79 -0
@@ 1,79 @@
import tkinter as tk
import tkinter.dnd as dnd # type: ignore

class Node:
    def __init__(self, canvas, label, x=10, y=10):
        #tk.Frame.__init__(self, parent, background="#888", width=100, height=100)

        self.label = tk.Label(canvas, text=label, borderwidth=2)
        self.id = canvas.create_window(x, y, window=self.label, anchor='nw')
        self.canvas = canvas
        self.label.bind('<ButtonPress>', self.press)

    def attach(self, canvas, x, y):
        self.canvas.coords(self.id, x, y)

    def press(self, event):
        if dnd.dnd_start(self, event):
            self.x_off = event.x
            self.y_off = event.y

            self.x_orig, self.y_orig = self.canvas.coords(self.id)

    def where(self, canvas, event):
        # where the corner of the canvas is relative to the screen:
        x_org = canvas.winfo_rootx()
        y_org = canvas.winfo_rooty()
        # where the pointer is relative to the canvas widget:
        x = event.x_root - x_org
        y = event.y_root - y_org
        # compensate for initial pointer offset
        return x - self.x_off, y - self.y_off

    def move(self, event):
        x, y = self.where(self.canvas, event)
        self.canvas.coords(self.id, x, y)

    def putback(self):
        self.canvas.coords(self.id, self.x_orig, self.y_orig)

    def dnd_end(self, target, event):
        pass

class NodeCanvas:
    def __init__(self, root):
        self.top = root
        self.canvas = tk.Canvas(self.top, width=800, height=600, background='#444')
        self.canvas.pack(fill='both', expand=1)
        self.canvas.dnd_accept = self.dnd_accept

    def dnd_accept(self, source, event):
        return self

    def dnd_enter(self, source, event):
        x, y = source.where(self.canvas, event)
        x1, y1, x2, y2 = source.canvas.bbox(source.id)

        dx, dy = x2-x1, y2-y1
        self.dndid = self.canvas.create_rectangle(x, y, x+dx, y+dx)
        self.dnd_motion(source, event)

    def dnd_motion(self, source, event):
        x, y = source.where(self.canvas, event)
        x1, y1, x2, y2 = self.canvas.bbox(self.dndid)
        self.canvas.move(self.dndid, x-x1, y-y1)

    def dnd_leave(self, source, event):
        self.canvas.delete(self.dndid)
        self.dndid = None

    def dnd_commit(self, source, event):
        self.dnd_leave(source, event)
        x, y = source.where(self.canvas, event)
        source.attach(self.canvas, x, y)

root = tk.Tk()
root.geometry("+1+1")
nodes = NodeCanvas(root)
n = Node(nodes.canvas, 'blah')
root.mainloop()