Python 访问不同类中的变量,该类需要Tkinter中的类参数

Python 访问不同类中的变量,该类需要Tkinter中的类参数,python,tkinter,Python,Tkinter,我正在做一个Tkinter项目,因为它越来越大,我开始使用类。在最终弄明白如何使用多个类作为框架之后,现在我又被一些新的东西卡住了,无法找到解决方案 我需要访问一个类中的变量,该变量是在另一个类中定义的。但是在定义它的原始位置,类接受一个参数。所以我不能调用这个变量,除非我将一个参数与其类一起使用。但是,既然我在这里的唯一目的是访问这个变量,甚至修改它,那么我如何在不影响Tkinter小部件的情况下完成它呢 同样,组织一个Tkinter项目是一个好办法吗?我见过人们做得不一样。不知道这个组织是好

我正在做一个Tkinter项目,因为它越来越大,我开始使用类。在最终弄明白如何使用多个类作为框架之后,现在我又被一些新的东西卡住了,无法找到解决方案

我需要访问一个类中的变量,该变量是在另一个类中定义的。但是在定义它的原始位置,类接受一个参数。所以我不能调用这个变量,除非我将一个参数与其类一起使用。但是,既然我在这里的唯一目的是访问这个变量,甚至修改它,那么我如何在不影响Tkinter小部件的情况下完成它呢

同样,组织一个Tkinter项目是一个好办法吗?我见过人们做得不一样。不知道这个组织是好是坏

import tkinter as tk

#Main Window
class MainProgram():
    def __init__(self):
        self.win = tk.Tk()   
        self.win.title("Class Tester")
        self.win.resizable("True", "True")     
        self.frame_1 = FirstFrame(self.win)        
        self.frame_2 = SecondFrame(self.win)       

 #First Frame       
class FirstFrame():
    def __init__(self, parent):
        self.parent =parent
        self.frame1 = tk.LabelFrame(self.parent, text="Frame 1")
        self.frame1.pack()  
        self.show_widgets()      
    def show_widgets(self):
        self.label1 = tk.Label(self.frame1, text="Hi 1")
        self.label1.grid(column=0, row=0)
    def a_fuction(self):
        self.var1 = 5 #Need to access this var from a different class
#Second Frame        
class SecondFrame():
    def __init__(self, parent):
        self.parent = parent
        self.frame2 = tk.LabelFrame(self.parent, text="Frame 2")
        self.frame2.pack()
        self.show_widgets()
        self.b_fuction()
    def show_widgets(self):
        self.label2 = tk.Label(self.frame2, text="Hi 2")
        self.label2.grid(column=1, row=0)
    def b_fuction(self):
        self.var2 = FirstFrame().var1 
        #Tryig to access but requires class argument "parent".
        print(self.var2)



if __name__ == "__main__":
    app = MainProgram().win
    app.mainloop()

我相信您已经在代码中不知不觉地解决了这个问题,因为您已经传递了父类的实例,您可以通过该实例引用类之间的变量

#Main Window
class MainProgram():
    def __init__(self):
        self.frame_1 = FirstFrame(self)        
        self.frame_2 = SecondFrame(self)       

 #First Frame       
class FirstFrame():
    def __init__(self, parent):
        self.parent =parent

    def a_fuction(self):
        self.parent.var1 = 5 

#Second Frame        
class SecondFrame():
    def __init__(self, parent):
        self.parent =parent
    def b_fuction(self):
        self.var2 = self.parent.var1

这里有一个需要执行的小示例。

要从另一个实例访问一个实例中的属性,您只需要引用另一个实例

可以说,最好的解决方案是让您的
main程序充当控制器。也就是说,
MainProgram
知道其他帧,其他帧可以在需要时请求它提供参考

首先,将
MainProgram
更改为将自身传递到其他帧:

class MainProgram():
    def __init__(self):
        ...     
        self.frame_1 = FirstFrame(self, self.win)        
        self.frame_2 = SecondFrame(self, self.win)
        ...

class FirstFrame():
    def __init__(self, main, parent):
        self.main = main
        ...

class SecondFrame():
    def __init__(self, main, parent):
        self.main = main
        ...
接下来,您可以使用
self.main
获取另一帧的实例:

class SecondFrame():
    ...  
    def b_fuction(self):
        first_frame = self.main.frame_1
        self.var2 = first_frame.var

每当你发现自己在问“我如何访问…”时,答案通常是你已经访问了它,但却把它扔掉了,所以解决办法是不要这样做

在这种情况下:您想要的
SecondFrame
实例已经存在,并且
MainProgram
实例知道它,但是
FirstFrame
无法返回到其父实例。它有一个
parent
成员,但那只是
MainProgram
win
成员,而不是
MainProgram
本身

你把两种设计混在一起了。您的组织类似于创建继承
Frame
的子类的典型tkinter习惯用法,但您已经对其进行了调整,以创建只具有
Frame
而不是一个的独立类。。实际上,您的设计很好,可以说它比通常的OO更好(有点像模型视图设计的一半),但这意味着您需要跟踪父对象,而不仅仅是它的窗口(即模型,而不是视图)

所以,你可以这样做:

class MainProgram():
    def __init__(self):
        # etc.
        self.frame_1 = FirstFrame(self)
        self.frame_2 = SecondFrame(self)

# ...

class SecondFrame():
    def __init__(self, parent):
        self.parentobj = parent
        self.parent = parent.win
        # etc.
    # and so on
    def b_fuction(self):
        self.var2 = self.parentobj.frame_1.var1 

这是我在检查回复之前找到的一个解决方案。当我在类中定义变量时,我没有使用self.var,而是使用ClassXXX.var。通过这种方式,我可以通过调用ClassXXX.var来访问其他类中的变量

import tkinter as tk

#Main Window
class MainProgram():
    def __init__(self):
        self.win = tk.Tk()   
        self.win.title("Class Tester")
        self.win.resizable("True", "True")     
        self.frame_1 = FirstFrame(self.win)        
        self.frame_2 = SecondFrame(self.win)       


#First Frame       
class FirstFrame():

    def __init__(self, parent):

        self.parent =parent
        self.frame1 = tk.LabelFrame(self.parent, text="Frame 1")
        self.frame1.pack()  
        self.show_widgets()      
    def show_widgets(self):
        FirstFrame.var1 = 5 #Variable is declared in this style instead
        self.label1 = tk.Label(self.frame1, text="Hi 1")
        self.label1.grid(column=0, row=0)

#Second Frame        
class SecondFrame():
    def __init__(self, parent):
        self.parent = parent
        self.frame2 = tk.LabelFrame(self.parent, text="Frame 2")
        self.frame2.pack()
        self.show_widgets()
        self.b_fuction()
    def show_widgets(self):
        self.label2 = tk.Label(self.frame2, text="Hi 2")
        self.label2.grid(column=1, row=0)
    def b_fuction(self):
        self.var2 = FirstFrame.var1
        print(self.var2)



if __name__ == "__main__":
    app = MainProgram().win
    app.mainloop()

你不是已经在传递main程序的实例了吗?我相信这是正确的方法。只需在任何
xxxFrame
class'方法中使用
self.parent.frame1.var
。不,这不起作用,因为
self.parent
main程序所拥有的
Frame
对象,不是
MainProgram
本身。
parent
不是
MainProgram
的实例,它是主程序内部框架的实例。您的代码无法工作,因为框架没有
var1
属性。我喜欢这种方法。这样,如果我尝试使用FirstFrame().var1调用变量,就不会出现不必使用父参数的错误。