I've been stuck for few days trying to figure out how I can resize the frame in TKInter dynamically using this approach.
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(container, self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=TITLE_FONT)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=TITLE_FONT)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=TITLE_FONT)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I copied this code from Switch between two frames in tkinter, because I'm following the same approach.
The problem which I'm facing is that using this approach all frames are stacked in a container and the size of this container is the size of its' largest frame. Moving from one frame to another doesn't resize the respective window dynamically and leads to huge free space in small frames. I tried different techniques to make all frames in the container dynamically resizable but without much success. Can somebody suggest what I can do?
The frame widget in Tkinter works like a container where we can place widgets and all the other GUI components. To change the frame width dynamically, we can use the configure() method and define the width property in it.
Build A Paint Program With TKinter and Python We can use Pillow to open the images, resize them and display in the window. To resize the image, we can use image_resize((width, height) **options) method. The resized image can later be processed and displayed through the label widget.
Instead of stacking the frames, make sure only one is ever managed by grid at a time. You can do this by calling grid_remove()
of the current frame and then grid()
on the new frame. Or, being lazy you can call grid_remove()
on everything so that you don't have to remember which page is current.
def show_frame(self, page_name):
'''Show a frame for the given page name'''
for frame in self.frames.values():
frame.grid_remove()
frame = self.frames[page_name]
frame.grid()
Note: the automatic resizing will stop working if you give the main window a fixed size with the geometry
method on the root window, or if the user manually resizes the window. This is because tkinter assumes that if something explicitly requests a window size, that size should be honored.
If you always want the window to resize, you should reset the geometry to an empty string. You can add this as the last statement in the show_frame
method:
frame.winfo_toplevel().geometry("")
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