python + tkinter:如何将 Canvas 用于主函数和子函数?

python + tkinter: How to use Canvas for the main function and for a subfunction both?

这应该是一个简单的问题,但我就是没有找到答案。

我做了一个主函数,其中有一个按钮和一个画。我还有一个 subfunction,它连接到主函数中的 button

通过单击按钮,我想在同一 window 中绘制另一条线,并且应擦除原始线。

这是我写的代码。我真的不知道如何完成它。非常感谢任何形式的帮助。谢谢。

import Tkinter as tk

def DrawFunc():
    x1 = 20 ; y1 = 20
    x2 = 60 ; y2 = 80

    S_Canvas = tk.Canvas(root)
    S_Canvas.pack()

    S_Canvas.create_line(x1, y1, x2, y2, fill="black")  # When the button is clicked, this line should be shown. And the old line should be deleted.


def Window():
    global root
    root = tk.Tk()
    root.geometry("400x400")

    S_Canvas = tk.Canvas(root)
    S_Canvas.pack()
    S_Canvas.create_line(50, 250, 250, 70, fill="red")  # When the program is run, this line is shown.

    Frame_1 = tk.Frame(root)
    Frame_1.place(width=120, height=80, x=0, y=0)
    Button_1 = tk.Button(Frame_1, text = u"Draw", width = 20, height=10, bg= "green" ,command = DrawFunc())
    Button_1.pack()

    root.mainloop()
Window()

要绘制相同的 canvas,您的 DrawFunc 函数必须知道 canvas.

最快的解决方案是向 DrawFunc 函数添加一个 targetCanvas 参数,然后将其传递给 S_Canvas.

我可能记得不好,但我认为 tkinter 不支持直接将参数传递给回调函数。作为解决方法,您可以使用 lambda 函数:

Button_1 = tk.Button(Frame_1,
                     text = u"Draw",
                     width = 20,
                     height=10,
                     bg= "green",
                     command = lambda: DrawFunc(targetCanvas))

如果您想重复使用此命令,则必须定义一个 draw_func_command 函数,该函数不带参数:

def draw_func_command():
    global S_Canvas
    DrawFunc(S_Canvas)

但是,您需要将 S_Canvas 声明为全局...

为了避免这种情况,实现 UI 元素的一般方法是将它们声明为 classes。不过我不打算在这里展开这个,因为这是一个广泛的话题,有点超出了问题的范围。

要删除第一行,有点棘手。其实,Canvas.create_linereturns一个对象,就是画的线。要删除它,您必须将它存储在一个变量中,然后对其调用 delete 函数。

你的代码的问题是函数不在同一个class,所以变量必须相互传递...

至于擦除 canvas 的问题,在你的 DrawFunc 函数中添加一个 oldLine 参数,然后在其主体中调用 oldLine.delete()

currentLine = S_Canvas.create_line(50, 250, 250, 70, fill="red")
Button1 = Button(..., command = lambda: DrawFunc(targetCanvas, currentLine))