I'm creating a Python (3.4.3) - tkinter program and am wondering whether it is possible to reference a def
(self.get_details) from inside another class
for a button's command. I haven't been able to find an answer to this problem anywhere, so I figured I'd just ask.
Example:
import tkinter as tk
...
class Widgets(tk.Frame):
def __init__(self, parent):
tk.Frame.__init___(self, parent)
self.parent = parent
self.initUI()
def initUI():
# Lots of other different tkinter widgets go here
self.button = tk.Button(command=App(get_details))
self.button.pack()
class PopUp(tk.TopLevel): ....
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def get_details(self):
# Complete a function
def initUI(self):
self.parent.title("My Application")
self.style = Style()
self.style.theme_use("default")
self.pack()
self.widgets = Widgets(self)
self.widgets.pack(side="top", anchor="center", fill="both", expand=True)
if __name__ == "__main__":
root = tk.Tk()
App(root).pack(side="top", fill="both", expand=True)
root.resizable(0,0)
root.mainloop()
So I would like a button which belongs to the class Widgets()
to call a command that is def get_details(self)
which belongs to the class App()
, which has the Widgets()
class packed inside it.
I hope I was descriptive enough, it is fairly hard to word this problem. I am still kind of new to Python in general. Thanks!
Edit:
As suggested I changed it to self.parent.get_details()
, which worked! However when I reference a tkinter widget from the Widgets()
class inside def get_details()
for example: self.button
, I get:
AttributeError: 'App' object has no attribute 'button'
So I tried referencing the button as: self.parent.button
, to which I received:
AttributeError: 'tkapp' object has no attribute 'button'
How should I be calling/referencing the button? Thanks!
We can perform a certain action with the help of a Button that encapsulates the function and the objects. However, there might be cases when we want to perform multiple operations with a single button. This can be achieved by defining the lambda functions which target multiple events or callback in the application.
The Tkinter button has only one command property so that multiple commands or functions should be wrapped to one function that is bound to this command .
"__init__" is a reseved method in python classes. It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.
In App
, you create a Widgets
object and save a reference to it named self.widgets
. When you do so, you pass a reference to that App
object into the Widgets
object. That App
instance reference is saved within the Widgets
object as self.parent
. Keep in mind that these two uses of self
refer to different objects: while in App
, self
refers to the current instance of that App
object. While in Widgets
, self
refers to the current instance of that Widgets
object. To refer to something that's inside the other class, you have to use the proper reference and follow the path.
In an App
instance:
self this App instance
.widgets the Widgets instance it contains
.button the button in that Widget instance
In a Widgets
instance:
self this Widgets instance
.parent the App object that created this Widgets object
.get_details the get_details function in the parent App object
In the following, I've fixed your code's leftover bits (...
causing syntax errors, Style
not defined, etc.) and provided a small example of how to reference each object from the other one. The button initially says "hello", which you can change to "goodbye" by clicking it.
import tkinter as tk
class Widgets(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
# Lots of other different tkinter widgets go here
self.button = tk.Button(text='hello', command=self.parent.get_details)
self.button.pack()
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def get_details(self):
self.widgets.button.config(text='goodbye')
def initUI(self):
self.parent.title("My Application")
self.pack()
self.widgets = Widgets(self)
self.widgets.pack(side="top", anchor="center", fill="both", expand=True)
if __name__ == "__main__":
root = tk.Tk()
App(root).pack(side="top", fill="both", expand=True)
root.resizable(0,0)
root.mainloop()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With