Я хотел бы добавить 2 метода к экземплярам tk.Tk
и tk.Toplevel
. Первый существует как корневое окно приложения, где последний создается пользователем любое количество раз. Каждый tk.Toplevel
представляет различные функциональные возможности приложения, и существуют 13 существующих вариантов. Приложение сконфигурировано так, что в любой момент может быть создан только 1 экземпляр каждого варианта.
Один из подходов к решению этой проблемы может заключаться в создании подкласса обоих классов:
class RootWindow(tk.Tk):
def method_1(self):
...
def method_2(self):
...
class TopWindow(tk.Toplevel):
def method_1(self):
...
def method_2(self):
...
Поскольку я только желаючтобы добавить 2 метода для функциональности (которые идентичны, поскольку они используют методы этих классов, такие как 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
(например, для привязок событий, не обязательно визуального поведения).
Редактировать:
Взглянув на решение @BryanOakleys, я обнаружил, что линтерам действительно не нравится это;они указывают на неразрешенные ссылки на атрибуты, к которым, как я знаю, подклассы будут иметь доступ, но не к смешанному классу. Примите во внимание следующее:
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
). Опять же, это ожидаемое поведение при использовании смешанных классов (никогда не пробовал их)?