Reputation: 153
When implementing complex dialogs (i.e. dialogs with some 10 or more widgets, especially when arranged within multiple frames or the like), the creation requires many tkinter calls and the code can become increasingly complex (difficult to read and maintain) when it is kept within a single method. Also in general, short functions/methods are usually preferred over longer ones.
My current approach to limit method length is to encapsulate creation of all widgets that belong to a group within the dialog into one method(parent_frame, other_options)
that returns the top-level widget like this:
import tkinter as tk
class Dialog:
def __init__(self, master):
self.__master = master
self.create_gui(master)
def create_gui(self, frame, title = None):
if title: frame.title(title)
group_a = self.create_group_a(frame)
group_a.grid(row=0, column=0, sticky="nsew")
group_b = self.create_group_b(frame)
group_b.grid(row=1, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
def create_group_a(self, frame):
inner_frame = tk.LabelFrame(frame, text="Label")
text = self.create_text_with_scrollbar(inner_frame)
text.pack(fill="both")
return inner_frame
def create_group_b(self, frame):
button = tk.Button(frame, text="Button")
return button
def create_text_with_scrollbar(self, frame):
text_frame = tk.Frame(frame)
text_frame.grid_rowconfigure(0, weight=1)
text_frame.grid_columnconfigure(0, weight=1)
text = tk.Text(text_frame)
text.grid(row=0, column=0, sticky="nsew")
scrollbar = tk.Scrollbar(text_frame, command=text.yview)
scrollbar.grid(row=0, column=1, sticky="nsew")
text['yscrollcommand'] = scrollbar.set
return text_frame
if __name__ == "__main__":
master = tk.Tk()
Dialog(master)
tk.mainloop()
Are there any specific guidelines around on code structuring in such cases? Does anybody have any advice on how to better structure such code?
Upvotes: 0
Views: 630
Reputation: 2527
What I usually do is to write a new class for every group. Those classes inherit from Frame. The end result will look something like this:
class MainFrame(Frame):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self.first_sub = FirstSubFrame(self)
self.second_sub = SecondSubFrame(self)
self.first_sub.grid()
self.second_sub.grid()
class FirstSubFrame(Frame):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self.possibly_another_subframe = PossibleOtherFrame(self)
self.awesome_button = tkinter.Button()
self.possibly_another_subframe.grid()
self.awesome_button.grid()
...
I hope this helps.
Upvotes: 2