Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tkinter - How to stop frame changing size when widget is added?

In the Page frame, I've weighted two frames inside innerFrame so that they each take up half of the screen, however, when I add a widget to one of these frames, I've used a listbox as an example as it is large, one of the frames now takes up more than the other. How do I make it so that the frames don't change size when a widget is added and each remain half the size of the window?

Without Listbox

With Listbox

Here is my code:

import tkinter as tk
from tkinter import ttk

class Program(tk.Tk):        
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        tk.Tk.iconbitmap(self, default = "")
        tk.Tk.wm_title(self, "")

        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 (Page, Other):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(Page)

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


class Page(tk.Frame):

    def __init__(self, parent, controller):


        tk.Frame.__init__(self, parent)

        innerFrame = tk.Frame(self, bg="red")
        innerFrame.place(relx=.5, rely=.5, anchor="c", relwidth=1.0, relheight=1.0)


        innerFrame.grid_rowconfigure(0, weight=1)
        innerFrame.grid_rowconfigure(1, weight=1)
        innerFrame.grid_columnconfigure(0, weight=1)

        #First Half
        frameOne = tk.Frame(innerFrame, bg="pink")
        frameOne.grid(row=0, sticky="NSWE")

        #Second Half
        frameTwo = tk.Frame(innerFrame, bg="green")
        frameTwo.grid(row=1, sticky="NSWE")

        lb = tk.Listbox(frameTwo)
        lb.pack(fill="both", expand=True)


class Other(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)



app = Program()
app.state('zoomed')
app.mainloop()
like image 490
simpleguy Avatar asked Feb 02 '16 18:02

simpleguy


People also ask

How do I stop Tkinter from resizing?

Tkinter windows can be resized automatically by hovering and pulling over the window. We can disable the resizable property using the resizable(boolean value) method. We will pass false value to this method which will disable the window to be resized.

How do I change frame size in Tkinter?

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.

How do you toggle frames in Tkinter?

One way to switch frames in tkinter is to destroy the old frame then replace it with your new frame. I have modified Bryan Oakley's answer to destroy the old frame before replacing it. As an added bonus, this eliminates the need for a container object and allows you to use any generic Frame class.

What is the difference between frame and LabelFrame in Tkinter?

The LabelFrame widget, like the Frame widget, is a spatial container—a rectangular area that can contain other widgets. However, unlike the Frame widget, the LabelFrame widget allows you to display a label as part of the border around the area.


1 Answers

Grid accepts the parameter uniform, which takes an arbitrary value. All rows (or all columns) with the same value are considered to be part of a "uniform group". This forces the rows (or columns) to be a uniform size in proportion to their weight.

If you have two rows in a frame, both rows have an identical weight, and both belong to the same uniform group, they will each take up exactly 50% of the available space.

In your case you can do this:

innerFrame.grid_rowconfigure(0, weight=1, uniform="x")
innerFrame.grid_rowconfigure(1, weight=1, uniform="x")

(again, the "x" is arbitrary; it can be any value as long as it's the same value for both rows)

The official documentation for tk (upon which tkinter is built) describes it like this (see http://tcl.tk/man/tcl8.5/TkCmd/grid.htm#M24)

The -uniform option, when a non-empty value is supplied, places the row in a uniform group with other rows that have the same value for -uniform. The space for rows belonging to a uniform group is allocated so that their sizes are always in strict proportion to their -weight values.

...

When multiple rows or columns belong to a uniform group, the space allocated to them is always in proportion to their weights. (A weight of zero is considered to be 1.) In other words, a row or column configured with -weight 1 -uniform a will have exactly the same size as any other row or column configured with -weight 1 -uniform a. A row or column configured with -weight 2 -uniform b will be exactly twice as large as one that is configured with -weight 1 -uniform b.


Note: the uniform option doesn't show up in the tkinter documentation, but it is a perfectly valid option. It has been a part of tk (upon which tkinter is built) for many, many years.

like image 56
Bryan Oakley Avatar answered Oct 27 '22 04:10

Bryan Oakley