Home > Software engineering >  How do I resize placed tkinter widgets when the window is resized?
How do I resize placed tkinter widgets when the window is resized?

Time:02-18

I have read the other questions posted on this site and could not solve my issue. I am working on a tkinter app and to make it look as good as possible I chose to use .place() to show the widgets on the screen. The values of x and y are fixed for each widget but I want the window to be resizable and the widgets to adapt keeping the same ratio. See the code attached and how the GUI looks

import tkinter as tk
from tkinter import messagebox


class MyClass:
    def __init__(self, root):
        self.root = root
        self.root.title("App")
        self.root.geometry("600x300")

        self.welcome_label = tk.Label(self.root, text="Welcome", justify="center", fg="blue", font=("Arial", 24))
        self.welcome_label.place(x=230, y=40)

        self.username_label = tk.Label(self.root, text="Username:")
        self.username_label.place(x=140, y=100)
        self.username_box = tk.Entry(self.root, bd=3, selectbackground="#e5e3e3")
        self.username_box.place(x=230, y=100)

        self.password_label = tk.Label(self.root, text="Password:")
        self.password_label.place(x=140, y=150)
        self.password_box = tk.Entry(self.root, bd=3, selectbackground="#e5e3e3")
        self.password_box.place(x=230, y=150)

        self.log_in_buttonn = tk.Button(self.root, text="Log In", justify="center", command=self.log_inn)
        self.log_in_buttonn.place(x=470, y=230, width=70, height=50)
        self.register_button = tk.Button(self.root, text="Register", command=self.register)
        self.register_button.place(x=100, y=230, width=70, height=50)

    def log_inn(self):
        ...
    def register(self):
        ...


if __name__ == "__main__":
    roott = tk.Tk()
    app = MyClass(roott)
    roott.mainloop()

Screenshot 1 smaller window

Screenshot 2 bigger window

Screenshot 3 normal and default

CodePudding user response:

Instead of using place, you could use the grid geometry manager. Tkinter will take care of all the resizing issues and the output will look perfect! Achieving the same result using place is much harder because it accepts highly hard coded values. Grid is relative.

Using .grid_rowconfigure and .grid_columnconfigure on the container widget:

<containter_widget>.grid_rowconfigure(<row number>, weight = <whole number>)
<containter_widget>.grid_columnconfigure(<column number>, weight = <whole number>)

Explanation:

Tkinter gives every row and column a weightof 0 by default. What it means is that if a column has no widgets, it will have zero width on screen.

Giving a column a non-zero weight ensures that it always has some width on screen even if it is empty.

If you give the columns 0 and 1 a weightof 1, both the columns will take exactly half of the available space horizontally in the container widget assuming all other columns have a weight of 0 (even if you resize your window). .grid_rowconfigure works similarly.

Using .grid:

<widget>.grid(row = <row number>, column = <column number>, sticky = <combination of n,s,e,w as a string>, rowspan = _, columnspan = _, padx = _, pady = _, ipadx = _, ipady = _)

Explanation:

  • row, column: self-explanatory
  • sticky: directions in which the widget should expand within the space assigned for it by the container widget. n, s, e, w stand for the four directions.
  • rowspan: If you have used .grid_rowconfigure, you can use rowspan to tell tkinter how many rows should the widget "span"
  • columnspan: similar to rowspan
  • padx: horizontal padding
  • pady: vertical padding
  • ipadx: internal horizontal padding
  • ipady: internal vertical padding

Sample grid statement:

widget.grid(row = 0, column = 1, sticky = "nsew", rowspan = 3, columnspan = 2, padx = 5, pady = 5, ipadx = 3, ipadx = 3)
  • Related