How to use tkinter entry .get() fuction in another class - python-3.x

I'm struggling to get a variable entry getter from another class, i know i have to pass the instance of the class im getting the variable from, but how would i use the actual variable in the class i would like to use it in?
Here is the class:
class NewEmployee:
def __init__(self, master):
self.master = master
self.master.title("Jans Corp")
self.master.configure(background="lightgrey")
self.master.geometry("300x500")
self.FirstNameEntry = tk.Entry(self.master)
self.SurnameEntry = tk.Entry(self.master)
self.AgeEntry = tk.Entry(self.master)
self.PostcodeEntry = tk.Entry(self.master)
Here is where i'd like to use self.FirstNameEntry.get()
class Database(NewEmployee):
def __init__(self, master):
conn = sqlite3.connect(':memory:')
c = conn.cursor()
def addEmployees(self):
with conn:
c.execute("INSERT INTO Employees VALUES (:first, :last, :age)",
{'first':emp.first, 'last':emp.last, 'age':emp.age, }) <-----
Here you can see i have added the instance of the class im want to get the info from but do not know how to call "FirstNameEntry.get()" in the database class.
Would i have to use NewEmployee.FirstNameEntry() or would it be something else?

Here you can see i have added the instance of the class im want to get the info from...
That is not how classes work. Inheritance is a "is a" relationship. Your code is saying that your Database class "is a" NewEmployee, which is clearly not true. Databases are not employees.
The way to do this is to pass an instance of Employee to your addEmployee method. Roughly speaking, it looks like this:
emp = NewEmployee()
db = Database()
db.addEmployee(emp)
That means that you need to modify addEmployee to accept the employee to be added, and to call the get method of the widgets:
class Database():
...
def addEmployee(self, emp):
with conn:
c.execute(..., {'first':emp.FirstNameEntry.get(),...})
Note that it's rather unusual to have something like an Employee class that has widgets in it. Usually it just has data, and you would have a separate class to represent the GUI (ie: you have one GUI but many employees)
For example, your GUI class would be:
class EmployeeForm():
def __init__(self):
...
self.firstNameEntry = tk.Entry(...)
...
You would create one instance of this at the start of your program:
class TheApplication():
def __init__(self):
...
self.employeeForm = EmployeeForm()
...
You might then have an Employee class that looks something like this:
class Employee():
def __init__(self, first, last, etc):
self.first = first
self.last = last
self.etc = etc
Then, you might add a getEmployee method in your GUI class like this:
class EmployeeForm():
...
def getEmployee(self):
first = self.firstEntry.get()
last = self.lastEntry.get()
etc = self.etcEntry.get()
return Employee(first, last, etc)
Then, somewhere in your code -- maybe the "save" button on the form or application -- you would do something like this:
employee = self.employeeForm.getEmployee()
db.addEmployee(employee)

That's not another class ... that's a subclass. You would call it the same way you defined it: with self. Also, remember that with all subclasses, you have to call the parent __init__ from the subclass.
class Database(NewEmployee):
def __init__(self, master):
super().__init__(master) #call parent __init__
conn = sqlite3.connect(':memory:')
c = conn.cursor()
def addEmployees(self):
with conn:
c.execute("INSERT INTO Employees VALUES (:first, :last, :age)",
{'first':self.FirstNameEntry.get(), 'last':self.SurnameEntry.get(), 'age':self.AgeEntry.get(), })

Related

How to inherit an updated attribute in Python

I'm trying to define two clases, A and B, with B being the child, as in the following code
class A:
def __init__(self, att_A=False):
self.att_A = att_A
def call_B(self):
b = B()
class B(A):
def __init__(self):
super().__init__()
print(f'{self.att_A=}')
a = A()
a.att_A = True
a.call_B()
B does properly inherit the methods and attributes at the time of definition but I want it to also access the values of self.att_A even when they were updated after being initiated.
Is it possible to do that or is there any workaround, like forwarding the attribute as a method parameter?
I have tried deffining att_A as a class attribute but still B cannot access the updated value

How Can I Dynamically Create Python Class Instances Using a List?

I am trying to understand how to dynamically create instances of a python class.
The simple example below shows how to create a class instance
class Person:
def __init__(self, name):
self.name = name
emmy = Person("Emmy")
niels = Person("Niels")
print(emmy.name)
print(niels.name)
If I want to iterate through a list to create class instances, how can I dynamically execute a command the same as
emmy = Person("Emmy")
I have tried to dynamically do it with something like eval or exec method so that I can iterate through a list and be able to call the class instance name using item name from list.
class Person:
def __init__(self, name):
self.name = name
people = ["Emmy","Niels"]
for item in people:
eval('item = Person(item)')
print(emmy.name)
print(niels.name)
Thanks in advance for any suggestions.
I found a solution creating a string variable to use as a command for the exec function.
class Person:
def __init__(self, name):
self.name = name
people = ["Emmy","Niels"]
for item in people:
a = str(item) + ' = Person("' + str(item) + '")'
exec(a)
print(Emmy.name)
print(Niels.name)

Trying to figure out how to pass variables from one class to another in python while calling a class from a dictionary

So I am getting used to working with OOP in python, it has been a bumpy road but so far things seem to be working. I have, however hit a snag and i cannot seem to figure this out. here is the premise.
I call a class and pass 2 variables to it, a report and location. From there, I need to take the location variable, pass it to a database and get a list of filters it is supposed to run through, and this is done through a dictionary call. Finally, once that dictionary call happens, i need to take that report and run it through the filters. here is the code i have.
class Filters(object):
def __init__ (self, report, location):
self.report = report
self.location = location
def get_location(self):
return self.location
def run(self):
cursor = con.cursor()
filters = cursor.execute(filterqry).fetchall()
for i in filters:
f = ReportFilters.fd.get(i[0])
f.run()
cursor.close()
class Filter1(Filters):
def __init__(self):
self.f1 = None
''' here is where i tried super() and Filters.__init__.() etc.... but couldn't make it work'''
def run(self):
'''Here is where i want to run the filters but as of now i am trying to print out the
location and the report to see if it gets the variables.'''
print(Filters.get_location())
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(),
'filter_2': Filter2(),
'filter_3': Filter3()
}
My errors come from the dictionary call, as when i tried to call it as it is asking for the report and location variables.
Hope this is clear enough for you to help out with, as always it is duly appreciated.
DamnGroundHog
The call to its parent class should be defined inside the init function and you should pass the arguments 'self', 'report' and 'location' into init() and Filters.init() call to parent class so that it can find those variables.
If the error is in the Filters1 class object, when you try to use run method and you do not see a location or a report variable passed in from parent class, that is because you haven't defined them when you instantiated those object in ReportFilters.fd
It should be:
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(report1, location1),
'filter_2': Filter2(report2, location2),
'filter_3': Filter3(report3, location3)
}
class Filter1(Filters):
def __init__(self, report, location):
Filters.__init__(self, report, location)
self.f1 = None
def run(self):
print(self.get_location())

How can i avoid repetitive calling of instance variables in Subclasses?

i was wondering if there is a way in Python to get rid of repetitive calling of instance variables , when creating subclasses.
for example:
class Name:
def __init__(self,first,last):
self.first = first
self.last = last
def __str__(self):
return f"Users first name is : {self.first}, Users last name is: {self.last}"
def __repr__(self):
return f"first:{self.first}, last:{self.last}"
class Cash(Name):
def __init__(self,first,last,cash):
super().__init__(first,last)
self.cash = cash
def full(self):
return f"{self.first},{self.last},{self.cash}"
c1 = Cash("Exa","Cool",200)
print(c1.full())
Is it possible to call all instance variables (self.first,self.last...) from "Name", without having to mention them in the constructor of "Cash"
something like:
class Cash(Name):
def __init__("all from Name" + new one ("cash" in this example)):
super().__init__("all from Name")
self.cash = cash
In your case, you can change the Cash class to look like this:
class Cash(Name):
def __init__(self,*inputs):
super(Cash,self).__init__(*inputs[:-1])
self.cash = inputs[-1]
def full(self):
return f"{self.first},{self.last},{self.cash}"
but for a more general solution that covers all situations take a look at this similar question.

Need to call class method from different class without initialization of the first class or some other way around it

I have a small problem with my code.
There are two classes. First one creates a window with a Options button. Upon clicking the button, the second class is called and creates another window with an Ok button. Let's say there is also a checkbox, which changes the background color to black or something like that. After clicking the button, whatever changes were made in the options are stored into a file and the second window is closed.
All of this works fine. My problem is that now I need to call method update_init from the first class that will apply those changes to the MainWindow. The code below shows my first solution to this problem, but from what I understand, by using second mainloop I create second thread, which should be avoided.
class MainWindow:
def __init__(self, master):
self.master = master
self.options_btn = tk.Button(self.master, text="Options", command=self.open_options)
self.options_btn.pack()
self.options_window = None
def open_options(self):
options_master = tk.Toplevel()
self.options_window = OptionsWindow(options_master)
options_master.mainloop()
lst = meta_load() # loads changes from a file
self.update_init(lst)
def update_init(self, lst):
#code
class OptionsWindow:
def __init__(self, master):
self.master = master
self.ok_btn = tk.Button(self.master, text="OK", command=self.update_meta)
self.ok_btn.pack()
def update_meta(self):
meta_save(12) # saves changes into a file
self.master.destroy()
main_master = tk.Tk()
main_master.minsize(width=1280, height=720)
b = MainWindow(main_master)
main_master.mainloop()
My second solution was to just put both classes into one, but the code is quite messy if I do so.
Can I somehow call the method update_init (which is in the MainWindow class) from the OptionsWindow class without initializing new MainWindow class window? Or is there any other way to deal with this? I would appreciate any help.
I am sorry if this is too specific, I've tried to make it as general as possible, but it's a very specific problem and I couldn't find much information about it anywhere on the internet.
In general you can call a class method from anywhere you want and pass anything to it without initialisation of that class's instance, thanks to objective nature of python, but beware of self dependencies! Although, I don't think that's a good practice.
class A:
def __init__(self):
self.foo = 'foo'
def return_foo(self):
return self.foo
class B:
def __init__(self):
self.bar = 'bar'
print('Ha-ha Im inited!')
def return_bar(self):
try:
return self.bar
except AttributeError:
return 'bar'
def test():
a = A()
# b = B()
return_bar = getattr(B, 'return_bar', None)
if callable(return_bar):
print('%s%s' % (a.return_foo(), return_bar(None)))
test()
Links:
getattr
callable

Resources