Я пытаюсь выяснить, каков наилучший способ связи между различными виджетами, где виджеты - это пользовательские классы, наследуемые от виджетов tkinter, и у меня есть несколько фреймов (чтобы помочь с управлением макетом). Рассмотрим, например, следующий простой графический интерфейс (написанный для python 3, замените tkinter на Tkinter для python 2):
from tkinter import Frame,Button,Tk
class GUI(Frame):
def __init__(self, root):
Frame.__init__(self,root)
self.upper_frame=Frame(root)
self.upper_frame.pack()
self.lower_frame=Frame(root)
self.lower_frame.pack()
self.upper_btn1 = Button(self.upper_frame, text="upper button 1")
self.upper_btn2 = Button(self.upper_frame, text="upper button 2")
self.upper_btn1.grid(row=0,column=0)
self.upper_btn2.grid(row=0,column=1)
self.lower_btn = CustomButton(self.lower_frame, "lower button 3")
self.lower_btn.pack()
class CustomButton(Button):
def __init__(self,master,text):
Button.__init__(self,master,text=text)
self.configure(command=self.onClick)
def onClick(self):
print("here I want to change the text of upper button 1")
root = Tk()
my_gui = GUI(root)
root.mainloop()
Причина, по которой я помещаю их в разные фреймы, заключается в том, что я хочу использовать разные менеджеры компоновки в двух разных фреймах для создания более сложной компоновки. Однако я хочу, чтобы команда в lower_btn
изменила свойства, например, upper_btn1
.
Однако я не могу сразу получить доступ к upper_btn1
из экземпляра lower_btn
настроенного класса CustomButton
. Родитель lower_btn
- frame2
, а родитель frame2
- root (не экземпляр GUI). Если я изменю родителя lower_btn
на экземпляр GUI, то есть
self.lower_btn = CustomButton(self, "lower button")
он не будет правильно размещен при использовании pack()
. Если я изменю родителя frame1/frame2
на экземпляр GUI, то есть
self.upper_frame=Frame(self)
self.upper_frame.pack()
self.lower_frame=Frame(self)
self.lower_frame.pack()
В принципе я мог бы получить доступ к upper_btn1
из lower_btn
по self.master.master.upper_btn1
, НО тогда frame1/frame2
были размещены неправильно, используя pack()
(это я не понимаю, почему). Конечно, я могу передать экземпляр GUI как отдельную переменную, поверх master, CustomButton
, то есть что-то вроде
class CustomButton(Button):
def __init__(self,master,window,text):
Button.__init__(self,master,text=text)
self.window=window
self.configure(command=self.onClick)
def onClick(self):
self.window.upper_btn1.configure(text="new text")
и затем измените конструкцию lower_btn
на
self.lower_btn = CustomButton(self.lower_frame,self, "lower button 3")
но это ли "правильный" способ сделать это?
Итак, как лучше всего реорганизовать этот графический интерфейс? Должен ли я передавать GUI как отдельную переменную поверх аргумента master / parent? Должен ли я изменить основной / родительский элемент кнопок и / или рамок (и как-то решить проблемы с управлением макетом)? Или я должен сделать команды кнопок как методы экземпляра GUI, чтобы они могли взаимодействовать с виджетами в этом GUI, хотя на самом деле это не похоже на объектно-ориентированное программирование? Я не могу найти работающий объектно-ориентированный дизайн, который кажется «правильным». Кроме того, объяснение, почему pack()
не работает для frame1/frame2
, если я сделаю экземпляр GUI (self
) мастером, также будет оценено, поскольку это был бы мой интуитивный, наиболее объектно-ориентированный подход.
Редактировать: Возможно, лучший способ - вообще не использовать фреймы внутри фреймов, а использовать только grid (), а затем использовать colspan / rowspan для большей гибкости управления компоновкой.