如何在tkinter中移动具有相同标记的单独项目?

时间:2018-05-24 14:53:41

标签: python tkinter

我试图创建一个程序,用户可以在其中添加某些逻辑门,并且可以单独移动。 我试图添加一个计数并连接标签,但它不起作用。 我的程序是我到目前为止所做的,即使在画布上添加相同的门,我也需要一些单独移动门的帮助。

from tkinter import *

canvas=Canvas(width=600,height=600)
canvas.grid()

def andGATE():
    canvas.create_line(150,50,150,150,width=5,tag="andgate")
    canvas.create_arc(150,50,200,150,start=90,extent=-180,width=5,fill="black",tag="andgate")



    canvas.create_line(150,75,120,75,width=5,tag="andgate")
    canvas.create_line(150,120,120,120,width=5,tag="andgate")
    canvas.create_line(200,100,250,100,width=5,tag="andgate")
    canvas.create_rectangle(150,50,180,150,width=5,fill="black",tag="andgate")
    canvas.tag_bind("andgate","<B1-Motion>",moveANDGate)

def gateSelected():
    sf=var.get()
    if sf=='AND':
        andGATE()

def moveANDGate(event):
    x=event.x
    y=event.y
    coords=canvas.coords("andgate")
    movex=x-coords[0]
    movey=y-coords[1]
    canvas.move("andgate",movex,movey)

root = Tk()
root.geometry("500x500")
var = StringVar(root)
var.set('AND')
choices = ['AND']
option = OptionMenu(root, var, *choices)
option.pack(side="left",padx=10,pady=10)
button = Button(root, text="Add Gate", command=gateSelected)
button.pack(side="left",padx=10,pady=10)
clearButton = Button(root,text="Clear",command=lambda:clearScreen())
clearButton.pack(side="left",padx=30,pady=10)
root.mainloop()

1 个答案:

答案 0 :(得分:1)

您需要为构成单个门的每个画布项集合使用唯一标记。然后,您可以使用该唯一标记将所有项目移动到一起。

为了简化实现,我将通过使用全局变量来说明每个新门的id。使用全局变量不是最好的解决方案,但它肯定是最简单的。

为了使这个答案变得简单,我们将为每个标签添加一个绑定,将标签传递给move函数。也可以为画布设置单个绑定,首先确定单击哪个门。出于这个答案的目的,我们将保持简单并为每个门创建一个独特的绑定。

首先,我们需要修改moveANDgate以接受唯一标记,以便它知道需要移动哪个标记:

def moveANDGate(event, tag):
    x=event.x
    y=event.y
    coords=canvas.coords(tag)
    movex=x-coords[0]
    movey=y-coords[1]
    canvas.move(tag, movex, movey)

接下来,我们需要创建一个可用于生成唯一标记的全局变量。然后我们可以在andGATE内使用该变量来创建标记并将其添加到画布中的所有项目。然后,我们需要将函数绑定到新标记的<B1-Motion>事件。:

gate_id = 0
def andGATE():
    global gate_id
    gate_id += 1
    gate_tag = "andgate-%s" % gate_id
    tags = ("andgate", gate_tag)

    canvas.create_line(150, 50, 150, 150, width=5, tags=tags)
    canvas.create_arc(150, 50, 200, 150, start=90, extent=-180, width=5, fill="black", tags=tags)

    canvas.create_line(150, 75, 120, 75, width=5, tags=tags)
    canvas.create_line(150, 120, 120, 120, width=5, tags=tags)
    canvas.create_line(200, 100, 250, 100, width=5, tags=tags)
    canvas.create_rectangle(150, 50, 180, 150, width=5, fill="black", tags=tags)

    canvas.tag_bind(gate_tag, "<B1-Motion>", lambda event, tag=gate_tag: moveANDGate(event, tag))

在这个例子中,我给每个项目两个标签:一个是静态字符串“andgate”,另一个是id。这使得可以一次对所有的andgate对象执行某些操作,或者为特定的andgate执行某些操作。将"andgate"视为类名,将"andgate-<number>"视为实例名称。这不完全是它们,但从逻辑上讲,这就是它们的使用方式。