What would be the best way to reference widgets inside instances of other classes?
I think the most common-use case for this is reusing an object an indefinite number of times, as it looks like you're trying to do with some listboxes that are set up inside a frame. In this case, I think you should put as much repeatable code as possible in the subclass and create a method in it that returns just what you want. When you create an instance of the subclass inside your main class, then you can access its methods when you need to (ie, selectedColumns.get_all_listbox_values()
).
One thing you should keep in mind is that the instance won't work right if you create it and grid it on the same line:
No
selectedColumns = ColumnSelector(self, "Columns to include in export", (), removeSelected).grid(column=0, row=0, sticky=(N,W))
selectedColumns.get_all_listbox_values()
>>> AttributeError: 'NoneType' object has no attribute 'get_all_listbox_values'
Yes
selectedColumns = ColumnSelector(self, "Columns to include in export", (), removeSelected)
selectedColumns.grid(column=0, row=0, sticky=(N,W))
selectedColumns.get_all_listbox_values()
>>> (0, 1, 2, etc)
Below is an example of one way to set up your script. There's a main class (App
) and another class that inherits from Frame (MyEntry
) that can be used in App
multiple times. There's one button in the App
class that prints out results from a method in MyEntry
that calculates a couple of values. Hopefully it helps to give you some ideas about structuring your code.
class App(Frame):
'''the main window class'''
def __init__(self, parent):
Frame.__init__(self, parent)
# create instances of MyEntry, passing whatever operators as args
# we can make as many of these instances as we need in just a couple of lines
# and it retains readability
self.divide = MyEntry(self, '/')
self.multiply = MyEntry(self, '*')
self.divide.pack()
self.multiply.pack()
Button(self, text='Calculate', command=self._print_result).pack()
def _print_result(self):
'''print the return of the calculate method from the instances of
the MyEntry class'''
print self.divide.calculate()
print self.multiply.calculate()
class MyEntry(Frame):
'''creates two entries and a label and has a method to calculate
the entries based on an operator'''
def __init__(self, parent, operator): # include the operator as an arg
Frame.__init__(self, parent)
# make an instance variable from the operator to access it between methods
self.operator = operator
# make two entries
self.num1 = Entry(self)
self.num2 = Entry(self)
# grid the entries and a label which contains the operator
self.num1.grid(row=0, column=0)
Label(self, text=self.operator).grid(row=0, column=1)
self.num2.grid(row=0, column=2)
def calculate(self):
'''return the value of the two entries based on the operator specified'''
if self.operator is '/':
return int(self.num1.get()) / int(self.num2.get())
elif self.operator is '*':
return int(self.num1.get()) * int(self.num2.get())
else:
return
root = Tk()
App(root).pack()
mainloop()