neilps2000
neilps2000

Reputation: 3

In tkinter, how can I access variables created in one window in a different one?

I can't seem to figure out how to create or modify a variable in one window of my application and then later access it in another one. Also, how can I retrieve the selected value on the spinboxes in the StartPage?

Here is the code I'm using:

import tkinter as tk

TITLE_FONT = ("Helvetica", 18, "bold")

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        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 (StartPage, PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, c):
        '''Show a frame for the given class'''
        frame = self.frames[c]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO DE PRECIOS", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)

        test1 = tk.Spinbox(self, values=(1, 2, 4, 8))
        test1.pack()

        test2 = tk.Spinbox(self, values=(1, 2, 4, 8))
        test2.pack()

        button1 = tk.Button(self, width=20, text="Calculo Final",
                            command=lambda: controller.show_frame(PageOne))
        button2 = tk.Button(self, width=20, text="Calculo Actividades",
                            command=lambda: controller.show_frame(PageTwo))
        button1.pack()
        button2.pack()

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO FINAL", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, width=20, text="Volver al menu principal",
                           command=lambda: controller.show_frame(StartPage))
        button.pack()




class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO ACTIVIDADES", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, width=20, text="Volver al menu principal",
                           command=lambda: controller.show_frame(StartPage))
        button.pack()


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

Upvotes: 0

Views: 2139

Answers (2)

JeanClaudeDaudin
JeanClaudeDaudin

Reputation: 435

I have modified your code to retrieve the selected values of the Spinbox in the StartPage class with the specificities of the spinbox widget, and to print the current values in the PageOne and PageTwo classes in the button callback:

import tkinter as tk
TITLE_FONT = ("Helvetica", 18, "bold")
class SampleApp(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.varSpin1=1
        self.varSpin2=1

        self.frames = {}
        for F in (StartPage, PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(StartPage)

    def show_frame(self, c):
        '''Show a frame for the given class'''
        frame = self.frames[c]
        frame.tkraise()
        #print("spinbox values: %d %d"%(self.varSpin1,self.varSpin2))

class StartPage(tk.Frame):
    def setVarSpin1(self,v):
        self.controller.varSpin1=v
    def setVarSpin2(self,v):
        self.controller.varSpin2=v
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO DE PRECIOS", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        self.controller=controller
        val1 = tk.IntVar()
        val2 = tk.IntVar()
        self.test1 = tk.Spinbox(self, values=(1,2,4,8), textvariable=val1,
                                command=lambda:self.setVarSpin1(val1.get())).pack()
        self.test2 = tk.Spinbox(self, values=(1,2,4,8), textvariable=val2,
                                command=lambda:self.setVarSpin2(val2.get())).pack()
        button1 = tk.Button(self, width=20, text="Calculo Final",
                            command=lambda: controller.show_frame(PageOne)).pack()
        button2 = tk.Button(self, width=20, text="Calculo Actividades",
                            command=lambda: controller.show_frame(PageTwo)).pack()

class PageOne(tk.Frame):
    def callback(self):
        print("PageOne: spinbox values: %d %d"%(self.controller.varSpin1,self.controller.varSpin2))
        self.controller.show_frame(StartPage)
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO FINAL", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, width=20, text="Volver al menu principal",
                           command=lambda:self.callback()).pack()
        self.controller=controller        

class PageTwo(tk.Frame):
    def callback(self):
        print("PageTwo: spinbox values: %d %d"%(self.controller.varSpin1,self.controller.varSpin2))
        self.controller.show_frame(StartPage)   
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="CALCULO ACTIVIDADES", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, width=20, text="Volver al menu principal",
                           command=lambda:self.callback()).pack()
        self.controller=controller

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

Upvotes: 0

deborah-digges
deborah-digges

Reputation: 1173

Since each window you create, is an instance of a class that has a reference to the controller, variables may be passed between windows by setting a value on the controller.

For example, in a window created from the PageOne, you can set a value on the controller like this: In init, make sure you store a reference to the controller in both classes PageOne and PageTwo:

self.controller = controller

At the point you want to pass a variable you can set it on the controller object:

self.controller.value = "value"

In the window created from PageTwo, you can access this value like this:

value_from_other_window = self.controller.value

To answer your other question, to access the value from a spinbox, you need to have a reference to the spinbox object. I would suggest you keep these as instance variables of the classes PageOne and PageTwo:

self.test1 = tk.Spinbox(self, values=(1, 2, 4, 8))

When you need to access the value, you can call:

self.test1.get()

You probably shouldn't be having two classes PageOne and PageTwo as each of these seem to have exactly the same code, but for the label text. You could consider adding another parameter to init, which is the label text.

Upvotes: 2

Related Questions