[英]Calling a widget from another class to change its properties in tKinter
我在tKinter应用程序的主构造函数中创建了一个函数,该函数可更新小部件的某些属性,例如,它们在多个框架中的文本。 我想做的是在控制器框架中同时更改多个框架中的小部件。
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
i.widget_name.config(criteria=output)
# update_widgets(self, [Main, AnalysisSection], text_label, text, "foo")
# would result in Main.text_label_config(text="foo") and
# AnalysisSection.text_label_config(text="foo") ideally.
但是,使用此代码,我遇到两个问题。 首先,我收到一个属性错误,指出两个框架都没有属性widget_name 。 其次,当我尝试使用self前缀引用小部件名称时,两个框架都表示它们没有属性self 。 有没有办法解决这个问题?
完整程序如下:
import tkinter as tk
class Root(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.frames = {}
container = tk.Frame(self)
container.pack(side="bottom", expand=True)#fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
for X in (A, B):
frame=X(container, self)
self.frames[X]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(A)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
frame = self.frames[i]
widget = getattr(frame, widget_name)
widget[criteria] = output
class A(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.text = 'hello'
self.classLabel = tk.Label(self, text="Frame A")
self.classLabel.pack(side=tk.TOP)
# trying to change this widget
self.wordLabel = tk.Label(self, text="None")
self.wordLabel.pack(side=tk.TOP)
self.changeTextLabel = tk.Label(self, text="Change text above across both frames").pack(side=tk.TOP)
self.changeTextEntry = tk.Entry(self, bg='pink')
self.changeTextEntry.pack(side=tk.TOP)
self.changeFrameButton = tk.Button(text="Change to Frame B", command=lambda: self.controller.show_frame(B))
self.changeFrameButton.pack(side=tk.TOP, fill=tk.X)
self.changeTextEntryButton = tk.Button(self, text="ENTER", width=5, command=lambda: self.controller.update_widgets([A, B], 'self.wordLabel', 'text', self.changeTextEntry.get()))
self.changeTextEntryButton.pack(side=tk.TOP, fill=tk.X)
### calling this function outside of the button; this is already
### called within a function in my project.
x = self.controller.update_widgets([A, B], 'wordLabel', 'text', '*initial change*')
class B(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.text = 'hello'
self.classLabel = tk.Label(self, text="Frame B")
self.classLabel.pack(side=tk.TOP)
# trying to change this widget
self.wordLabel = tk.Label(self, text="None")
self.wordLabel.pack(side=tk.TOP)
self.changeTextLabel = tk.Label(self, text="Change text above across both frames").pack(side=tk.TOP)
self.changeTextEntry = tk.Entry(self, bg='light yellow').pack(side=tk.TOP)
self.changeFrameButton = tk.Button(text="Change to Frame A", command=lambda: self.controller.show_frame(A))
self.changeFrameButton.pack(side=tk.TOP, fill=tk.X)
self.changeTextEntryButton = tk.Button(self, text="ENTER", width=5, command=lambda: self.controller.update_widgets([A, B], 'self.wordLabel', 'text', self.changeTextEntry.get()))
self.changeTextEntryButton.pack(side=tk.TOP, fill=tk.X)
if __name__ == '__main__':
app = Root()
代码中的问题是您试图获取类的属性而不是类的实例 。 您需要将i
转换为该类的实际实例。 您还有一个额外的问题,那就是要传递'self.wordLabel'
而不是'wordLabel'
。
一个简单的解决方法是在self.frames
查找实例
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
frame = self.frames[i]
label = getattr(frame, widget_name)
label[criteria] = output
您还需要将button命令更改为如下所示:
self.changeTextEntryButton = tk.Button(... command=lambda: self.controller.update_widgets([A,B], 'wordLabel', 'text', self.changeTextEntry.get()))
如果您打算让update_widgets
始终更新所有页面类,则没有理由传递框架类列表。相反,您可以迭代已知的类:
def update_widgets(self, widget_name, criteria, output):
for frame in self.frames.values():
label = getattr(frame, 'classLabel')
label[criteria] = output
然后,您需要修改按钮以删除框架类列表:
self.changeTextEntryButton = tk.Button(..., command=lambda: self.controller.update_widgets('wordLabel', 'text', self.changeTextEntry.get()))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.