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()
我想画一些积木,然后用箭头把它们连接起来。
我做到了,但是如果我移动方块的坐标,我还需要改变箭头坐标。 有什么绑定方法吗,比如我移动方块位置连接箭头也会自动调整?
你能推荐 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()