Python Forum
[Tkinter] Use function from other class (Tkinter) - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [Tkinter] Use function from other class (Tkinter) (/thread-29037.html)



Use function from other class (Tkinter) - zarize - Aug-15-2020

Hi guys,

I would like to use function defined in main class, in another file/class - Rents.py/class Rents_tab(Frame)

MAIN.PY
import pandas as pd
from tkinter import *
from tkinter.ttk import *
from rents import *

class Application(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        #set window size
        parent.geometry("1600x1600")
        #Set the header of application
        parent.title("My first application")
        self.notebook = Notebook(self)
        self.notebook.grid(row=1, column=1)
        #DETERMINING TAB NAMES
        comment_tab = Comments_tab(self.notebook)
        rents_tab = Rents_tab(self.notebook)

        
        #Assign tab names
        self.notebook.add(rents_tab, text="Rents")
        def Load_Data(self):
            excel_file_mhs = pd.read_csv(r'C:\Users\USER\Desktop\project_))\September 2019.csv', encoding='cp1252')
            contr_select = excel_file_mhs.loc[excel_file_mhs['Country Name']== self.entry_country.get()]
            loca_select = contr_select.loc[contr_select['Location Name']== self.entry_location.get()]
            final_select = loca_select.loc[loca_select['Survey Date'] == self.entry_survey.get()]
            return final_select
Rents.py - In that file i want to use the function Load_Data()

import pandas as pd
from tkinter import *
from main import *
from tkinter.ttk import *

class Rents_tab(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        
        
        entry_label_country = Label(self, text="Please provide country: ")
        entry_label_country.grid(row=1, column=1)
        entry_country = Entry(self, width=30)
        entry_country.grid(row=1, column=2)
        entry_country.insert(0, "Poland") #Default displayed text
        
        entry_label_location = Label(self, text="Please provide location: ")
        entry_label_location.grid(row=2, column=1)
        entry_location = Entry(self, width=30)
        entry_location.grid(row=2, column=2)
        entry_location.insert(0, "Warsaw") #Default displayed text

        entry_label_survey = Label(self, text="Survey Date: ")
        entry_label_survey.grid(row=3, column=1)
        entry_survey = Entry(self, width=30)
        entry_survey.grid(row=3, column=2)
        entry_survey.insert(0, "2019") #Default displayed text
        
        # #Buttons
        test_button = Button(self, text="Show Data", command=Application().Load_Data)
        test_button.grid(row=3, column=3)
Could you please guide me, what i am doing wrong?

Using command=Application().Load_Data) gives me output
Error:
TypeError: __init__() missing 1 required positional argument: 'parent'
Using command=Application(self).Load_Data)
or
Using command=Application(parent).Load_Data) gives me output
Error:
AttributeError: 'Rents_tab' object has no attribute 'geometry'



RE: Use function from other class (Tkinter) - Yoriz - Aug-15-2020

Note: Namespace flooding with * imports

def Load_Data(self): indentation should be level with def __init__(self, parent):

Error:
TypeError: __init__() missing 1 required positional argument: 'parent'
is because when doing the following
class Rents_tab(Frame):
    def __init__(self, parent):
creating an instance of Rents_tab expects to be passed a variable for the parameter parent

Error:
AttributeError: 'Rents_tab' object has no attribute 'geometry'
is because when doing the following
class Application(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        #set window size
        parent.geometry("1600x1600")
an instance of Rents_tab is passed in as the parent into Application
so when it calls parent.geometry("1600x1600"), Rents_tab does not have the attribute 'geometry'


RE: Use function from other class (Tkinter) - zarize - Aug-15-2020

thank you :)

#EDIT

I have 1 more question... how can i access user's input from the Entry now?
If there is Entry in rents.py(another class)
entry_location.get()
How can i access it in main?
I thought that it could work but it dont:
print(Rents_tab.entry_location.get())


RE: Use function from other class (Tkinter) - Yoriz - Aug-15-2020

Application has been passed an instance of Rents_tab as the parent parameter.
add parent as an attribute to Application
class Application(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
inside of Application to access Rents_tab's entry_location you can use
self.parent.entry_location.get()



RE: Use function from other class (Tkinter) - zarize - Aug-15-2020

Thank you for your message.


I tried this:
    def test(self):
        print(self.parent.entry_location.get())
returned me:
Error:
AttributeError: 'Notebook' object has no attribute 'entry_location'



RE: Use function from other class (Tkinter) - Yoriz - Aug-15-2020

You have Notebook set as the parent not Rents_tab


RE: Use function from other class (Tkinter) - zarize - Aug-16-2020

I would really appreciate more explanation


RE: Use function from other class (Tkinter) - deanhystad - Aug-16-2020

I think you have two problems. The first problem is that Load_Data is a function inside Application.__init__ when it should be a method of Application. I don't know if this is a design decision or if you just got the indentation wrong. But if you want to call Load_Data from outside __init__ it needs to be fixed.

The second problem is there is some confusion about the relationship between Application and Rents_Tab. Why is Load_Data in Application? As currently written I see no reason why Load_Data is not a method in Rents_tab. Are you planning on changing Load_Data in a way that makes it dependent upon Application? Often Notebook is used as a way to provide different views into some data, data that is shared by multiple tabs in the notebook. Is that what's going to happen here? If so, you are currently not set up for that type of relationship.

If Rents_tab is just a view into part of Application, you need to define the relationship between the two. As things currently are, Rents_tab knows nothing about Application. It doesn't even have a handle to talk to Application. If Appliction has resources that Rents_tab needs to use, you need to either make Application a subclass of Notebook, or pass an Application object as an argument to Rents_tab.__init__
    def __init__(self, parent_view, application):
        Frame.__init__(self, parent_view)
        self.application = application  # Keep reference to Application object?
        ...
        # #Buttons
        test_button = Button(self, text="Show Data", application.Load_Data)

         



RE: Use function from other class (Tkinter) - zarize - Aug-17-2020

Thank you very much for your message :)
1)
Yes, it was by a mistake, i fixed it now.

2)My goal is to make an application which has a lot of tabs, and every single tab should have 1 seperate file designed for it(in general 9 tabs). Load_Data is in Application class, because i was thinking that it might be good to stack all functions in main file(Application class).
Purpose of this function is to gather data based on Entries provided by user and display it (later on)

3)
I wanted to treat Rents_tab as other 8 tabs, i would like to store the code down there and access it from the main class - Application