【问题标题】:Tkinter reference methods and variables between classesTkinter 引用方法和类之间的变量
【发布时间】:2021-02-19 05:53:28
【问题描述】:

我被困在Tkinter 中的类之间引用方法和变量。

这里是一个简单的例子,我有三种不同类型的窗口,我想把它们放到不同的classes中。

root 窗口中,我可以单击button 打开第二个窗口,我可以在其中向Text 小部件输入内容。

同样在第二个窗口中,我希望OK 按钮将Text 小部件中的内容和insert 内容读入另一个Text 小部件到第三个窗口。而Cancel 按钮可以关闭第二个窗口并再次显示root 窗口。

代码中有很多错误,因为我不知道如何在classes 之间进行交叉引用以访问methodsvariables

有人可以帮我完成吗?谢谢。

from tkinter import *
from tkinter import scrolledtext
    
    
    def main():
        """The main app function"""
        root = Tk()
        root_window = Root(root)
        return None
    
    
    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=NewWindow)
            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):
    
            Root.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: Root.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=WorkingWindow)
            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()
    
    
    class WorkingWindow:
    
        def __init__(self):
    
            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, Root.content)
    
    
    if __name__ == '__main__':
        main()
        

【问题讨论】:

    标签: python class tkinter


    【解决方案1】:

    你几乎就在那里,你所要做的就是将 Root 类的实例传递给你正在调用的其他类

    以下是更正后的代码:

    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):
        
                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.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)
        
        
    if __name__ == '__main__':
            main()
    
    

    【讨论】:

    • 很好的解决方案!!我想我还没有在 Tkinter 中掌握“父母”的概念。但是你的修改让我很清楚。非常感谢!
    • 另一件事仍然让我感到困惑。看来,通过使用parent,我只能从NewWindow 类访问Root 类;并从WorkingWindow 类访问NewWindow 类。如果我想从WorkingWindow 类访问Root 类怎么办,例如,我想在关闭self.workWindow 时再次显示self.root 窗口,方法是调用Root 中的onClosing() 方法班级。 self.work_window.protocol("WM_DELETE_WINDOW", lambda: Root.onClosing(self.work_window))我应该如何做到这一点?
    • @ZhenhuaXu 实现这一目标的最快方法可能是创建一个实例变量并将其分配给父级。例如:- 在NewWindow 类构造函数中分配self.parent=parent 现在从WorkingWindow 类您可以通过调用parent.parent 访问Root
    • 是的,这行得通!这样,在没有太多代码的情况下也能正常工作。但是当类变得复杂时,这种逐层引用会显得乏味和不便。有没有更简单的方法可以直接从任何类访问一个类?我看过一些使用控制器的帖子,我理解这个概念但在使用它时遇到了麻烦。您能否使用我们当前的示例代码解释如何使用控制器?谢谢!
    • @ZhenhuaXu 我觉得你单独发个帖子会更好。
    猜你喜欢
    • 2012-01-30
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多