tkinter resize frame and contents with main window
Asked Answered
B

3

11

I am trying to work out how to control resizing of the window containing a frame. In the code I have three buttons across the top that should to stay exactly where they are.

When I drag the window to expand it, I want the frame and the text box it contains to expand with the master window. I have read that columnconfigure and rowconfigure can be used but not sure how to implement it.

from tkinter import *
from tkinter import scrolledtext

master_window = Tk()

# Create the buttons
btn_Image = Button(master_window, text='Image')
btn_Image.grid(row=1, column=1, padx=(10), pady=10, sticky=E + W)

btn_File = Button(master_window, text='File')
btn_File.grid(row=1, column=2, padx=(10), pady=10, sticky=E + W)

btn_Folder = Button(master_window, text='Folder')
btn_Folder.grid(row=1, column=3, padx=(10), pady=10, sticky=E + W)

# Group1 Frame ----------------------------------------------------
group1 = LabelFrame(master_window, text="Text Box", padx=5, pady=5)
group1.grid(row=2, column=1, columnspan=3, padx=10, pady=10, sticky=E+W+N+S)

# Create the textbox
txtbox = scrolledtext.ScrolledText(group1, width=40, height=10)
txtbox.grid(row=1, column=1,  columnspan=3, sticky=E+W+N+S)

mainloop()
Bondstone answered 19/5, 2018 at 7:7 Comment(0)
M
23

The row and column numbers of the grid() layout manager start from 0, not from 1 (there is nothing wrong to start placing the elements wherever you want though, I just mention this because your code gives me the impression you think the cells start at 1, not at 0). Because I do not see the reason why to start placing the widgets at row=1 and column=1, in my solution below, I start placing at the 0 index.

I suggest you to create a different container -parent widget- for the 3 buttons in questions (let us say a tkinter.Frame()).

Here is the code:

from tkinter import *
from tkinter import scrolledtext

master_window = Tk()

# Parent widget for the buttons
buttons_frame = Frame(master_window)
buttons_frame.grid(row=0, column=0, sticky=W+E)    

btn_Image = Button(buttons_frame, text='Image')
btn_Image.grid(row=0, column=0, padx=(10), pady=10)

btn_File = Button(buttons_frame, text='File')
btn_File.grid(row=0, column=1, padx=(10), pady=10)

btn_Folder = Button(buttons_frame, text='Folder')
btn_Folder.grid(row=0, column=2, padx=(10), pady=10)

# Group1 Frame ----------------------------------------------------
group1 = LabelFrame(master_window, text="Text Box", padx=5, pady=5)
group1.grid(row=1, column=0, columnspan=3, padx=10, pady=10, sticky=E+W+N+S)

master_window.columnconfigure(0, weight=1)
master_window.rowconfigure(1, weight=1)

group1.rowconfigure(0, weight=1)
group1.columnconfigure(0, weight=1)

# Create the textbox
txtbox = scrolledtext.ScrolledText(group1, width=40, height=10)
txtbox.grid(row=0, column=0,   sticky=E+W+N+S)

mainloop()

Demo:

At not stretched:

enter image description here

Average stretching:

enter image description here

After maximum stretching:

enter image description here

Musgrave answered 19/5, 2018 at 8:21 Comment(0)
S
2

I tkink it would be better to not import everything of tkinter. And also puting funtion calls to main function. Hence I just modify @Billal Begueradj 's pasted code to the following:

# coding: utf-8

try:
    import tkinter as tk
    from tkinter import scrolledtext
except: # Python2 compatible
    import Tkinter as tk
    from Tkinter import scrolledtext

def main():
    master_window = tk.Tk()

    # Parent widget for the buttons
    buttons_frame = tk.Frame(master_window)
    buttons_frame.grid(row=0, column=0, sticky=tk.W+tk.E)    

    btn_Image = tk.Button(buttons_frame, text='Image')
    btn_Image.grid(row=0, column=0, padx=(10), pady=10)

    btn_File = tk.Button(buttons_frame, text='File')
    btn_File.grid(row=0, column=1, padx=(10), pady=10)

    btn_Folder = tk.Button(buttons_frame, text='Folder')
    btn_Folder.grid(row=0, column=2, padx=(10), pady=10)

    # Group1 Frame ----------------------------------------------------
    group1 = tk.LabelFrame(master_window, text="Text Box", padx=5, pady=5)
    group1.grid(row=1, column=0, columnspan=3, padx=10, pady=10, sticky=tk.E+tk.W+tk.N+tk.S)

    master_window.columnconfigure(0, weight=1)
    master_window.rowconfigure(1, weight=1)

    group1.rowconfigure(0, weight=1)
    group1.columnconfigure(0, weight=1)

    # Create the textbox
    txtbox = scrolledtext.ScrolledText(group1, width=40, height=10)
    txtbox.grid(row=0, column=0, sticky=tk.E+tk.W+tk.N+tk.S)

    master_window.mainloop()

if __name__ == '__main__':
    main()
Saleratus answered 1/6, 2020 at 7:32 Comment(0)
H
0

This is just another example. Two frames with different resizing. Includes a treeview widget.

import tkinter as tk
from tkinter import ttk
import random
import string

class MyApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Using grid with two frames")


        # Lay out two frames on the root window
        ## first frame will contain two rows of control widgets
        ## this frame will be able to resize horizontally
        frame_controls = tk.Frame(master=self.root, padx=10, pady=10)
        frame_controls.grid(row=0, 
                            column=0, sticky="ew")
        
        ## second frame will contain a treeview
        ## this frame will be able to resize vertically and horizontally
        frame_treeview = tk.LabelFrame(master=self.root, padx=10, pady=10, 
                                       text="Image files")
        frame_treeview.grid(row=2, 
                            column=0, padx=5, pady=5, 
                            sticky="nsew")
        

        # Create widgets in the appropriate frames
        ## first frame, first row: a button, an entry box, and another button
        self.button_dest  = ttk.Button (master=frame_controls,  text="Dest dir")
        self.entry        = ttk.Entry  (master=frame_controls)
        self.button_clear = ttk.Button (master=frame_controls,  text="Clear")
        
        ## first frame, second row: two buttons
        self.button_scale  = ttk.Button (master=frame_controls, text="Scale")
        self.button_upload = ttk.Button (master=frame_controls, text="Upload")
        
        ## second frame, third row: the treeview
        self.tree = ttk.Treeview(master=frame_treeview, 
                                 columns=("original", "scaled", "status"), 
                                 show="headings")
        self.tree.heading("original", text="Original")
        self.tree.heading("scaled", text="Scaled")
        self.tree.heading("status", text="Status")

        ## add a vertical scroll bar to the containing frame and configure to the treeview
        self.vsb = ttk.Scrollbar(master=frame_treeview, 
                                 orient="vertical", 
                                 command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.vsb.set)

        ## add rows of random string values to the treeview (dummy data)
        for _ in range(20):
            self.tree.insert("", 
                tk.END, 
                values=("".join(random.choices(string.ascii_letters, k=8)), 
                        "".join(random.choices(string.ascii_letters, k=8)),
                        "".join(random.choices(string.ascii_letters, k=8))))
        

        # Lay out the widgets in the grid
        pad = 5 # uniform padding
        self.button_dest.grid(row=0, 
                              column=0, padx=pad, pady=pad)
        
        self.entry.grid (row=0, 
                         column=1, padx=pad, pady=pad, sticky=tk.EW, 
                         columnspan=2)
        
        self.button_clear.grid(row=0, 
                               column=3, padx=pad, pady=pad)
        
        self.button_scale.grid(row=1, 
                               column=0, padx=pad, pady=pad)
        self.button_upload.grid(row=1, 
                                column=1, padx=pad, pady=pad)

        self.tree.grid(row=2, 
                       column=0, padx=pad, pady=pad, sticky=tk.NSEW)
        self.vsb.grid(row=2, 
                      column=1, sticky=tk.NS)
        

        # Configure resizing behavior
        self.root.grid_rowconfigure(2, weight=1)          # the frame-containing window must resize
        self.root.grid_columnconfigure(0, weight=1)       # otherwise the contained frames will not

        frame_controls.grid_columnconfigure(2, weight=1)  # make contained entry resize with window

        frame_treeview.grid_rowconfigure(2, weight=1)     # make the contained treeview resize vertically, 
        frame_treeview.grid_columnconfigure(0, weight=1)  # and horizontally

if __name__ == "__main__":
    root = tk.Tk()
    app = MyApp(root)
    root.mainloop()
Hydrogeology answered 27/3 at 19:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.