Python Forum

Full Version: Problems with frames layout
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm trying to layout my GUI with next settings:

1st level.
- FrameMain, which takes most part of the window, it's the top one.
- FrameBottom, which takes it's position under FrameMain and it's height is equal to Button's height.

2nd level.
- FrameLeft (a child of FrameMain) is on the left side of the master's frame, takes half of it's width. It contains Canvas, which is going to be used to draw sprites.
- FrameRight (a child of FrameMain) is on the right side of the master's frame, takes half of it's width. It contains 2 more frames...

3rd level.
- FrameAction (a child of FrameRight) is on the top side of the master's frame, takes half of it's height. It contains a tabbed menu (notebook).
- FrameChat (a child of FrameRight) is on the bottom side of the master's frame, takes half of it's height. It'll contain some Text widget in future.

You can see my layout without Notebook widget on the screenshot, it's the bottom window - everything fits perfectly.

When I add Notebook widget into FrameAction, I'm having hext layout problems:
- FrameAction takes more width in compare with FrameLeft;
- FrameAction takes more height in compare with FrameChat.

You can see 2 compared windows on the screenshot and also I'm including my code.

Thanks in advance for help!

import tkinter as tk
from tkinter import ttk as tktw
import time
import socket


class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("640x480")
        self.minsize(width=640, height=480)
        self.fm = FrameMain(self, background="pink")
        self.fb = FrameBottom(self, background="lightblue")
        self.fl = FrameLeft(self.fm, background="yellow")
        self.fr = FrameRight(self.fm, background="green")
        self.fa = FrameAction(self.fr, background="orange")
        self.fc = FrameChat(self.fr, background="blue")
        self.tm = TopMenu(self)
        self.config(menu=self.tm)
        # self.ab = ActionBar(self.fa, width=0, height=0)
        # self.ai = ActionInfo(self.ab, width=0, height=0)
        # self.ab.add(self.ai, text="Info", state="normal")
        self.c = CanvasArea(self.fl, width=0, height=0)


class FrameMain(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1)


class FrameLeft(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1, side="left")


class CanvasArea(tk.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1)


class FrameRight(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1, side="right")


class FrameChat(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1, side="bottom")


class FrameAction(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1, side="top")


class ActionBar(tktw.Notebook):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(expand=1, fill=tk.BOTH)


class ActionInfo(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH, expand=1)


class FrameBottom(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=tk.BOTH)
        self.cb = ComboboxCommands(self, width=10, state="readonly")
        self.cl = CommandLine(self, relief="ridge", bd=2)
        self.bs = ButtonSend(self, text="Send", relief="ridge")


class ComboboxCommands(tktw.Combobox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(side="left", fill=tk.BOTH)


class CommandLine(tk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(side="left", fill=tk.BOTH, expand=1)


class ButtonSend(tk.Button):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(side="right")


class TopMenu(tk.Menu):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.add_cascade(label="Menu")


if __name__ == "__main__":
    w = Window()

    imgsrc = tk.PhotoImage(file="images/img.gif")
    img = w.c.create_image(0, 0, anchor="nw", image=imgsrc)

	w.mainloop()
[Image: notebook.png]
I've reorganised the frames to be create inside there parent frames.
FrameAction seemed surplus to requirement.
It seems that the size of the notebook is being calculated wrong as the more notebook tabs that are added the more width it takes up.
I'm not sure if its a bug or the way they are added is wrong maybe wrong parent or something.
the following code shows both examples one with and one without the notebook to make it easier to see the difference between them.
Still investigating what the problem is.
import tkinter as tk
from tkinter import ttk as tktw

CREATE_ACTION_BAR = False


class ParentFrame(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("640x480")
        self.minsize(width=640, height=480)
        self.create_menu()
        self.creare_frame_main()
        self.create_frame_bottom()

    def create_menu(self):
        self.tm = TopMenu(self)
        self.config(menu=self.tm)

    def creare_frame_main(self):
        self.fm = FrameMain(self, background="pink")
        self.fm.pack(fill=tk.BOTH, expand=1)

    def create_frame_bottom(self):
        self.fb = FrameBottom(self, background="lightblue")
        self.fb.pack(fill=tk.BOTH)


class TopMenu(tk.Menu):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.add_cascade(label="Menu")


class FrameMain(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.create_frame_left()
        self.create_frame_right()

    def create_frame_left(self):
        self.fl = FrameLeft(self, background="yellow")
        self.fl.pack(fill=tk.BOTH, expand=1, side="left")

    def create_frame_right(self):
        self.fr = FrameRight(self, background="green")
        self.fr.pack(fill=tk.BOTH, expand=1, side="right")


class FrameLeft(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.create_canvas_area()

    def create_canvas_area(self):
        self.c = CanvasArea(self, width=0, height=0)
        self.c.pack(fill=tk.BOTH, expand=1)


class FrameRight(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if CREATE_ACTION_BAR:
            self.create_action_bar()
        else:
            self.create_frame_action()
        self.create_frame_chat()

    def create_frame_action(self):
        self.fa = FrameAction(self, background="orange")
        self.fa.pack(fill=tk.BOTH, expand=1, side="top")

    def create_action_bar(self):
        self.ab = ActionBar(self, width=0, height=0)
        self.ab.pack(fill=tk.BOTH, expand=1, side="top")

    def create_frame_chat(self):
        self.fc = FrameChat(self, background="blue")
        self.fc.pack(fill=tk.BOTH, expand=1, side="bottom")


class FrameBottom(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.create_combobox_commands()
        self.create_commandline()
        self.create_buttonsend()

    def create_combobox_commands(self):
        self.cb = ComboboxCommands(self, width=10, state="readonly")
        self.cb.pack(side="left", fill=tk.BOTH)

    def create_commandline(self):
        self.cl = CommandLine(self, relief="ridge", bd=2)
        self.cl.pack(side="left", fill=tk.BOTH, expand=1)

    def create_buttonsend(self):
        self.bs = ButtonSend(self, text="Send", relief="ridge")
        self.bs.pack(side="right")


class ComboboxCommands(tktw.Combobox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class CommandLine(tk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class ButtonSend(tk.Button):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class CanvasArea(tk.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class FrameAction(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # self.create_action_bar()

    def create_action_bar(self):
        self.ab = ActionBar(self, width=0, height=0)
        self.ab.pack(expand=1, fill=tk.BOTH)


class ActionBar(tktw.Notebook):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _ in range(10):
            self.create_action_info()

    def create_action_info(self):
        self.ai = ActionInfo(self, width=0, height=0)
        self.ai.pack(fill=tk.BOTH, expand=1)
        self.add(self.ai, text="Info", state="normal")


class ActionInfo(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class FrameChat(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class DuplicateParentFrame(tk.Toplevel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("640x480")
        self.minsize(width=640, height=480)
        self.create_menu()
        self.creare_frame_main()
        self.create_frame_bottom()

    def create_menu(self):
        self.tm = TopMenu(self)
        self.config(menu=self.tm)

    def creare_frame_main(self):
        self.fm = FrameMain(self, background="pink")
        self.fm.pack(fill=tk.BOTH, expand=1)

    def create_frame_bottom(self):
        self.fb = FrameBottom(self, background="lightblue")
        self.fb.pack(fill=tk.BOTH)


if __name__ == "__main__":
    w = ParentFrame()
    CREATE_ACTION_BAR = True
    w2 = DuplicateParentFrame()
    w.mainloop()