Python Forum

Full Version: Updating a variable within a class
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello, I'm really struggling with this concept.

When I initialize my code, on the 'DisplayDict' Page, mydict is set to 'dict1'. When I go to the 'AddDict' page, I add 'dict2' and 'dict3' to mydict. Now when I go back to the "DisplayDict" page, I want to display 3 labels which say "dict1","dict2", and "dict3" respectively. However, it still only says "dict1". It seems as the class wasn't reinitialized. How do I rerun the code so that it updates for changes in the "mydict" variable?


global mydict # global
mydict = {'dict 1' : {"a b c" : 123}}

import tkinter as tk

LARGE_FONT= ("Verdana", 12)

class MyApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)



        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        
        for F in (AddDict, DisplayDict, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(AddDict)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()
        

class AddDict(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)

        def addvar():
            global mydict

            mydict['dict 2']={'d e f':456}
            mydict['dict 3']={'x y z':789}
            print(mydict)


        label = tk.Label(self, text="Calculation Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
        button = tk.Button(self, text="Display Results",
                            command=lambda: controller.show_frame(DisplayDict))
        button.pack()

        b = tk.Button(self, text="PageTwo",
                            command=lambda: controller.show_frame(PageTwo))
        b.pack()

        b2 = tk.Button(self, text="Calc", command=addvar)
        b2.pack()



class DisplayDict(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        
        global mydict

        for i in mydict:
            print(i)
            print("test")
            tk.Label(self, text=i).pack(pady=10, padx=10)
            
        button1 = tk.Button(self, text="Back to Calculation Page",
                            command=lambda: controller.show_frame(AddDict))
        button1.pack()




class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        
        label = tk.Label(self, text="Page Two")
        label.pack(pady=10, padx=10)

        button1 = tk.Button(self, text="Back to Home",
                        command=lambda: controller.show_frame(AddDict))
        button1.pack()
        button2 = tk.Button(self, text="Page One",
                        command=lambda: controller.show_frame(DisplayDict))
        button2.pack()
        


app = MyApp()
app.geometry('750x500')

app.mainloop()
The __init__ method is called when you create an instance of a class. For DisplayDict this happens in MyApp.__init__
frame = DisplayDict(container, self)
self.frames[DisplayDict] = frame
When you push the "Display Results" button it calls:
controller.show_frame(DisplayDict)
Here DisplayDict is used as a key to find which frame to show. It does not create a new DisplaDict an thus does not call DisplayDict.__init__

If you want to update the content of the frame you will need to provide a function to do so. You could change your show_frame method to show and update the frame. Something like this:
    def show_frame(self, cont):
        """in MyApp.  Update frame and raise"""
        frame = self.frames[cont]
        frame.update()  # Update widget in the frame
        frame.tkraise()

    def update(self):
        """In DisplayFrame.  Update widgets"""
        for i in mydict:
            tk.Label(self, text=i).pack(pady=10, padx=10)
Each of your frames would need an "update" method that the application could call.
(Apr-17-2020, 08:37 AM)deanhystad Wrote: [ -> ]The __init__ method is called when you create an instance of a class. For DisplayDict this happens in MyApp.__init__
frame = DisplayDict(container, self)
self.frames[DisplayDict] = frame
When you push the "Display Results" button it calls:
controller.show_frame(DisplayDict)
Here DisplayDict is used as a key to find which frame to show. It does not create a new DisplaDict an thus does not call DisplayDict.__init__

If you want to update the content of the frame you will need to provide a function to do so. You could change your show_frame method to show and update the frame. Something like this:
    def show_frame(self, cont):
        """in MyApp.  Update frame and raise"""
        frame = self.frames[cont]
        frame.update()  # Update widget in the frame
        frame.tkraise()

    def update(self):
        """In DisplayFrame.  Update widgets"""
        for i in mydict:
            tk.Label(self, text=i).pack(pady=10, padx=10)
Each of your frames would need an "update" method that the application could call.

Thank you for the reply. This was extremely helpful!!