I'm building a Python application using Tkinter.
In the main window, I have a Canvas with a scrollable Frame inside it. Within that scrollable frame, I've added several LabelFrame widgets. Each LabelFrame contains a "Select Path" button, which is supposed to open a folder selection dialog.
Here’s the simplified structure:
Tk() window
└── Canvas
└── Scrollable Frame
└── Multiple LabelFrames
└── Each with a "Select Path" button
Each button calls the following function:
def select_path(self):
filedialog.askdirectory()
All button commands are correctly set (using command=self.select_path, not self.select_path()). However, every time I click a button, the application freezes and shows "(Not Responding)" in the title bar.
If I use filedialog.askopenfile() instead of askdirectory(), everything works fine.
I’ve also tried passing the parent argument and using tricks like self.lift() and -topmost, but the freeze still occurs.
Any ideas why askdirectory() causes the app to freeze in this layout, while askopenfile() does not?
Thank you!
After following furas's recommendation, I reduced my code to only use the canvas, frames, and path buttons, and everything works fine. However, my main application still doesn't work.
This is my reduced code.
import tkinter
from tkinter import ttk, VERTICAL, ALL
from tkinter import filedialog as fd
class MyApp(tkinter.Tk):
def __init__(self):
super().__init__()
self.path_button = None
self.label_frame_3 = None
self.label_frame_2 = None
self.label_frame_1 = None
self.title('My application')
self.resizable(False, False)
self.geometry('1200x500')
self.current_window = None
self.scrollable_frame = None
self.y_scrollbar = None
self.my_canvas = None
self.create_gui()
def create_gui(self):
# scroll
# create a container frame for scrolling
self.my_canvas = tkinter.Canvas(self)
# add a Scrollbars to Canvas
self.y_scrollbar = ttk.Scrollbar(self.my_canvas, orient=VERTICAL, command=self.my_canvas.yview)
# Configure the canvas
self.my_canvas.configure(yscrollcommand=self.y_scrollbar.set, width=500, height=500)
def on_mousewheel(event):
self.my_canvas.yview_scroll(int(-1*(event.delta/60)), "units")
# create another frame inside my_canvas
self.scrollable_frame = tkinter.Frame(self.my_canvas, bg='white')
self.my_canvas.bind("<Configure>", lambda e: self.my_canvas.configure(scrollregion=self.my_canvas.bbox(ALL)))
self.my_canvas.bind_all("<MouseWheel>", on_mousewheel)
self.my_canvas.create_window((0, 0), window=self.scrollable_frame, anchor='nw')
# place scroll and scroll-bar
self.my_canvas.pack(side='left', fill='both', expand=True)
self.y_scrollbar.pack(side='right', fill='y')
# end scroll
self.create_all_labels(200, 200)
def create_all_labels(self, width, height):
# create and place frame 1
self.label_frame_1 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 1 ", labelanchor='nw', width=width,
height=height)
self.label_frame_1.grid(column=0, row=1, padx=5, pady=5)
self.create_frame(self.label_frame_1, "label_frame_1")
# create and place frame 2
self.label_frame_2 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 2 ", labelanchor='nw', width=width,
height=height)
self.label_frame_2.grid(column=1, row=1, padx=5, pady=5)
self.create_frame(self.label_frame_2, "label_frame_2")
# create and place frame 3
self.label_frame_3 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 3 ", labelanchor='nw', width=width,
height=height)
self.label_frame_3.grid(column=2, row=1, padx=5, pady=5)
self.create_frame(self.label_frame_3, "label_frame_3")
# create and place frame 4
self.label_frame_4 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 4 ", labelanchor='nw', width=width,
height=height)
self.label_frame_4.grid(column=0, row=2, padx=5, pady=5)
self.create_frame(self.label_frame_4, "label_frame_4")
# create and place frame 5
self.label_frame_5 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 5 ", labelanchor='nw', width=width,
height=height)
self.label_frame_5.grid(column=1, row=2, padx=5, pady=5)
self.create_frame(self.label_frame_5, "label_frame_5")
# create and place frame 6
self.label_frame_6 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 6 ", labelanchor='nw', width=width,
height=height)
self.label_frame_6.grid(column=2, row=2, padx=5, pady=5)
self.create_frame(self.label_frame_6, "label_frame_6")
# create and place frame 7
self.label_frame_7 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 7 ", labelanchor='nw', width=width,
height=height)
self.label_frame_7.grid(column=0, row=3, padx=5, pady=5)
self.create_frame(self.label_frame_7, "label_frame_7")
# create and place frame 8
self.label_frame_8 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 8 ", labelanchor='nw', width=width,
height=height)
self.label_frame_8.grid(column=1, row=3, padx=5, pady=5)
self.create_frame(self.label_frame_8, "label_frame_8")
# create and place frame 9
self.label_frame_9 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 9 ", labelanchor='nw', width=width,
height=height)
self.label_frame_9.grid(column=2, row=3, padx=5, pady=5)
self.create_frame(self.label_frame_9, "label_frame_9")
# create and place frame 10
self.label_frame_10 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 10 ", labelanchor='nw', width=width,
height=height)
self.label_frame_10.grid(column=0, row=4, padx=5, pady=5)
self.create_frame(self.label_frame_10, "label_frame_10")
# create and place frame 11
self.label_frame_11 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 11 ", labelanchor='nw', width=width,
height=height)
self.label_frame_11.grid(column=1, row=4, padx=5, pady=5)
self.create_frame(self.label_frame_11, "label_frame_11")
# create and place frame 12
self.label_frame_12 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 12 ", labelanchor='nw', width=width,
height=height)
self.label_frame_12.grid(column=2, row=4, padx=5, pady=5)
self.create_frame(self.label_frame_12, "label_frame_12")
def create_frame(self, frame: tkinter.LabelFrame, name: str):
# create and place Select Path button
self.path_button = tkinter.Button(frame, text=" Select Path ", command=self.select_path)
self.path_button.place(x=20, y=20)
def select_path(self):
print("before")
destination = fd.askdirectory(initialdir="C:", title="Select")
print("after")
def main_loop(self):
self.mainloop()
myapp = MyApp()
myapp.mainloop()
minimal working codedirectly in question (not link to external portal)askdirectory()without Canvas, Frames, etc.?