问题
I\'m trying to center a tkinter window. I know I can programatically get the size of the window and the size of the screen and use that to set the geometry, but I\'m wondering if there\'s a simpler way to center the window on the screen.
回答1:
You can try to use the methods winfo_screenwidth
and winfo_screenheight
, which return respectively the width and height (in pixels) of your Tk
instance (window), and with some basic math you can center your window:
import tkinter as tk
from PyQt4 import QtGui # or PySide
def center(toplevel):
toplevel.update_idletasks()
# Tkinter way to find the screen resolution
# screen_width = toplevel.winfo_screenwidth()
# screen_height = toplevel.winfo_screenheight()
# PyQt way to find the screen resolution
app = QtGui.QApplication([])
screen_width = app.desktop().screenGeometry().width()
screen_height = app.desktop().screenGeometry().height()
size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
x = screen_width/2 - size[0]/2
y = screen_height/2 - size[1]/2
toplevel.geometry("+%d+%d" % (x, y))
toplevel.title("Centered!")
if __name__ == '__main__':
root = tk.Tk()
root.title("Not centered")
win = tk.Toplevel(root)
center(win)
root.mainloop()
I am calling update_idletasks
method before retrieving the width and the height of the window in order to ensure that the values returned are accurate.
Tkinter doesn't see if there are 2 or more monitors extended horizontal or vertical. So, you 'll get the total resolution of all screens together and your window will end-up somewhere in the middle of the screens.
PyQt from the other hand, doesn't see multi-monitors environment either, but it will get only the resolution of the Top-Left monitor (Imagine 4 monitors, 2 up and 2 down making a square). So, it does the work by putting the window on center of that screen. If you don't want to use both, PyQt and Tkinter, maybe it would be better to go with PyQt from start.
回答2:
The simplest (but possibly inaccurate) method is to use tk::PlaceWindow, which takes the ID of a toplevel window as an argument.
The general approach to centering a window is to calculate the appropriate screen coordinates for the window's top left pixel:
x = (screen_width / 2) - (window_width / 2)
y = (screen_height / 2) - (window_height / 2)
With tkinter you always want to call the update_idletasks() method
directly before retrieving any geometry, to ensure that the values returned are accurate.
For example:
def center(win):
win.update_idletasks()
width = win.winfo_width()
height = win.winfo_height()
x = (win.winfo_screenwidth() // 2) - (width // 2)
y = (win.winfo_screenheight() // 2) - (height // 2)
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
See also: winfo_reqwidth(), winfo_reqheight()
However, this is not sufficient for accurately centering a tkinter window on certain platforms (e.g. Windows 7), or more specifically when using certain window managers, because the window's width and height returned by any method will not include the outermost frame, with the title and min/max/close buttons. It will also not include a menu bar (with File, Edit, etc.). Fortunately, there is a way to find the dimensions of these.
First, you need to understand the geometry strings used with the geometry() method.
The first half is the window's width and height excluding the outer-frame,
and the second half is the outer-frame's top left x and y coordinates.
There are four methods that will allow us to determine the outer-frame's dimensions.winfo_rootx()
will give us the window's top left x coordinate, excluding the outer-frame.winfo_x()
will give us the outer-frame's top left x coordinate.
Their difference is the outer-frame's width.
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = win.winfo_width() + (2*frm_width)
The difference between winfo_rooty()
and winfo_y()
will be our title-bar / menu-bar's height.
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = win.winfo_height() + (titlebar_height + frm_width)
Here is the complete function, in a working example:
import tkinter # Python 3
def center(win):
"""
centers a tkinter window
:param win: the root or Toplevel window to center
"""
win.update_idletasks()
width = win.winfo_width()
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = width + 2 * frm_width
height = win.winfo_height()
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = height + titlebar_height + frm_width
x = win.winfo_screenwidth() // 2 - win_width // 2
y = win.winfo_screenheight() // 2 - win_height // 2
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
win.deiconify()
if __name__ == '__main__':
root = tkinter.Tk()
root.attributes('-alpha', 0.0)
menubar = tkinter.Menu(root)
filemenu = tkinter.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=root.destroy)
menubar.add_cascade(label="File", menu=filemenu)
root.config(menu=menubar)
frm = tkinter.Frame(root, bd=4, relief='raised')
frm.pack(fill='x')
lab = tkinter.Label(frm, text='Hello World!', bd=4, relief='sunken')
lab.pack(ipadx=4, padx=4, ipady=4, pady=4, fill='both')
center(root)
root.attributes('-alpha', 1.0)
root.mainloop()
One way to prevent seeing the window move across the screen is to use
.attributes('-alpha', 0.0) to make the window fully transparent and then set it to 1.0
after the window has been centered. Using withdraw()
or iconify()
later followed by deiconify()
doesn't seem to work well, for this purpose, on Windows 7. Note that I use deiconify()
as a trick to activate the window.
You might want to consider providing the user with a flag and/or option to center the window, and not center by default; otherwise, your code can interfere with the window manager's functions. For example, xfwm4 has smart placement, which places windows side by side until the screen is full. It can also be set to center all windows, in which case you won't have the problem of seeing the window move (as addressed above).
回答3:
Tk provides a helper function that can do this as tk::PlaceWindow, but I don't believe it has been exposed as a wrapped method in Tkinter. You would center a widget using the following:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()
This function should deal with multiple displays correctly as well. It also has options to center over another widget or relative to the pointer (used for placing popup menus), so that they don't fall off the screen.
回答4:
I have found a solution for the same question on this site
from tkinter import Tk
from tkinter.ttk import Label
root = Tk()
Label(root, text="Hello world").pack()
# Apparently a common hack to get the window size. Temporarily hide the
# window to avoid update_idletasks() drawing the window in the wrong
# position.
root.withdraw()
root.update_idletasks() # Update "requested size" from geometry manager
x = (root.winfo_screenwidth() - root.winfo_reqwidth()) / 2
y = (root.winfo_screenheight() - root.winfo_reqheight()) / 2
root.geometry("+%d+%d" % (x, y))
# This seems to draw the window frame immediately, so only call deiconify()
# after setting correct window position
root.deiconify()
root.mainloop()
sure, I changed it correspondingly to my purposes, it works.
回答5:
This answer is better for understanding beginner
#import tkinter as tk
win = tk.Tk() # Creating instance of Tk class
win.title("Centering windows")
win.resizable(False, False) # This code helps to disable windows from resizing
window_height = 500
window_width = 900
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
win.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
win.mainloop()
回答6:
I use frame and expand option. Very simple. I want some buttons in the middle of screen. Resize window and button stay in the middle. This is my solution.
frame = Frame(parent_window)
Button(frame, text='button1', command=command_1).pack(fill=X)
Button(frame, text='button2', command=command_2).pack(fill=X)
Button(frame, text='button3', command=command_3).pack(fill=X)
frame.pack(anchor=CENTER, expand=1)
回答7:
Use:
import tkinter as tk
if __name__ == '__main__':
root = tk.Tk()
root.title('Centered!')
w = 800
h = 650
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))
root.mainloop()
回答8:
This works also in Python 3.x and centers the window on screen:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow . center')
app.mainloop()
来源:https://stackoverflow.com/questions/3352918/how-to-center-a-window-on-the-screen-in-tkinter