python到link两块动态有没有什么方法

Is there any method in python to link two blocks dynamically

我想画一些积木,然后用箭头把它们连接起来。

我做到了,但是如果我移动方块的坐标,我还需要改变箭头坐标。 有什么绑定方法吗,比如我移动方块位置连接箭头也会自动调整?

你能推荐 python 中的任何其他方法吗?

from tkinter import * 

top = Tk()  
top.geometry("800x600")  
 
#creating a simple canvas  
a = Canvas(top,bg = "White",height = "515", width = "1000")
a.create_rectangle(430, 255, 550, 275,fill="White")
a.create_text(490,265,text="School",fill="black",font=('Helvetica 8 bold'))    
a.create_rectangle(430, 205, 480, 225,fill="White")
a.create_text(455,215,text="Boys",fill="black",font=('Helvetica 8 bold'))    
a.create_rectangle(480, 160, 540, 180,fill="White")
a.create_text(510,170,text="Girls",fill="black",font=('Helvetica 8 bold'))    


#School to Boys
a.create_line(450, 225, 450, 255, arrow= BOTH)
#School to COM
a.create_line(510, 180, 510, 255, arrow= BOTH)   
a.pack(expand=True) 
top.mainloop()

不,tkinter 没有给 link 块任何方法。但是,您可以自己创建它们。首先,创建一个矩形和文本并为它们分配相同的标签(注意:每个块必须有一个唯一的标签)。

现在,如果您想使用鼠标移动方块,您必须使用canvas.find_withtag("current") 获取当前选定的方块,并使用canvas.move(tagorid, x, y) 移动方块。移动后使用 widget.generate_event() 生成自定义虚拟事件。

您现在必须使用 canvas.tag_bind(unqiue_tagn, "<<customevent>>", update_pos) 在事件生成时调用 update_pos 函数,update_pos 应该更新连接位置。

这是示例代码。

import tkinter as tk


class NodeScene(tk.Canvas):

    def __init__(self, *args, **kwargs):
        super(NodeScene, self).__init__(*args, **kwargs)

        self.bind("<Button-1>", self.click_pos)
        self.bind("<B1-Motion>", self.selected_item)

        self.prev_x, self.prev_y = 0, 0

    def click_pos(self, event):
        self.prev_x, self.prev_y = event.x, event.y

    def selected_item(self, event):

        _current = self.find_withtag("current")

        assoc_tags = self.itemcget(_current, "tags").split(" ")[0]
   
        if _current and "node" in assoc_tags:
            new_pos_x, new_pos_y = event.x - self.prev_x, event.y - self.prev_y
            self.move(assoc_tags, new_pos_x, new_pos_y)
            
            self.event_generate("<<moved>>", when="tail")
            self.prev_x, self.prev_y = event.x, event.y


class Node:

    def __init__(self, canvas: tk.Canvas, text: str, pos=(50, 50)):
        
        self.tag_id = f"node{id(self)}"
        self.canvas = canvas
        
        self.c_rect = self.canvas.create_rectangle(0, 0, 0, 0, fill="white", tags=(self.tag_id))
        c_text = self.canvas.create_text(*pos, text=text, fill="black", font=("Helvetica 8 bold"), tags=(self.tag_id))
       
        padding = 10
        text_rect = list(self.canvas.bbox(c_text))
        
        text_rect[0] -= padding
        text_rect[1] -= padding
        text_rect[2] += padding
        text_rect[3] += padding

        self.canvas.coords(self.c_rect, *text_rect)

    def bbox(self):
        return self.canvas.bbox(self.c_rect)

    def top(self):
        bbox = self.bbox()
        return (bbox[2] + bbox[0]) / 2, bbox[1]
    
    def bottom(self):
        bbox = self.bbox()
        return (bbox[2] + bbox[0]) / 2, bbox[3]


class Connection:

    def __init__(self, canvas, node1: Node, node2: Node, pos_x):  # pos_x is the offset from center

        self.node1 = node1
        self.node2 = node2
        self.pos_x_offset = pos_x
        self.canvas = canvas

        self.connection_id = self.canvas.create_line(0, 0, 0, 0, arrow= tk.BOTH)

        self.canvas.tag_bind(self.node1.tag_id, "<<moved>>", self.update_conn_pos, add="+")
        self.canvas.tag_bind(self.node2.tag_id, "<<moved>>", self.update_conn_pos, add="+")
        
        self.update_conn_pos()

    def update_conn_pos(self, event=None):
        """ updates the connection position """
    
        node1_btm = self.node1.bottom()
        node2_top = list(self.node2.top()) 
        node2_top[0] += self.pos_x_offset

        self.canvas.coords(self.connection_id, *node1_btm, *node2_top)


root = tk.Tk()

canvas = NodeScene(root)
canvas.pack(expand=True, fill="both")

node = Node(canvas, "School", pos=(100, 150))
node1 = Node(canvas, "boys", pos=(80, 80))
node2 = Node(canvas, "girls", pos=(120, 30))

connection = Connection(canvas, node1, node, -20)
connection2 = Connection(canvas, node2, node, 20)

root.mainloop()