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_line
returns一个对象,就是画的线。要删除它,您必须将它存储在一个变量中,然后对其调用 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))
这应该是一个简单的问题,但我就是没有找到答案。
我做了一个主函数,其中有一个按钮和一个行画。我还有一个 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_line
returns一个对象,就是画的线。要删除它,您必须将它存储在一个变量中,然后对其调用 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))