Tkinter使用控制器交叉引用类和变量? [英] Tkinter cross reference class and variables using controller?

查看:57
本文介绍了Tkinter使用控制器交叉引用类和变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的上一篇文章中,我问如何引用方法和Tkinter中类之间的变量.@JacksonPro使用 parent 提供了一个不错的解决方案,如下所示:

In my previous post, I asked how to reference methods and variables between classes in Tkinter. And @JacksonPro provided a nice solution using parent like the following:

from tkinter import *
from tkinter import scrolledtext
    
    
def main():
        """The main app function"""
        root = Tk()
        root_window = Root(root)
        root.mainloop()
    
    
class Root:
    
        def __init__(self, root):
            # Main root window configration
            self.root = root
            self.root.geometry("200x100")
            
            self.btn_ok = Button(self.root, text="Open new window",
                                 command=lambda :NewWindow(self))
            self.btn_ok.pack(padx=10, pady=10)
    
        def hide(self):
            """Hide the root window."""
            self.root.withdraw()
    
        def show(self):
            """Show the root window from the hide status"""
            self.root.update()
            self.root.deiconify()
    
        def onClosing(self, window):
            window.destroy()
            self.show()
    
class NewWindow:
        
        def __init__(self, parent):
    
            self.parent = parent
            parent.hide()
        
            self.new_window = Toplevel()
    
            lbl = Label(self.new_window, text="Input here:")
            lbl.pack(padx=10, pady=(10, 0), anchor=W)
    
            # Create a scrolledtext widget.
            self.new_content = scrolledtext.ScrolledText(
                                    self.new_window, wrap=WORD,
                                    )
    
            self.new_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
    
    
            # Respond to the 'Cancel' button.
            btn_cancel = Button(self.new_window, text="Cancel", width=10,
                                command=lambda: parent.onClosing(self.new_window))
            btn_cancel.pack(padx=10, pady=10, side=RIGHT)
    
            # Add 'OK' button to read sequence
            self.btn_ok = Button(self.new_window, text="OK", width=10,
                                 command=self.readContent)
            self.btn_ok.pack(padx=10, pady=10, side=RIGHT)
    
        def readContent(self):
            self.content = self.new_content.get(1.0, END)
            
            self.new_window.destroy()
            workwindow = WorkingWindow(self)
            
    
    
class WorkingWindow:
    
        def __init__(self, parent):

            self.parent = parent
            self.work_window = Toplevel()
            self.work_content = scrolledtext.ScrolledText(self.work_window, wrap=WORD, font=("Courier New", 11))
            self.work_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
            self.work_content.insert(1.0, parent.content)
            self.work_window.protocol("WM_DELETE_WINDOW",
                             lambda: parent.parent.onClosing(self.work_window))
    
    
if __name__ == '__main__':
        main()

但是,似乎这种方法仅允许您使用大量的 parent 逐层引用类.像这样在代码中:

However, it seems like this approach only allows you to reference between class layer by layer, using a lot of parent. Like this in the code:

self.work_window.protocol("WM_DELETE_WINDOW", lambda: parent.parent.onClosing(self.work_window))

当类在应用程序中累积时,这将非常不便且令人困惑.所以我想知道如何实现使用 controller 从任何地方访问任何类中的任何方法或变量的目标?我在 controller 上看到过帖子,但在这种情况下,例如,仍然对如何使用它感到困惑.任何帮助,将不胜感激.谢谢!

It would be very inconvenient and confusing when the classes are accumulating in the application. So I was wondering how to achieve the goal of accessing any method or variable in any class from anywhere using controller? I have seen posts on controller, but still confusing on how to use it, for example, in this case. Any help would be appreciated. Thanks!

推荐答案

由于每个tk对象都知道其主对象是什么,因此请使用递归函数调用来查找作为 Tk 实例的父对象.

Since each tk object knows what their master is, use a recursive function call to find the parent that is an instance of Tk.

下面是一个人为的示例,其中包含一些不同的框架和一个按钮. find_tkroot 函数将在层次结构中向上移动,以找到 Tk 实例.在这种情况下,它仅使用它来设置根窗口的标题.

Below is a contrived example that contains a few different frames and a button. The find_tkroot function will move up through the hierarchy to find the Tk instance. In this case, it just uses it to set the title of the root window.

from tkinter import *

def find_tkroot(widget):
    try:
        if widget.__class__.__name__ == 'Tk':
            return widget
        else:
            return find_tkroot(widget.master)
    except RecursionError as err:
        print(err)
        print("Got lost at {0}".format(widget))

root = Tk()
frm1 = Frame(root)
frm2 = Frame(frm1)
frm1.grid()
frm2.grid()
btnClose = Button(frm2,text="Close",command=lambda: find_tkroot(btnClose).title('Set Me'))
btnClose.grid()

print(find_tkroot(frm2))

如果您创建自己的班级,则可以扩展此范围以找到特定班级名称的父级.

You could extent this to find a parent of a specific class name if you create your own classes.

def find_parent_matching(widget, class_name):
    print("Checking: ", widget)
    try:
        if widget.__class__.__name__ == class_name:
            return widget
        else:
            return find_tkroot(widget.master)
    except RecursionError as err:
        print(err)
        print("Got lost at {0}".format(widget))

将小部件名称作为第二个参数,例如 find_parent_matching(widget,'MyCustomClass')

Which takes a widget name as a second parameter, for example find_parent_matching(widget,'MyCustomClass')

这篇关于Tkinter使用控制器交叉引用类和变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆