我有一个使用tkinter的简单图形用户界面,它提供了一个空白画布,光标在任意位置放置绿色方块。
我正在尝试在界面顶部的“全部清除”按钮中编码,清除整个画布(同时保持光标在再次点击画布时绘制正方形的能力) :
import tkinter as tk
class Interface(tk.Frame):
def __init__(self, master):
super().__init__(master)
tk.Button(self, text="Clear all", command=self.clearall).pack(side = tk.LEFT)
#What the heck do I do here?
def clearall(self):
#self._canvas.delete(tk.ALL)
pass
class App(object):
def __init__(self, master):
master.title("Doodle test")
master.geometry("600x600")
self._interface = Interface(master)
self._interface.pack()
self._canvas = tk.Canvas(master, bg='white')
self._canvas.pack(fill=tk.BOTH, expand=1)
self._canvas.bind("<Button-1>", self.leftclick)
# And would I need to put something here?
def plz_run_me_when_clearall_method_is_called(self):
self._canvas.delete(tk.ALL)
def leftclick(self, arg):
d = 10
self._canvas.create_rectangle([(arg.x, arg.y), (arg.x+d, arg.y+d)], fill="green")
root = tk.Tk()
app = App(root)
root.mainloop()
通常,如果整个程序是在一个类中构造的,那么这将是一个简单的任务,例如:
def clearall(self):
self._canvas.delete(tk.ALL)
由于有两个类,我无法为.delete(tk.ALL)
调用_canvas
方法,因为它是在App
类中声明的。那么我怎么能传达一个按钮来执行从另一个类影响项目Y的函数X?
编辑:仍然试图为这篇文章考虑一个合适的标题。
答案 0 :(得分:2)
python(不仅仅是tkinter)的一个简单规则是,如果一个对象需要另一个对象中的资源,那么第一个对象需要对第二个对象的引用。
这意味着要么将App
的实例传递给Interface
的实例,要么传递画布本身。
例如,您可以通过这种方式传递画布:
class Interface(tk.Frame):
def __init__(self, master, canvas):
...
self._canvas = canvas
...
def clearall(self):
self._canvas.delete(tk.ALL)
class App(object):
def __init__(self, master):
...
self._canvas = tk.Canvas(master, bg='white')
self._interface = Interface(master, self._canvas)
...
有许多方法可以完成类似的事情。例如,您可以传递对应用程序本身的引用(例如:self._interface = Interface(master, self). You could then either make
self._canvas`“public”,或者您可以提供返回画布的getter,而不是传入画布。
上述方法的潜在缺点是它将两个类紧密地联系在一起。也就是说,如果有一天App
被重新绘制在图像对象而不是画布对象上,则Interface
也必须进行修改,因为它取决于App
中的特定实现(也就是说,它在画布上完成所有工作。)
松散耦合意味着Interface
不了解或关心App
的实施方式,它只知道App
承诺提供Interface
可以使用的API。通过这种方式,App
可以完全更改其实现而不会中断Interface
,只要它继续提供相同的API。
要保持这些类松散耦合,您需要将clearall
方法添加到App
中。有了这个,Interface
不需要知道App
使用画布,它只需要知道App
提供了一种清除绘图表面的方法,无论绘图表面是什么是
class Interface(tk.Frame):
def __init__(self, master, app):
...
self._app = app
...
def clearall(self):
self._app.clearall()
class App(object):
def __init__(self, master):
...
self._canvas = tk.Canvas(master, bg='white')
self._interface = Interface(master, self)
...
def clearall(self):
self._calvas.delete(tk.ALL)