2

I'm currently working on a GUI using tkinter which allows the user to navigate between different frames. I based my code structure on this user response.

My issue now is to automatically adjust tkinter's window to its contents when a frame is changed. I want the borders of the window to fit the widgets following the red arrows as in here and here (the outputs from the sample code below), so that there is no such "empty space" in each frame.

The code works in a way that the method show_frame allows the change between the two defined frames.

from tkinter import *


class WindowController(Tk):

    def __init__(self, *args, **kwargs):

        Tk.__init__(self, *args, **kwargs)

        container = Frame(root)
        container.grid()

        self.frames = {}

        for F in (FirstWindow, SecondWindow):
            frame = F(parent=container, controller=self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(FirstWindow)

        self.destroy()

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


class FirstWindow(Frame):

    def __init__(self, parent, controller):

        self.controller = controller
        self.parent = parent

        Frame.__init__(self, parent)

        # Widgets:

        # "Do Nothing" Button
        self.Title0 = Button(self, text='Do nothing')
        self.Title0.grid(row=0, column=0)

        # "Do Nothing" Button
        self.Title1 = Button(self, text='Do Nothing')
        self.Title1.grid(row=1, column=0)

        # Change Frame Button
        self.Title2 = Button(self, text='To Second Window', command=lambda: self.controller.show_frame(SecondWindow))
        self.Title2.grid(row=2, column=0)


class SecondWindow(Frame):

    def __init__(self, parent, controller):

        self.controller = controller
        self.parent = parent

        Frame.__init__(self, parent)

        # Widgets:

        # "Do Nothing" Button
        self.Title0 = Button(self, text='Do nothing')
        self.Title0.grid(row=0, column=0)

        # "Do Nothing" Button
        self.Title1 = Button(self, text='Do Nothing')
        self.Title1.grid(row=0, column=1)

        # Change Frame Button
        self.Title2 = Button(self, text='To First Window', command=lambda: self.controller.show_frame(FirstWindow))
        self.Title2.grid(row=0, column=2)



if __name__ == "__main__":
    root = Tk()
    root.resizable(width=False, height=False)
    app = WindowController()
    app.mainloop()

My problem seems to be similar to the one in here, but it wasn't solved.

This is my first question here, so criticism is very much appreciated.

fagoncal
  • 23
  • 1
  • 3

1 Answers1

2

The answer is in the question Tkinter Frame Resize: Since both frames are gridded the window will expand to contain them both.

To get the window to change size you need to have only one frame gridded at a time.

To remove a frame from a window and still remember its attributes use:

frame.grid_remove()

To display the frame again use:

frame.grid()  # Will remember grid settings

This code works but you could probably improve on its beauty:

class WindowController(Tk):
    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        container = Frame(root)
        container.grid()
        self.frames = {}

        for F in (FirstWindow, SecondWindow):
            frame = F(parent=container, controller=self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
            frame.grid_remove()     # Remove all frames

        self.show_frame(FirstWindow)
        self.destroy()

    def show_frame(self, cont):
        for fme in self.frames:     # Remove all frames
            self.frames[fme].grid_remove()
        frame = self.frames[cont]
        frame.grid()        # Display frame
figbeam
  • 7,001
  • 2
  • 12
  • 18