繁体   English   中英

从另一个类调用小部件以在tKinter中更改其属性

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM