我想在tk.Tk和tk.Toplevel的实例中添加两个方法。前者以应用程序根窗口的形式存在,后者由用户创建多少次。每个tk.Toplevel代表应用程序的不同功能,目前存在13个变体。应用程序被配置为在任何时候只能创建每个变体的一个实例。
解决这一问题的一种方法可能是对这两个类进行子类划分:
class RootWindow(tk.Tk):
def method_1(self):
...
def method_2(self):
...
class TopWindow(tk.Toplevel):
def method_1(self):
...
def method_2(self):
...由于我只希望为功能添加两个方法(这些方法与使用这些类的方法(如winfo_height())相同),子类看起来既多余又多余,因为相同的代码编写了两次。因此,另一种方法可能是使用setattr(),但我觉得这违反了类设计的开放/关闭原则:
def method_1(self):
...
def method_2(self):
...
class RootWindow(tk.Tk):
def __init__(self):
setattr(self, 'method_1', method_1)
setattr(self, 'method_2', method_2)
class TopWindow(tk.Toplevel):
def __init__(self):
setattr(self, 'method_1', method_1)
setattr(self, 'method_2', method_2)现在,我只编写了一次方法,并修改了类;本质上,这凝聚了第一个方法,实际上是相同的。
考虑到tk.Tk是窗口,而tk.Toplevel是窗口,难道没有办法通过tkinter定义所有基于“窗口”的小部件都可以访问的方法吗?如果所有窗口都来自单个tkinter类,那么这不是一个问题,但是tk.Tk的根窗口与tk.Toplevel的根窗口不同(例如事件绑定,不一定是可视化行为)。
编辑:
查看@BryanOakley解决方案,我发现指针确实不喜欢这样;它们指向未解决的对属性的引用,我知道子类将访问这些属性,但不能访问混合类。请考虑以下几点:
class Mixin:
def method(self):
width = self.winfo_width()
height = self.winfo_height()
print(f'The window is {width} x {height}')IDE指针抛出警告,因为self无法找到已定义的winfo_width。然而,我知道它将被来自tk.Tk和tk.Toplevel的子类的实例调用,但是滥用会导致未定义的行为,例如:
class OtherWindow(Window):
pass
o = OtherWindow()
o.method()
# Attribute error这有问题吗?提议的解决方案可以工作,但感觉它是被迫工作的,因为“我知道它将如何使用”。一个明显的解决方案是键入提示:
class Mixin:
def method(self: Union[tk.Tk, tk.Toplevel]):
width = self.winfo_width()
height = self.winfo_height()
print(f'The window is {width} x {height}')因此,指针是令人满意的,代码对任何人都是可读的(假设它们不需要查找Union)。同样,当使用混合类(从未尝试过)时,这是否是预期的行为?
发布于 2019-11-01 19:22:33
我会用混音课。为TopWindow和RootWindow保留自定义类是创建基本Toplevel和Tk类的专门化的正确解决方案,mixin解决了不想重复代码的问题。
例如:
class CustomMixin():
def method_1(self):
...
def method_2(self):
...
class TopWindow(CustomMixin, tk.Toplevel):
pass
class RootWindow(CustomMixin, tk.Tk):
pass发布于 2019-11-01 19:22:24
编写一个拥有方法的类,然后在其他类中创建一个类属性,该类保留额外方法类的实例。
试试看,如果你有什么问题,请告诉我:
import tkinter as tk
class SomeExtraMethods:
def __init__(self, window):
self.window = window
def size(self):
return [self.window.winfo_width(), self.window.winfo_height()]
class RootWindow(tk.Tk):
def __init__(self):
super().__init__()
self.extra = SomeExtraMethods(self)
tk.Button(self, text='Print root window size', command=self.print_size).pack()
tk.Button(self, text='Open top window', command=self.open_top).pack()
def print_size(self):
print(self.extra.size())
def open_top(self):
top = TopWindow()
class TopWindow(tk.Toplevel):
def __init__(self):
super().__init__()
self.extra = SomeExtraMethods(self)
tk.Button(self, text='Print top window size', command=self.print_size).pack()
def print_size(self):
print(self.extra.size())
if __name__ == '__main__':
RootWindow().mainloop()结果:

https://stackoverflow.com/questions/58664587
复制相似问题