MC2020
MC2020

Reputation: 47

Referencing a variable from another class

I have provided my code below. There is no error, but it is not performing how I would like. In the 'Display Var' class I am showing the output for myvar. I want it to show two labels, one which says 'dict 1 ' and another one that says 'dict 2'. Right now it just pulls the original value of 'dict 1'. The first step for the program is to go to the Calc Var page and I add 'dict 2' to mydict. From there I want to go to the 'Display Var' page and display the edited dictionary so that it shows are 'dict 1 ' and 'dict 2', but it only will show as 'dict 1'. How do I make it show as 'dict 1 ' and 'dict 2?

Any help is greatly appreciated!

import tkinter as tk

LARGE_FONT= ("Times New Roman", 22)


class MyApp(tk.Tk):

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

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

        global mydict
        mydict = {'dict1' : {"a b c" : 123}} # set its value


        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 (CalcVar, DisplayVar):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(CalcVar)

    def show_frame(self, cont):

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


class CalcVar(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)


        def addvar():
            global mydict
            #myvar.set(myvar.get()+" c") # when add the value.
            dict2 = {'d e f' : 456}
            mydict['dict 2'] = dict2
            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(DisplayVar))
        button.pack()


        calcbutton = tk.Button(self, text="AddVar",
                            command=addvar)
        calcbutton.pack()



class DisplayVar(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        global mydict

        for x, y in mydict.items():
            label = tk.Label(self, text=x, font=LARGE_FONT) 
            label.pack(pady=10,padx=10)


        button1 = tk.Button(self, text="Back to Calculation Page",
                            command=lambda: controller.show_frame(CalcVar))
        button1.pack()

Upvotes: 0

Views: 77

Answers (1)

jizhihaoSAMA
jizhihaoSAMA

Reputation: 12672

Your problem isn't "Referencing a variable from another class".When your run it in the first time,the text is "a,b".Even though you call addvar() next time,the text in label won't be changed.You could use a textvariable instead of text in the Label widget.

Followed by your code:

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)

        global myvar # global
        myvar = tk.StringVar() # create a StringVar and assign it myvar
        myvar.set("a b") # set its value

        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 (CalcVar, DisplayVar):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(CalcVar)

    def show_frame(self, cont):

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

class CalcVar(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)

        def addvar():
            global myvar
            myvar.set(myvar.get()+" c") # when add the value.
            print(myvar.get())

        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(DisplayVar))
        button.pack()

        calcbutton = tk.Button(self, text="AddVar",
                            command=addvar)
        calcbutton.pack()

class DisplayVar(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        global myvar

        label = tk.Label(self, textvariable=myvar, font=LARGE_FONT) # bind a textvariable not text
        label.pack(pady=10,padx=10)
        button1 = tk.Button(self, text="Back to Calculation Page",
                            command=lambda: controller.show_frame(CalcVar))
        button1.pack()

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

app.mainloop()

Edit:The principle is the same even if you want to use a dict.The easiest way is use textvaribale.But if you want to show the string in the dict.Just use myvar.set(xx) to set it.

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)

        global myvar,mydict # global
        mydict = {'dict 1' : {"a b c" : 123}}
        myvar = tk.StringVar() # create a StringVar and assign it myvar
        myvar.set(" ".join(i for i in mydict)) # set "dict 1" string

        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 (CalcVar, DisplayVar):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(CalcVar)

    def show_frame(self, cont):

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

class CalcVar(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)

        def addvar():
            global myvar,mydict
            dict2 = {'d e f' : 456}
            mydict['dict 2'] = dict2 # add it to your dict
            myvar.set(" ".join(i for i in mydict)) # also set the vale and show it.
            print(myvar.get())

        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(DisplayVar))
        button.pack()

        calcbutton = tk.Button(self, text="AddVar",
                            command=addvar)
        calcbutton.pack()

class DisplayVar(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        global myvar

        label = tk.Label(self, textvariable=myvar, font=LARGE_FONT) # bind a textvariable not text
        label.pack(pady=10,padx=10)
        button1 = tk.Button(self, text="Back to Calculation Page",
                            command=lambda: controller.show_frame(CalcVar))
        button1.pack()

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

app.mainloop()

I strongly recommend you just use \n to join them(That's very easy and fast),if you really want to create two label widgets.This is code(maybe it is not the best way):

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)

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

        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 (CalcVar, DisplayVar):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(CalcVar)

    def show_frame(self, cont):

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

class CalcVar(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)

        def addvar(p,c):
            global mydict
            for i in p.winfo_children()[0].winfo_children(): # delete all the widget in the displayVar
                i.pack_forget()
            mydict['dict 2']={'d e f':456}
            for i in mydict: # then pack them in it.
                tk.Label(p.winfo_children()[0],text=i).pack(pady=10,padx=10)
            button1 = tk.Button(p.winfo_children()[0], text="Back to Calculation Page",
                                command=lambda: c.show_frame(CalcVar))
            button1.pack()

        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(DisplayVar))
        button.pack()

        calcbutton = tk.Button(self, text="AddVar",
                            command=lambda :addvar(parent,controller))
        calcbutton.pack()

class DisplayVar(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        global mydict

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

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

app.mainloop()

Upvotes: 1

Related Questions