Search code examples
pythonclassooptkintertoplevel

Comunicate between main GUI interface and top level GUI interface


I have a problem between communication of GUI's. My program consists on one main interface that is created on class maininterface(): and other top level interface that it is created in a different class: class Interface_PowerBalance(). The main interface controls the other top level interfaces. My issue is that I wan't to receive info of some attributes of the toplevel interfaces into the main interface and I don't achieve it.

Here there is the class maininterface(): where I create the main GUI.

class mainInterface():

    def __init__(self,root,title):
        self.root=root
        self.root.title(title)
        self.Widgets()
    def Widgets(self):
        self.PowerBalanceLabel=Label(self.root,text='Power balance is:')
        self.PowerBalanceLabel.grid(row=0,column=1)

        self.Button_InterfacePowerBalance=Button(root,command=self.PowerBalanceframe)
        self.Button_InterfacePowerBalance.grid(column=0,row=0)
        
    def PowerBalanceframe(self):
        self.Power=Interface_PowerBalance(self.root,'Power balance interface').PowerBalance()
        self.PowerBalanceLabel.config(text='Power balance is: '+str(self.Power))

When I click self.Buttton_InterfacePowerBalance the program creates the top level interface that is in class Interface_PowerBalance() with the next code:

class Interface_PowerBalance():
    """ This class creates the interface to obtain the power balance """
    def __init__(self,root,title):
        self.root=root
        self.PowerBalanceFrame=Toplevel(self.root)
        self.PowerBalanceFrame.title(title)
        self.value=DoubleVar()
        self.valueList=[]
        self.Widget()
    def Widget(self):
        self.myentry_value = Entry(self.PowerBalanceFrame,textvariable=self.value)
        self.myentry_value.grid(row=2,column=2)
        self.Button1=Button(self.PowerBalanceFrame, text='Insert a device', command=self.StoreData)
        self.Button1.grid(row=0,column=0)
    def StoreData(self):
        self.valueList.append(self.value.get())
        self.PowerBalance()
    def PowerBalance(self,*args):
        self.Power=float(self.Power)
        N=len(self.valueList)
            for j in range (0,N):
                self.Power=self.Power+float(self.valueList[j])
        self.PowerLabel=Label(self.PowerBalanceFrame,text=str(self.Power))
        self.PowerLabel.grid(row=6,column=2)
        return self.Power

What my programs do rigth now is receive the self.Power attribute from class Interface_PowerBalance():when this toplevel interface is opened and show it in the main interface in the self.PowerBalanceLabel. What I want to do is receive self.Power attribute from class Interface_PowerBalance(): each time this attribute is changed and show it in the main interface in the self.PowerBalanceLabel.

I don't know if it makes sense.

Thank you.


Solution

  • First of all create a variable power in the mainInterface, because you want to keep track of it always:

    class mainInterface():
        def __init__(self,root,title):
            self.root=root
            self.root.title(title)
            self.Widgets()
            self.Power = 0.0 # Here you will store the Power value
    

    Second, you will not change the value of the label in the PowerBalanceFrame method because you are not binding the toplevel to know when it is closing, so change it to:

    def PowerBalanceframe(self):
        Interface_PowerBalance(self,'Power balance interface').PowerBalance()
    

    The trick now is in how you create your toplevel. You want it to edit the label of the maininterface so you have to pass the main as parameter (see I passed self as parameter instead of self.root), so you have to change the __init__ of the Interface_PowerBalance:

    class Interface_PowerBalance():
        """ This class creates the interface to obtain the power balance """
        def __init__(self,main,title):
            self.main = main # here main is the main interface
            self.root=main.root # thus main.root is the root
            self.PowerBalanceFrame=Toplevel(self.root)
            self.PowerBalanceFrame.title(title)
            self.value=DoubleVar()
            self.valueList=[]
            self.Widget()
    

    now you can access main.Power and the main.PowerBalanceLabel, so just change the PowerBalance method to:

    def PowerBalance(self,*args):
        N=len(self.valueList)
        for j in range (0,N):
            self.main.Power=self.main.Power+float(self.valueList[j])
        self.PowerLabel=Label(self.PowerBalanceFrame,text=str(self.main.Power))
        self.PowerLabel.grid(row=6,column=2)
        self.main.PowerBalanceLabel['text'] = "Power balance is: " + str(self.main.Power) #here is where you edit the main GUI
    

    This will work but I shall warn you that your code is not very good. First it would be much better if you used the mainInterface as children of the tk.Tk. Second that you could use tkinter variables to keep track of the power and use bind to identify when it is changed. And last but not least, variables should be lowercase and classes uppercase.