-1

I have tried to condense the code down as much as possible to make it clear what I am asking...

I have a variable called chosen_name, determined in a class called booking_frame, that I would like to access in the calendar_frame class.

Therefore, it would be obvious for calendar_frame to inherit the attributes of booking_frame - however, I believe (I'm probably completely wrong lol) that calendar_frame has to inherit the characteristics of Frame so that the whole program functions correctly.

The reason that calendar_frame is a completely separate class is so that it can appear as a different frame.

Extremely grateful for any help given :)


# import tkinter modules
from tkinter import *
from tkinter import ttk
import tkinter.font as tkFont
from PIL import ImageTk, Image
from tkcalendar import *



# define self
class tkinterApp(Tk):

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

        Tk.__init__(self, *args, **kwargs)

        # creating a container
        container = Frame(self)
        container.pack(side = "top", fill = "both", expand = True)

        container.grid_rowconfigure(0, weight = 1)
        container.grid_columnconfigure(0, weight = 1)

        # initialising frames to an empty array
        self.frames = {}

        menu_bar = Menu(container)
        main_menu = Menu(menu_bar)

        menu_bar.add_cascade(label="Main Menu", menu=main_menu)
        main_menu.add_command(label="Welcome page", command=lambda: self.show_frame(welcome_frame))
        main_menu.add_command(label="Book a vehicle", command=lambda: self.show_frame(booking_frame))
        main_menu.add_command(label="Register as new user", command=lambda: self.show_frame(register_frame))

        Tk.config(self, menu=menu_bar)

        for F in (welcome_frame, booking_frame, register_frame, calendar_frame):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(welcome_frame)

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


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

        welcome = Label(self, text="Hello, please use the menu above to navigate the interface")
        welcome.grid(row=0, column=4, padx=10, pady=10)

class register_frame(Frame):

    def __init__(self, parent, controller):

        Frame.__init__(self, parent)

        register_label = Label(self, text="New user - enter your details below to use the Collyer's car park.")
        register_label.grid()


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

        chosen_name = "Steve"


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

    print(booking_frame.chosen_name)


app = tkinterApp()
app.geometry("1000x800")
app.title("Collyer's Car Park")
app.mainloop()

  • 1. Look for some resources on the scope of variables. `chosen_name = "Steve"` sets a _local variable_ in the `booking_frame` constructor. It doesn't exist before the constructor is called, or after it runs. 2. Even if you changed it to `self.chosen_name = "Steve"` to make it an instance variable, an instance of `calendar_frame` has no relation to an instance of `booking_frame`. 3. You can have `calendar_frame` inherit `booking_frame` if that's what you want to do. There's no rule that says inheritance only works for one generation. – Pranav Hosangadi Feb 08 '21 at 23:10
  • 1
    Please supply the expected [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) (MRE). You have a lot of irrelevant code in a post that asks only about scoping and cross-class capabilities. Remove the Tkinter references and all of the GUI overhead. Remove the extra classes. *Then* describe just how you want to access the variable in another class. Is that a method, an assignment to a class attribute, or other use? – Prune Feb 08 '21 at 23:12
  • Does this answer your question? https://stackoverflow.com/a/32213127/7432 – Bryan Oakley Feb 08 '21 at 23:51

2 Answers2

1

First you need to change local variable chosen_name to instance variable self.chosen_name inside booking_frame class, otherwise it cannot be accessed outside the class:

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

        self.chosen_name = "Steve"  # changed to instance variable

Then you can access it via controller.frames[booking_frame].chosen_name inside calendar_frame class:

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

        print(controller.frames[booking_frame].chosen_name)
acw1668
  • 40,144
  • 5
  • 22
  • 34
0

Inheritance is to model relationships of objects which behave the same ("IS A" relationship). It is not meant to share data between objects.

A possible solution to your problem is to use a third object, that would be shared between booking_frame and calendar_frame.

This object can be a Python dictionary for example ; you can pass it to all your "frame" objects, or you can maybe decide to have it global (not very academic, for sure, but quick and dirty):

GLOBAL_STATE = {}

class booking_frame(Frame):
    ...
    GLOBAL_STATE["chosen_name"] = "Steve"

class calendar_frame(Frame):
    ...
    print(GLOBAL_STATE.get("chosen_name"))

I hope you can see now how you can refactor your code to share data between those objects.

mguijarr
  • 7,641
  • 6
  • 45
  • 72
  • Thanks @mguijarr I did as you said, but when I call `controller.show_frame(calendar_frame)` within the `booking_frame`, I get an error: `KeyError: `. – Benjamin McDowell Feb 08 '21 at 23:35