I'm trying to write a simple tkinter app and would like to follow OOP best practices glimpsed from here: Best way to structure a tkinter application?
and here: https://www.begueradj.com/tkinter-best-practices/
and here:
The app should be a simple game for children to learn the alphabet, showing one big letter and then three buttons with animal pictures to chose from.
Now I have started with this code:
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, self.master) # or super().__init__(self.master)?
self.configure_gui()
self.create_widgets()
def configure_gui(self):
self.master.title('Example')
self.master.geometry('500x500')
self.master.minsize(100, 100)
self.master.columnconfigure([0, 1], minsize=50, weight=1)
self.master.rowconfigure([0, 1], minsize=50, weight=1)
# self.master.resizable(False, False)
def create_widgets(self):
# Frame that will contain the big letter
self.letterbox = tk.Frame(self.master, bg='red', width=200, height=200)
self.letterbox.grid(row=0, column=0, sticky='nsew')
...
# Frame that contains the 3 animal pictures
self.animalbox = tk.Frame(self.master, bg='yellow')
self.animalbox.rowconfigure(0, weight=1)
self.animalbox.columnconfigure([0, 1, 2], weight=1)
self.animalbox.grid(row=1, column=0, sticky='nsew')
self.animalbox_left = tk.Button(self.animalbox, text='left animal')
self.animalbox_left.grid(row=0, column=0, padx=10, pady=10, ipady=10)
self.animalbox_middle = tk.Button(self.animalbox, text='middle animal')
self.animalbox_middle.grid(row=0, column=1, padx=10, pady=10, ipady=10)
self.animalbox_right = tk.Button(self.animalbox, text='right animal')
self.animalbox_right.grid(row=0, column=2, padx=10, pady=10, ipady=10)
# Frame that contains the score and options
self.scorebox = tk.Frame(self.master, bg='blue')
self.scorebox.grid(row=0, column=1, rowspan=2, sticky='nsew')
def main():
root = tk.Tk()
MainApplication(root)
root.mainloop()
if __name__ == '__main__':
main()
I thought about splitting the questions but since they all adress the same short piece of code and are maybe rather basic, I chose to keep them in one post.
Questions:
- Why does it matter, whether I pass two arguments to tk.Frame.init(self, self.master) but only one to argument (self.master) to the super().__init__self(self.master)? If I pass two arguments to super()... it doesn't work.
Edit: I've found the answer here: What does 'super' do in Python? - difference between super().__init__() and explicit superclass __init__() In the end it's just an implementation detail of super, if I understand correctly.
- In the code examples from Brian Oakley and for example here https://www.pythontutorial.net/tkinter/tkinter-object-oriented-frame/ only "self" is passed as master to the widget, while my code needs "self.master" to work. Why?
Edit2: In the meantime I have found out, that if you initialize the MainApplication inheriting from tk.Frame, then it's possible to use "self.pack() in the MainApplication init-function:
class MainApplication(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, self.master)
self.pack()
This will pack the just initialized frame into the tk.Tk() root window and then allows other widgets to pack themselves into this frame, thus allowing to reference them like:
self.letterbox = tk.Frame(self, bg='red', width=200, height=200)
...instead of:
self.letterbox = tk.Frame(self.master, bg='red', width=200, height=200)
...which directplay packs the widget into the root window.
Does it matter, whether I assign MainApplication(root) to a variable or not in the main() function definition?
def main(): root = tk.Tk() MainApplication(root) root.mainloop() Edit3: I don't think it matters.
Thanks a lot for your insight. This is my first question on stackoverflow and I tried to make it nice. Best regards!