-2

(I'm using mac 10.8.5 and Python3 with PyCharm)

I have a tkinter GUI TestMain() class plus one PageOne() class and a PageTwo() class. I need PageOne() and PageTwo() to be different GUI windows cause they will handle different data. I minimized the code in order to set it as readable as possible. After many tests I tried to place the tk.StringVar() and a simple function in the global scope as you can see below, but there's still a problem.

import tkinter as tk

page1_label = tk.StringVar()
page2_entry = tk.StringVar()

def set_ebdata():
    data = page2_entry.get()
    page1_label.set(data)


class TestMain(tk.Tk):

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

        tk.Tk.wm_title(self, 'TEST GUI')
        container = tk.Frame(self)
        container.pack(side='top')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.configure(background='lightgrey')
            frame.grid(row=0, column=0, sticky='nswe')
        self.show_frame(PageOne)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


class PageOne(tk.Frame):

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

        frame_eb_data = tk.Frame(self, width=100, height=100, bg="orange", colormap="new")
        frame_eb_data.grid(row=0, column=0, sticky='w', padx=5, pady=5)
        frame_but_right = tk.Frame(self, width=240, height=60, bg="yellow", colormap="new")
        frame_but_right.grid(row=0, column=1, padx=5, pady=5, rowspan=2)
        lab_eb_data = tk.Label(frame_eb_data, background='#DDD4EF', textvariable=page1_label)
        lab_eb_data.grid(row=0, column=0, sticky='n')

        b_ebdata = tk.Button(frame_but_right, text="Page 2", width=10, height=2, command=lambda: controller.show_frame(PageTwo))
        b_ebdata.grid(row=3, column=0)


class PageTwo(tk.Frame):

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

        frame_buttons = tk.Frame(self, width=455, bg="#DDD4EF", colormap="new")
        frame_buttons.grid(row=0, column=0, padx=5, pady=5, sticky='e')
        frame_up_left = tk.Frame(self, width=485, height=260, bg="#89E3FA", colormap="new")
        frame_up_left.grid(row=1, column=0, sticky='w', padx=5, pady=5)

        b_data = tk.Label(frame_buttons, text='Example GUI', font='TrebuchetMS 30 bold', background="#DDD4EF")
        b_data.grid(row=0, column=0, padx=13, pady=5, sticky='w')

        b5 = tk.Button(frame_buttons, text='Set Text', command=lambda: set_ebdata)
        b5.grid(row=0, column=2, padx=5, pady=5, sticky='e')

        b6 = tk.Button(frame_buttons, text='Page 1', command=lambda: controller.show_frame(PageOne))
        b6.grid(row=0, column=3, padx=5, pady=5, sticky='e')

        label_2 = tk.Label(frame_up_left, text="Name:", font=("bold", 14))
        label_2.grid(row=1, column=0, sticky='e')
        entry_nombre_fld = tk.Entry(frame_up_left, width=40, textvariable=page2_entry)
        entry_nombre_fld.grid(row=1, column=1, columnspan=3, sticky='w')


app = TestMain()

app.mainloop()

When you run the program a window with a "Page 2" button (b_ebdata) appears, by clicking it you enter Page 2 window which has a "Set Text" button (b5), a "Page 1" button (b6) and an entry field (entry_nombre_fld).

I'd like to set the text I'll enter in the entry field (entry_nombre_fld) in the Page 1 label (lab_eb_data) by clicking the "Set Text" button (b5).

Could a solution be to put page1_label = tk.StringVar() into PageOne() class and page2_entry = tk.StringVar() into PageTwo() class and make those accessible by each other?

Any other suggestion ?

Thx in advance for your help!

Samuel
  • 109
  • 1
  • 2
  • 9
  • A class variable is accessed from anywhere within the script by `class.variableName` provided that the variable is always referred to with `self` within the class. – amitchone May 25 '18 at 16:13
  • 1
    you are trying to create your variables before your `Tk()` instance. You cannot create tk objects until `Tk()` has been initiated. – Mike - SMT May 25 '18 at 16:16
  • move your `StringVar()`'s into the main class as a class attribute and then refer to them with the controller argument in your other classes. Like this: `textvariable=controller.page1_label` – Mike - SMT May 25 '18 at 16:23

1 Answers1

1

I had to change a few things but for the most part the major solution is to move your StringVar()'s into the main class. Then next we can use the controller argument in the other 2 classes to manipulate the data.

I added a function on page 2 to deal with updating the the label StringVar. Because of this I deleted the other function you had for this.

I had to change your entry field to a class attribute so we can use its content in the new method. I also had to create a class attribute for the controller in page 2 so we can use the controller in the method as well.

Now there might be an easier way but this is what I managed with your code.

import tkinter as tk


class TestMain(tk.Tk):

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

        self.title('TEST GUI')
        # Moved StringVar()'s to the main class
        self.page1_label = tk.StringVar()
        self.page2_entry = tk.StringVar()
        container = tk.Frame(self)
        container.pack(side='top')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.configure(background='lightgrey')
            frame.grid(row=0, column=0, sticky='nswe')
        self.show_frame(PageOne)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

   # Deleted this function


class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        frame_eb_data = tk.Frame(self, width=100, height=100, bg="orange")
        frame_eb_data.grid(row=0, column=0, sticky='nsew', padx=5, pady=5)
        frame_but_right = tk.Frame(self, width=240, height=60, bg="yellow")
        frame_but_right.grid(row=1, column=0, padx=5, pady=5, sticky='nsew')
        lab_eb_data = tk.Label(frame_eb_data, background='#DDD4EF', textvariable=controller.page1_label)
        lab_eb_data.grid(row=0, column=0)

        b_ebdata = tk.Button(frame_but_right, text="Page 2", width=10, height=2, command=lambda: controller.show_frame(PageTwo))
        b_ebdata.grid(row=0, column=0)


class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        # Added the self.controller so the method below can use it.
        self.controller = controller
        frame_buttons = tk.Frame(self, width=455, bg="#DDD4EF", colormap="new")
        frame_buttons.grid(row=0, column=0, padx=5, pady=5, sticky='e')
        frame_up_left = tk.Frame(self, width=485, height=260, bg="#89E3FA", colormap="new")
        frame_up_left.grid(row=1, column=0, sticky='w', padx=5, pady=5)

        b_data = tk.Label(frame_buttons, text='Example GUI', font='TrebuchetMS 30 bold', background="#DDD4EF")
        b_data.grid(row=0, column=0, padx=13, pady=5, sticky='w')
        b5 = tk.Button(frame_buttons, text='Set Text', command= self.update_p2_label)
        b5.grid(row=0, column=2, padx=5, pady=5, sticky='e')
        b6 = tk.Button(frame_buttons, text='Page 1', command=lambda: controller.show_frame(PageOne))
        b6.grid(row=0, column=3, padx=5, pady=5, sticky='e')

        self.entry_nombre_fld = tk.Entry(frame_up_left, width=40)
        self.entry_nombre_fld.grid(row=1, column=1, columnspan=3, sticky='w')
        label_2 = tk.Label(frame_up_left, text="Name:", font=("bold", 14))
        label_2.grid(row=1, column=0, sticky='e')
    # Added this function to update the page1_label StringVar.
    def update_p2_label(self):
        self.controller.page1_label.set(self.entry_nombre_fld.get())


app = TestMain()
app.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79