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 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 weight
of 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 weight
of 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)