zih301
zih301

Reputation: 135

Centering window python tkinter

Ive recently started using tkinter in python, and I was having trouble centering the window. I tried all the tips on this website, but whenever I try them, the window is like a line in the middle of the screen. I have widgets already on it, and it works fine without the centering, but I would really appreciate it if someone could help me solve my problem. This is what I have been trying so far.

root = Tk()
root.title("Password")
root.resizable(FALSE,FALSE)

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

w = mainframe.winfo_width()
h = mainframe.winfo_height()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))

Upvotes: 4

Views: 13297

Answers (3)

Luka Sh
Luka Sh

Reputation: 350

Hopefully someone will find use of this code, basically this is a solution you can use to center a TopLevel window relative to master (parent) window. Probably not the cleanest solution, but it will get the work done.

from Tkinter import *

class PasswordDialog(Toplevel):

    def __init__(self, master=None):
        Toplevel.__init__(self, master)
        self.master = master

        self.title("Password")

        self.label_info = Label(self, text="You need to enter your password", pady=10)
        self.label_info.grid(row=0, column=0, columnspan=2, padx=20, pady=10, sticky="ew")
        self.label_pw = Label(self, text="Enter password:", pady=10)
        self.label_pw.grid(row=1, column=0, padx=(20, 2), sticky="e")
        self.entry = Entry(self, show="*")
        self.entry.bind("<KeyRelease-Return>", self.store_pass_event)
        self.entry.grid(row=1, column=1, padx=(2,20), sticky="w")
        self.button = Button(self, command=self.store_pass, text="Log in")
        self.button.grid(row=2, column=0, columnspan=2, pady=10)

        self.update()

        size = tuple(int(_) for _ in self.geometry().split('+')[0].split('x'))
        parent_offset = tuple(int(_) for _ in self.master.geometry().split('x')[1].split('+'))

        parent_width = self.master.winfo_width()
        parent_height = self.master.winfo_height()
        
        x = parent_width//2 - size[0]//2 + parent_offset[1]
        y = parent_height//2 - size[1]//2 + parent_offset[2]

        self.geometry("+%d+%d" % (x, y))

    def store_pass_event(self, event):
        self.store_pass()

    def store_pass(self):
        self.master.password = self.entry.get()
        self.destroy()

Upvotes: -1

zih301
zih301

Reputation: 135

Ok I have found and fixed the problem. Piggybacking off of OregonTrail's solution, i found that if the window is the right size and you just want to change the location, then you can easily instead of setting the root's size, you can just move the window to the center.

w = root.winfo_reqwidth()
h = root.winfo_reqheight()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('+%d+%d' % (x, y)) ## this part allows you to only change the location

I think that this answer isn't exactly in the center, probably off by a little since h was returning 200 when it should be less, but it looks to be at the center and works fine.

Upvotes: 4

OregonTrail
OregonTrail

Reputation: 9039

You need to use winfo_reqwidth() and winfo_reqheight(), because the window does not have a height or width at the time that you call winfo_height() and winfo_width().

An example program:

from tkinter import Tk
from tkinter import ttk

root = Tk()

style = ttk.Style()
style.configure("BW.TLabel", foreground="black", background="white")

l1 = ttk.Label(text="This is the best label in the world", style="BW.TLabel")
l1.pack()

w = l1.winfo_reqwidth()
h = l1.winfo_reqheight()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
print(w, h, x, y)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))

root.mainloop()

Upvotes: 3

Related Questions