Python 如何在 Tkinter 的屏幕上居中显示窗口?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3352918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to center a window on the screen in Tkinter?
提问by psicopoo
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.
我正在尝试将 tkinter 窗口居中。我知道我可以以编程方式获取窗口的大小和屏幕的大小,并使用它来设置几何图形,但我想知道是否有一种更简单的方法可以使窗口在屏幕上居中。
采纳答案by Wayne Werner
You can try to use the methods winfo_screenwidthand winfo_screenheight, which return respectively the width and height (in pixels) of your Tkinstance (window), and with some basic math you can center your window:
您可以尝试使用方法winfo_screenwidthand winfo_screenheight,它们分别返回Tk实例(窗口)的宽度和高度(以像素为单位),并通过一些基本的数学运算,您可以将窗口居中:
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_idletasksmethod before retrieving the width and the height of the window in order to ensure that the values returned are accurate.
我update_idletasks在检索窗口的宽度和高度之前调用方法,以确保返回的值是准确的。
Tkinterdoesn'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.
Tkinter看不到是否有 2 个或更多显示器水平或垂直扩展。因此,您将获得所有屏幕的总分辨率,并且您的窗口将最终位于屏幕中间的某个位置。
PyQtfrom 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, PyQtand Tkinter, maybe it would be better to go with PyQt from start.
另一方面,PyQt也看不到多显示器环境,但它只会获得左上角显示器的分辨率(想象一下 4 个显示器,2 个向上和 2 个向下构成一个正方形)。因此,它通过将窗口放在该屏幕的中心来完成工作。如果您不想同时使用PyQt和Tkinter,也许从一开始就使用 PyQt 会更好。
回答by Honest Abe
The simplest (but possibly inaccurate) method is to use tk::PlaceWindow, which takes the ID of a toplevel window as an argument.
最简单(但可能不准确)的方法是使用tk::PlaceWindow,它将顶层窗口的 ID 作为参数。
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.
使用 tkinter,您总是希望
在检索任何几何之前直接调用该update_idletasks()方法
,以确保返回的值准确无误。
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()
另请参阅:winfo_reqwidth(),winfo_reqheight()
However, this is notsufficient for accuratelycentering 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 anymethod 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 wayto find the dimensions of these.
然而,这是不足够准确在某些平台上为中心的Tkinter的窗口(例如,Windows 7),或者更具体地使用某些时窗口管理器,因为窗口的宽度和高度由返回任何方法将不包括最外层框架,与该标题和最小/最大/关闭按钮。它也不包括菜单栏(带有文件、编辑等)。幸运的是,有一种方法可以找到这些维度。
First, you need to understand the geometry stringsused with the geometry()method.
The first half is the window's width and height excludingthe outer-frame,
and the second half is the outer-frame's top left x and y coordinates.
首先,您需要了解与该方法一起使用的几何字符串geometry()。
前半部分是窗口的宽度和高度,不包括外框,
后半部分是外框左上角的 x 和 y 坐标。
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, excludingthe outer-frame.winfo_x()will give us the outer-frame's top left x coordinate.
Their difference is the outer-frame's width.
有四种方法可以让我们确定外框的尺寸。winfo_rootx()将为我们提供窗口的左上角 x 坐标,不包括外框。winfo_x()会给我们外框的左上角 x 坐标。
它们的区别在于外框的宽度。
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.
winfo_rooty()和之间的区别winfo_y()将是我们的标题栏/菜单栏的高度。
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.0after 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.
防止看到窗口在屏幕上移动的一种方法是使用
.attributes('-alpha', 0.0)使窗口完全透明,然后1.0在窗口居中后将其设置为。为此,在 Windows 7 上使用withdraw()或iconify()稍后使用deiconify()似乎效果不佳。请注意,我将其deiconify()用作激活窗口的技巧。
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).
您可能需要考虑为用户提供一个标志和/或选项来使窗口居中,而不是默认居中;否则,您的代码可能会干扰窗口管理器的功能。例如,xfwm4 具有智能放置功能,可以将窗口并排放置,直到屏幕填满为止。它也可以设置为所有窗口居中,在这种情况下,您不会看到窗口移动的问题(如上所述)。
回答by patthoyts
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:
Tk 提供了一个辅助函数,可以作为tk::PlaceWindow执行此操作,但我不相信它已在 Tkinter 中作为包装方法公开。您可以使用以下方法将小部件居中:
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.
此功能也应正确处理多个显示。它还具有将另一个小部件居中或相对于指针(用于放置弹出菜单)的选项,这样它们就不会从屏幕上掉下来。
回答by easyScript
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)
回答by Ievgen S.
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.
当然,我根据我的目的相应地改变了它,它有效。
回答by Hoseong Jeon
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()
回答by Sandeep Prasad Kushwaha
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()
回答by bitagoras
This works also in Python 3.x and centers the window on screen:
这也适用于 Python 3.x 并使窗口在屏幕上居中:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow . center')
app.mainloop()
回答by CONvid19
For PyQt5use:
对于PyQt5使用:
from PyQt5.QtWidgets import QApplication
def center(toplevel):
toplevel.update_idletasks()
app = 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!")

