我试图弄清楚在不同小部件之间进行通信的最佳方式是什么,其中小部件是从 tkinter 小部件继承的自定义类,并且我有几个框架(以帮助进行布局管理)。例如,考虑以下简单的 gui(为 python 3 编写,将 tkinter 更改为 python 2 的 Tkinter):
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
的实例中访问。is的父级,并且父级是 root(不是 GUI 实例)。如果我将父级更改为 GUI 实例,即lower_btn
CustomButton
lower_btn
frame2
frame2
lower_btn
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()
我原则上可以通过 from 访问,upper_btn1
但是然后没有正确放置(我不明白为什么)。我当然可以将 GUI 实例作为单独的变量在 master 之上传递给,即类似于lower_btn
self.master.master.upper_btn1
frame1/frame2
pack()
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 的最佳方法是什么?我应该将 GUI 作为主/父参数之上的单独变量传递吗?我应该更改按钮和/或框架的主/父级(并以某种方式解决布局管理问题)吗?或者我应该将按钮的命令作为 GUI 实例的方法,以便它们可以与该 GUI 中的小部件进行通信,尽管这并不像面向对象的编程?我似乎找不到一个感觉“正确”的面向对象的设计。此外,如果我将 GUI 实例 ( ) 设为主实例,为什么pack()
不起作用的解释也将不胜感激,因为这将是我直观的、最面向对象的方法。frame1/frame2
self
编辑:也许最好的方法是根本不使用框架内的框架,只使用 grid() ,然后使用 colspan/rowspan 给布局管理更多的灵活性。