Python Forum
Getting a variable from one class to another class
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Getting a variable from one class to another class
#1
As some of you know I've been working on improving my understanding of classes and methods on my project code. I've hit a roadblock that I'm not sure how to handle. I'm posting the whole script to show my setup. The roadblock is that I need to get the variable letter from the class Child2 to the database query in the class of Child3. The current script I have function call printing out the letter variable for testing. Is calling an outside function going to be the route I need to take? Or is there a way for me to call the class and get the variable to its destination? Any help would be much appreciated.
Thanks

#! /usr/bin/env python3.8
'''cookbook'''
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import string
import webbrowser
from functools import partial
from PIL import Image, ImageTk
from  modules import database as db, time_converter as tc

def link():
    '''Open Webbrowser'''
    webbrowser.open_new('http://recipes.phpshelf.net')

def get_letter(letter):
    '''none'''
    print(letter)

class RootWindow:
    '''RootWindow'''
    def __init__(self, master):
        self.master = master
        self.master.grid_columnconfigure(0, weight=1)
        self.master.rowconfigure(0, weight=1)

        self.logo_frame()
        self.letter_frame()
        self.container_frame()
        self.title_frame()
        self.recipe_frame()
        self.footer_frame()

        Child(self.logoframe, self.footerframe)
        Child2(self.letterframe)
        Child3(self.titleframe)

    def logo_frame(self):
        '''logo frame'''
        self.logoframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.logoframe.grid(column=0, row=0, sticky='new')
        self.logoframe.grid_columnconfigure(0, weight=3)

    def letter_frame(self):
        '''letterframe'''
        self.letterframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.letterframe.grid(column=0, row=1, sticky='new')
        for i in range(26):
            self.letterframe.grid_columnconfigure(i, weight=3)

    def container_frame(self):
        '''Container frame will hold two frames. Title frame and recipe frame'''
        self.containerframe = ttk.Frame(self.master)
        self.containerframe.grid(column=0, row=2, sticky='new')
        self.containerframe.grid_columnconfigure(0, weight=3)

    def title_frame(self):
        '''Title Frame'''
        self.titleframe = ttk.Frame(self.containerframe, border=5, relief='ridge')
        self.titleframe.grid(column=0, row=0, sticky='nw')
        self.titleframe.grid_columnconfigure(0, weight=3)

    def recipe_frame(self):
        '''Recipe Frame'''
        self.recipeframe = ttk.Frame(self.containerframe, border=5, relief='ridge')
        self.recipeframe.grid(column=1, row=1)
        self.recipeframe.grid_columnconfigure(0, weight=3)

    def footer_frame(self):
        '''footer'''
        self.footerframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.footerframe.grid(column=0, row=3, sticky='new')
        self.footerframe.grid_columnconfigure(0, weight=3)


class Child:
    '''Child'''
    def __init__(self, logoframe, footerframe):
        self.my_logo(logoframe)
        self.my_footer(footerframe)

    def my_logo(self, logoframe):
        '''logo'''
        load = Image.open('/home/johnny/Desktop/CookBook/images/cookbook_logo.png')
        render = ImageTk.PhotoImage(load)
        self.logo = ttk.Label(logoframe, image=render)
        self.logo.image = render
        self.logo.grid(column=0, row=0)


    def my_footer(self, footerframe):
        '''footer'''
        style = ttk.Style()
        style.map('Footer.TLabel', \
        foreground=[('pressed', 'firebrick'), ('active', 'red')], \
        background=[('pressed', '!disabled', 'gray86'), ('active', 'gray86')] \
        )
        style.configure('Footer.TLabel', foreground='blue', \
        font=('Times', 12, 'normal', 'underline'))
        self.footer = ttk.Button(footerframe, text='My Footer', \
        style='Footer.TLabel', cursor='hand2', command=link)
        self.footer.grid(column=0, row=0, ipady=3)


class Child2:
    '''Child2'''
    #pylint: disable=R0903
    def __init__(self, letterframe):
        self.lettermenu(letterframe)

    def lettermenu(self, letterframe):
        '''lettermenu'''
        letters = string.ascii_uppercase
        i = 0
        style = ttk.Style()
        style.configure('Btn.TButton', width=4)
        for letter in letters:
            self.button = ttk.Button(letterframe, text=letter, style='Btn.TButton', \
            command=partial(get_letter, letter))
            self.button.grid(column=i, row=0, sticky='new')
            i += 1

class Child3:
    #pylint: disable=R0903
    '''Child3 Class'''
    def __init__(self, titleframe):
        self.title_menu(titleframe)

    def title_menu(self, titleframe):
        '''title menu'''
        data = db.Database().title_query(letter='a')

        canvas = tk.Canvas(titleframe)
        scrollbar = ttk.Scrollbar(titleframe, orient='vertical', command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)

        scrollable_frame.bind(
            '<Configure>',
            lambda e: canvas.configure(scrollregion=canvas.bbox('all'))
        )

        canvas.create_window((0, 0), window=scrollable_frame, anchor='nw')
        canvas.configure(yscrollcommand=scrollbar.set)
        letter = 'a'
        if data:
            self.old_letter = letter

        if not data:
            msg = messagebox.showerror(title='No listing', \
            message='Sorry, there have not been any recipes added starting with ' + letter)
            if msg == 'ok':
                self.title_menu(self.old_letter)

        style = ttk.Style()
        style.map('L.TLabel', \
        background=[('pressed', '!disabled', 'gray86'), ('active', '#ffffee')], \
        foreground=[('pressed', 'red'), ('active', 'red')])

        style.configure('L.TLabel', relief='flat', padding=2, foreground='blue')

        for recipe_id, title in data:
            title = ttk.Button(scrollable_frame, text=title.title(), \
            style='L.TLabel', cursor='hand2')
            title.grid(column=0, row=recipe_id, sticky='nw')

        scrollbar.grid(column=0, row=0, sticky='nsw')
        canvas.grid(column=1, row=0, sticky='nsw')


def main():
    '''main'''
    root = tk.Tk()
    root.title('Johnny\'s CookBook')
    root.resizable(width=False, height=False)
    RootWindow(root)
    root.mainloop()

if __name__ == '__main__':
    main()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#2
Can you be more specific about the classes you are reffering to. Ofcourse you can use variables as argument in classes. Just like you did here:

class RootWindow:
    '''RootWindow'''
    def __init__(self, master):
        self.master = master
        self.master.grid_columnconfigure(0, weight=1)
master is a variable here passed trough.
- Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid. Albert Einstein
Reply
#3
example:
class control:
    def __init__(self):
        zz = class1().parrot()
        c2 = class2().display_it(zz)

# or you can do it this way:
#     def __init__(self):
#         zz = class1()
#         val = zz.parrot()
#         c2 = class2()
#         c2.display(val)

class class1:
    def __init__(self):
        pass

    def parrot(self):
        return "He's Resting"

class class2:
    def __init__(self):
        pass

    def display_it(self, what):
        print(what)

if __name__ == '__main__':
    control()
results:
Output:
He's Resting
Reply
#4
I understand the concept of your example Larz60+.
So it's acceptable to have functions with classes?
I was under the impression that functions should be outside the class and only methods are within.
I will have to do a little bit of rewriting my code but, that's okay.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#5
Quote:So it's acceptable to have functions with classes?
you can indeed. usually a function uses (instantiates) a class, but a class can instantiate another class.
calling a routine a function or a class (to me at least) has value as you know if it's a method, it's part of a class, function not.
They operate the same with an exception. A method has visibility of (inherited) variables created in the __init__, or from an inherited class class ziggy(tkinter): tkinter inherited by ziggy.

If you think of a class as a rubber stamp, it will make it come clear.
def funca:
   tkinner = tk.Tk() # (a copy of class tk)

def funcb:
   tkinner = tk.Tk() # (another (and unique) copy of class tk)
finally, everything is a class in python. Try it:
>>> a = 1
>>> type(a)
<class 'int'>
>>> type(1)
<class 'int'>
>>> b = 'hello'
>>> type(b)
<class 'str'>
>>> def zz():
...     return 'hello'
... 
>>> type(zz)
<class 'function'>
>>> f = zz()
>>> f
'hello'
>>> type(f)
<class 'str'>
>>>
Reply
#6
Just wanted to post what I came up with. Maybe it will help someone in the future.
#! /usr/bin/env python3.8
'''Docstring'''

###### Do the imports ######
import tkinter as tk
from tkinter import ttk, messagebox
import string
from functools import partial
from PIL import Image, ImageTk
from  modules import database as db


###### Intiate the window ######
class RootWindow:
    '''Docstring'''
    def __init__(self, master):
        self.master = master
        self.master.columnconfigure(0, weight=1)
        self.master.rowconfigure(0, weight=1)


        ###### Intiate all of our main containerframes ######
        self.logo_frame()
        self.letter_frame()
        self.container_frame()
        self.title_frame()
        self.recipe_frame()
        self.footer_frame()

        ###### Initate the widgets ######
        Child(self.logoframe, self.footerframe)
        Child2().lettermenu(self.letterframe, self.containerframe)
        Child3().titlemenu(self.containerframe)

    ###### This sets all the container frames ######
    ###### Need to create a class for generic ######
    ###### frames to eliminate repetitive code #####
    def logo_frame(self):
        '''logo frame'''
        self.logoframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.logoframe.grid(column=0, row=0, sticky='new')
        self.logoframe.grid_columnconfigure(0, weight=3)

    def letter_frame(self):
        '''letterframe'''
        self.letterframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.letterframe.grid(column=0, row=1, sticky='new')
        for i in range(26):
            self.letterframe.grid_columnconfigure(i, weight=3)

    def container_frame(self):
        '''Container frame will hold two frames. Title frame and recipe frame'''
        self.containerframe = ttk.Frame(self.master)
        self.containerframe.grid(column=0, row=2, sticky='nw')
        self.containerframe.grid_columnconfigure(0, weight=3)

    def title_frame(self):
        '''Title Frame'''
        self.titleframe = ttk.Frame(self.containerframe, border=5, relief='ridge')
        self.titleframe.grid(column=0, row=0, sticky='nw')
        self.titleframe.grid_columnconfigure(0, weight=3)

    def recipe_frame(self):
        '''Recipe Frame'''
        self.recipeframe = ttk.Frame(self.containerframe, border=5, relief='ridge')
        self.recipeframe.grid(column=1, row=1)
        self.recipeframe.grid_columnconfigure(0, weight=3)

    def footer_frame(self):
        '''footer'''
        self.footerframe = ttk.Frame(self.master, border=5, relief='ridge')
        self.footerframe.grid(column=0, row=3, sticky='new')
        self.footerframe.grid_columnconfigure(0, weight=3)

###### This class defines and displays header and footer ######
class Child:
    '''logo'''
    def __init__(self, logoframe, footerframe):
        self.my_logo(logoframe)
        self.my_footer(footerframe)

    def my_logo(self, logoframe):
        '''doc'''
        load = Image.open('/home/johnny/Desktop/CookBook/images/cookbook_logo.png')
        render = ImageTk.PhotoImage(load)
        self.logo = ttk.Label(logoframe, image=render)
        self.logo.image = render
        self.logo.grid(column=0, row=0)

    def my_footer(self, footerframe):
        '''footer'''
        style = ttk.Style()
        style.map('Footer.TLabel', \
        foreground=[('pressed', 'firebrick'), ('active', 'red')], \
        background=[('pressed', '!disabled', 'gray86'), ('active', 'gray86')] \
        )
        style.configure('Footer.TLabel', foreground='blue', \
        font=('Times', 12, 'normal', 'underline'))
        self.footer = ttk.Button(footerframe, text='My Footer', \
        style='Footer.TLabel', cursor='hand2')
        self.footer.grid(column=0, row=0, ipady=3)


###### Class produces the letter menu ######
class Child2:
    '''doc'''
    def __init__(self):
        pass

    def lettermenu(self, letterframe, containerframe):
        '''lettermenu'''
        letters = string.ascii_uppercase
        i = 0
        style = ttk.Style()
        style.configure('Btn.TButton', width=4)
        for letter in letters:
            button = ttk.Button(letterframe, text=letter, style='Btn.TButton', \
            command=partial(Child3().titlemenu, containerframe, letter=letter))
            button.grid(column=i, row=0, sticky='new')
            i += 1


###### This class retrieves and displays recipe titles ######
class Child3:
    '''doc'''
    def __init__(self):
        pass

    def titlemenu(self, containerframe, letter='a'):
        '''title menu'''

        ###### Query the database for recipe titles from our letter menu defaults to a ######
        data = db.Database().title_query(letter=letter)

        ###### Create the canvas and scrollbar ######
        canvas = tk.Canvas(containerframe)
        scrollbar = ttk.Scrollbar(containerframe, orient='vertical', command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)

        scrollable_frame.bind(
            '<Configure>',
            lambda e: canvas.configure(scrollregion=canvas.bbox('all'))
        )

        canvas.create_window((0, 0), window=scrollable_frame, anchor='nw')
        canvas.configure(yscrollcommand=scrollbar.set)

        ###### If there are not any results returned, display message ######
        if not data:
            msg = messagebox.showerror(title='No listing', \
            message='Sorry, there have not been any recipes added starting with ' + letter)
            if msg == 'ok':
                return True
        else:
            ###### Setup our look for the recipe menu ######
            style = ttk.Style()
            style.map('L.TLabel', \
            background=[('pressed', '!disabled', 'gray86'), ('active', '#ffffee')], \
            foreground=[('pressed', 'red'), ('active', 'red')])

            style.configure('L.TLabel', relief='flat', padding=2, foreground='blue')

            ###### Loop through and display the return results from the database ######
            for recipe_id, title in data:
                title = ttk.Button(scrollable_frame, text=title.title(), \
                style='L.TLabel', cursor='hand2')
                title.grid(column=0, row=recipe_id, sticky='nw')

            scrollbar.grid(column=0, row=0, sticky='nsw')
            canvas.grid(column=1, row=0, sticky='nsw')
def main():
    '''Docstring'''
    root = tk.Tk()
    RootWindow(root)
    root.mainloop()

if __name__ == '__main__':
    main()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#7
Thank you for sharing.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Video [PyQt] Get a executable file (.exe) from a .py file add a promoted class in a QWidget MiguelonReyes 0 614 Oct-17-2023, 11:43 PM
Last Post: MiguelonReyes
  [Tkinter] Take the variable of a cursor class delcencen 2 1,149 Feb-13-2023, 05:19 AM
Last Post: deanhystad
Lightbulb Using Tkinter With Concurrent.Futures / ThreadPoolExecutor Class AaronCatolico1 1 1,417 Dec-14-2022, 08:01 PM
Last Post: deanhystad
  [PyQt] CustomSortFilterProxyModel Class Using hasantr 2 1,167 Dec-02-2022, 01:57 PM
Last Post: hasantr
Bug [Tkinter] CanĀ“t create a class for frames ThomasFab 5 1,941 Sep-28-2022, 08:44 PM
Last Post: deanhystad
Lightbulb [Tkinter] Tkinter Class Import Module Issue AaronCatolico1 6 2,970 Sep-06-2022, 03:37 PM
Last Post: AaronCatolico1
  [Tkinter] define entry via class on a loop drSlump 9 3,375 Oct-27-2021, 05:01 PM
Last Post: deanhystad
  [Kivy] Acces atributes from a button defined in a class inside the .kv Tomli 2 2,052 Jun-10-2021, 01:05 AM
Last Post: Tomli
  [Tkinter] Modify Class on Button Click KDog 4 3,903 May-11-2021, 08:43 PM
Last Post: KDog
Question [PyQt] Need help with class composition / multiple inheritance / polymorphism (?) Alfalfa 4 3,014 May-11-2021, 12:55 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020