I have a root window and I want to create a Toplevel window positioned in a specific place on the screen (centralized over the root window). So far I have been unable to accomplish this without seeing the Toplevel window quickly build itself in its default location and then hop over to the position I want it. I would prefer not to see this because it's weird and jarring.
Is there a way to build, then reposition a window in Tkinter without seeing it reposition itself?
Here's some example code with a sleep thrown in to simulate a complex window being rendered:
from tkinter import *
import time
def centralize_over_root(window_to_centralize):
root_geometry = root.winfo_geometry()
root_width_height = root_geometry.split('+')[0]
root_width = root_width_height.split('x')[0]
root_height = root_width_height.split('x')[1]
root_x_y = root_geometry.split(f'{root_height}+')[1]
root_x = root_x_y.split('+')[0]
root_y = root_x_y.split('+')[1]
window_to_centralize.update()
time.sleep(0.5)
window_width = window_to_centralize.winfo_width()
window_height = window_to_centralize.winfo_height()
window_x = int(root_x) + round((int(root_width) - int(window_width)) / 2.0)
window_y = int(root_y) + round((int(root_height) - int(window_height)) / 2.0)
result = f'+{window_x}+{window_y}'
return result
def new_window():
new_window = Toplevel(root)
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
root = Tk()
Button(root, text='Make new window', command=new_window).pack(padx=50, pady=50)
root.mainloop()
I think the following will do what you want. There are comments showing where I made changes. The problem was the time.sleep()
was interfering with the mainloop()
and your window_to_centralize.update()
which makes it appear before you're finished configuring it.
from tkinter import *
import time
def centralize_over_root(window_to_centralize):
root_geometry = root.winfo_geometry()
root_width_height = root_geometry.split('+')[0]
root_width = root_width_height.split('x')[0]
root_height = root_width_height.split('x')[1]
root_x_y = root_geometry.split(f'{root_height}+')[1]
root_x = root_x_y.split('+')[0]
root_y = root_x_y.split('+')[1]
# window_to_centralize.update() # Don't do this - will happen automatically.
# time.sleep(0.5)
root.after(500) # This pauses without interfering with mainloop.
window_width = window_to_centralize.winfo_width()
window_height = window_to_centralize.winfo_height()
window_x = int(root_x) + round((int(root_width) - int(window_width)) / 2.0)
window_y = int(root_y) + round((int(root_height) - int(window_height)) / 2.0)
result = f'+{window_x}+{window_y}'
return result
def new_window():
new_window = Toplevel(root)
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
root = Tk()
Button(root, text='Make new window', command=new_window).pack(padx=50, pady=50)
root.mainloop()
You can hide the window using withdraw()
and show it after reposition using deiconify()
:
def new_window():
new_window = Toplevel(root)
new_window.withdraw() # hide the window
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
new_window.deiconify() # show the window
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.