可以使用 tkinter 按钮重复更改 canvas 对象吗?

Can tkinter buttons be used to change canvas objects repeatedly?

我正在尝试创建一个 GUI 来表示三角形对称群的图形解释(即保持其不变的等边三角形的反射和旋转)。 理想情况下,我希望以动画方式执行此操作,但这超出了我的范围,所以我只是更改点上的标签,并希望使用按钮进行反射或旋转,但我不能获取按钮以实际更改我需要它们的坐标值。

我试图在下面的代码中交换 p1、p2 和 p3 的坐标 `

def rf(p1, p2, p3):
    p4=p3
    p3=p2
    p2=p4
def ro(p1, p2, p3):
    p4=p1
    p1=p2
    p2=p3
    p3=p4
    print(p4)
def buttons(p1, p2, p3):
    l=tk.Button(top, text="Rotate", command=ro(p1, p2, p3))
    k=tk.Button(top, text="Reflect", command=rf(p1, p2, p3))
    triangle(p1, p2, p3)
    text(p1, p2)
    k.pack()
    l.pack()
buttons(p1, p2, p3)
top.mainloop()

`

当我运行它,并按下旋转按钮时,p1打印原始值,无论按下多少次按钮都只打印一次。 我怎样才能解决这个问题,是否有更好的包可以实际制作动画? 谢谢!

您不能将参数传递给这样的按钮中的命令。 你所做的实际上是在创建按钮时评估 ro(p1, p2, p3) ,采用该方法的 return (即 None )并将其保存为命令。因此,当您按下按钮时,它会调用 None...当然什么也不做。

通常情况下,当你制作一个按钮时,命令应该只是一个METHODS NAME ONLY 例子: l = tk.Button(top, text="旋转", command=ro)

这是一件 python 的事情,您可以在其中将整个方法视为变量。 所以也许可以这样做,并将方法更改为如下所示:

def ro():
    p4=p1
    p1=p2
    p2=p3
    p3=p4
    print(p4)

如果您确实需要传递参数,这是最常见的解决方法:

l = tk.Button(top, text="Rotate", command=lambda: ro(p1, p2, p3)

关于其工作原理的解释有点长,您可以在 python 中查找 lambda 关键字的作用以进一步了解它。

编辑,如评论所述

按照你现在的方式使用你的变量可能会导致一些奇怪的事情发生。即它不会“保存”对变量的更改。发生这种情况是因为您正在使用的变量的范围仅限于它们在其中使用的函数。也就是说,您正在使用的名称是在函数中创建的,因此一旦函数完成它们就会被删除。有几种方法可以解决这个问题。

一种方法是全局保存名称,删除参数并告诉函数它们是全局的:

p1 = 5  # these are just examples, make sure they are established
p2 = 7  # on the root level, or at least on the level that your
p3 = 12 # button is made or lower

def ro():
    global p1, p2, p3 # this will insist on using the globally named variables and not things specific to this function
    p1, p2, p3 = p2, p3, p1 # oh, btw, you can do this to save space and not have to make a p4

在这种情况下,您将不得不删除 lambda 并让它作为命令调用 'ro'。 这会做你想做的,但有几个问题:

  1. 除了旋转这三个东西之外,您不能将 ro() 方法用于任何其他事情
  2. 通常不赞成使用 'global' 关键字,我个人从不使用它

您可能满意的是这样的:

p = [14, 12, 83]
q = [1, 43, 18, 75]

def ro(x):
    first = x.pop(0)
    x.append(first)

print(p)
ro(p)
print(p)
print()
print(q)
ro(q)
print(q)

如果你 运行 那个,你会看到它旋转了任意列表中的所有数字。 这样,您可以将三角形存储在列表中,然后像这样制作按钮:

l=tk.Button(top, text="Rotate", command=lambda: ro(p))

它会改变给 ro() 命令的列表,你不需要担心变量的作用域,因为你用 ro(p) 中的 'p' 传递它并且它对传递的内容进行更改。

希望对您有所帮助。