Tkinter geometry() controls the size and screen position of a top-level window. A geometry string can contain the window width, height and its horizontal and vertical position.
import tkinter as tk
root=tk.Tk()
root.geometry('500x300+100+80')
root.mainloop()
This creates a window 500 pixels wide and 300 pixels high, positioned 100 pixels from the left and 80 pixels from the top of the screen.
Show Table of ContentsThe complete geometry format is:
'WIDTHxHEIGHT+X+Y'
For example:
root.geometry('600x400+150+100')
| Part | Meaning |
|---|---|
600 | Window width |
400 | Window height |
150 | Horizontal position from the left edge |
100 | Vertical position from the top edge |
The size or position part can be omitted when only one needs to change.
To set only the size:
root.geometry('500x300')
The width and height are normally specified in pixels.
width=500
height=300
root.geometry(f'{width}x{height}')
Using an f-string is simpler than joining several converted strings.
The position can be included with the size:
root.geometry('500x300+200+120')
This requests a position 200 pixels from the left and 120 pixels from the top.
root.geometry('+200+120')
The existing requested size is retained while the window position changes.
A negative position value is interpreted relative to the opposite screen edge by the Tk window manager.
root.geometry('400x250-20-40')
This requests the window near the bottom-right side of the screen.
Use the screen width and height to calculate the top-left position required to center a window.
import tkinter as tk
root=tk.Tk()
width=500
height=300
screen_width=root.winfo_screenwidth()
screen_height=root.winfo_screenheight()
x=(screen_width-width)//2
y=(screen_height-height)//2
root.geometry(f'{width}x{height}+{x}+{y}')
root.mainloop()
This is useful for dialogs and small applications where an initial centered position improves usability.
A fixed geometry is not always necessary. If geometry() is not called, Tkinter and its geometry managers calculate a suitable window size from the widgets inside it.
import tkinter as tk
root=tk.Tk()
tk.Label(root, text='Tkinter chooses the required window size.', padx=20, pady=20).pack()
root.mainloop()

By default, a top-level Tkinter window can normally be resized horizontally and vertically by the user.
root.resizable(False, False)
root.resizable(True, False)
root.resizable(False, True)
print(root.resizable())
The returned values indicate whether width and height are currently user-resizable.
minsize() sets the smallest permitted window size.
root.minsize(300, 200)
maxsize() sets the largest permitted size.
root.maxsize(900, 700)
import tkinter as tk
root=tk.Tk()
root.geometry('500x350')
root.minsize(300, 200)
root.maxsize(900, 700)
root.mainloop()
This still allows resizing, but only within the specified limits.
An application can call geometry() again at any time to change its requested size.
import tkinter as tk
root=tk.Tk()
root.geometry('300x200')
width=300
height=200
def resize(change):
global width, height
width=max(150, width+change)
height=max(100, height+change)
root.geometry(f'{width}x{height}')
tk.Button(root, text='Increase Window', command=lambda: resize(20)).grid(row=0, column=0, padx=10, pady=20)
tk.Button(root, text='Decrease Window', command=lambda: resize(-20)).grid(row=0, column=1, padx=10, pady=20)
root.mainloop()
The max() calls prevent the example from requesting an impractically small window.
On platforms that support the zoomed window state, it can be used to maximize the window:
root.state('zoomed')
This is a maximized normal window. It is not the same as fullscreen mode.
state('zoomed') is not equally portable across all Tk window managers. Test maximize behaviour on the operating systems supported by your application.Fullscreen hides normal desktop/window-manager space and requests that the Tkinter window occupy the full screen.
root.attributes('-fullscreen', True)
import tkinter as tk
root=tk.Tk()
root.attributes('-fullscreen', True)
def exit_fullscreen(event=None):
root.attributes('-fullscreen', False)
root.bind('<Escape>', exit_fullscreen)
root.mainloop()
Fullscreen support and details are controlled by the platform window manager, so applications should always provide an obvious way to exit it.
root.iconify()
root.deiconify()
root.withdraw()
The common portable states include:
'normal'
'iconic'
'withdrawn'
Query the current state with:
print(root.state())
Calling geometry() without an argument returns the current size and position.
print(root.geometry())
Sample Output
500x300+200+120
The same information can also be retrieved with:
print(root.winfo_geometry())
| Method | Meaning |
|---|---|
winfo_width() | Current allocated widget width. |
winfo_height() | Current allocated widget height. |
winfo_reqwidth() | Width requested by the widget based on its contents and options. |
winfo_reqheight() | Height requested by the widget. |
winfo_screenwidth() | Screen width available to Tk, in pixels. |
winfo_screenheight() | Screen height available to Tk, in pixels. |
winfo_x() | Current x position of the window/widget. |
winfo_y() | Current y position of the window/widget. |
winfo_geometry() | Current geometry string. |
print('Width:', root.winfo_width())
print('Height:', root.winfo_height())
print('Requested width:', root.winfo_reqwidth())
print('Screen width:', root.winfo_screenwidth())
Immediately after creating widgets, Tkinter may not yet have completed geometry calculation. Calling update_idletasks() processes pending idle work such as geometry calculations and redraw requests.
import tkinter as tk
root=tk.Tk()
label=tk.Label(root, text='A label whose requested size must be calculated.', padx=20, pady=20)
label.pack()
root.update_idletasks()
print('Window width:', root.winfo_width())
print('Requested width:', root.winfo_reqwidth())
root.mainloop()
after(), to schedule GUI updates.| Method | Processes |
|---|---|
update_idletasks() | Pending idle callbacks, layout calculations and redraw work. |
update() | Processes a broader set of pending Tk events and can create nested/re-entrant event handling if used carelessly. |
For ordinary applications, allow mainloop() to process events rather than repeatedly calling update().
When the number or size of widgets changes dynamically, it is often better to let the geometry manager calculate the required window size instead of estimating the width manually.
import tkinter as tk
root=tk.Tk()
root.title('Dynamic Buttons')
languages=('PHP', 'Python', 'Perl', 'jQuery', 'Java', 'MySQL', 'CSS', 'Oracle')
for column, language in enumerate(languages):
tk.Button(root, text=language).grid(row=0, column=column, padx=3, pady=15)
root.update_idletasks()
print('Required width:', root.winfo_reqwidth())
print('Required height:', root.winfo_reqheight())
root.mainloop()
Here Tkinter calculates the natural window size from the Buttons. This is generally more robust than assuming each Button requires exactly 50 pixels.
geometry() controls a top-level window's requested size and position. Geometry managers such as grid() and place() arrange widgets inside that window.
| Feature | Purpose |
|---|---|
root.geometry() | Top-level window size and screen position. |
widget.grid() | Arrange child widgets in rows and columns. |
widget.pack() | Arrange child widgets against sides or available space. |
widget.place() | Position child widgets using coordinates or relative positions. |
For responsive grid layouts, see rowconfigure() and columnconfigure().
A maximized normal window and fullscreen mode are different. Use state('zoomed') only for supported maximize behaviour and attributes('-fullscreen', True) for fullscreen.
Tkinter can calculate a natural requested size from its child widgets. Hardcoded dimensions can clip content when fonts, platforms or display settings change.
print(root.winfo_width())
can return an initial placeholder size before layout calculation has completed. Use update_idletasks() first when an immediate measurement is required.
winfo_reqwidth() is the size requested by the widget. winfo_width() is its current allocated width.
It only processes idle work. Long-running work should not block Tkinter's event loop.
Keep GUI operations on the Tkinter thread. Background work can communicate results back to the GUI, which can then update widgets through the main event loop.
A fixed-size window may become difficult to use on another display. Prefer sensible minimum sizes and responsive widget layouts when possible.
Different text, fonts, themes and padding produce different widget widths. Let Tkinter calculate requested geometry where possible.
geometry('WIDTHxHEIGHT') to set window size.geometry('WIDTHxHEIGHT+X+Y') to set size and screen position.geometry('+X+Y') when only the position should change.geometry() without an argument returns the current geometry string.winfo_screenwidth() and winfo_screenheight() when calculating a centered position.resizable() to control whether users can resize width or height.minsize() and maxsize() to restrict resizing without completely disabling it.state('zoomed') is a maximize operation on supported platforms, not true fullscreen.attributes('-fullscreen', True) for fullscreen and provide a way to exit.iconify() to minimize, deiconify() to restore and withdraw() to hide a window.winfo_width() and winfo_height() report current allocated dimensions.winfo_reqwidth() and winfo_reqheight() report requested dimensions.update_idletasks() can force pending geometry calculations before taking immediate measurements.update_idletasks() does not solve blocking-code or threading problems.geometry() controls the top-level window; grid(), pack() and place() arrange child widgets inside it.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.