[英]How to center a window on the screen in Tkinter?
我正在尝试将 tkinter window 居中。我知道我可以通过编程方式获取 window 的大小和屏幕的大小并使用它来设置几何图形,但我想知道是否有更简单的方法将 window 居中屏幕。
最简单(但可能不准确)的方法是使用tk::PlaceWindow ,它将顶层窗口的路径名作为参数。 主窗口的路径名是.
import tkinter
root = tkinter.Tk()
root.eval('tk::PlaceWindow . center')
second_win = tkinter.Toplevel(root)
root.eval(f'tk::PlaceWindow {str(second_win)} center')
root.mainloop()
问题
简单的解决方案会忽略带有标题栏和菜单栏的最外层框架,这会导致稍微偏离真正居中的位置。
解决方案
import tkinter # Python 3
def center(win):
"""
centers a tkinter window
:param win: the main window 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()
使用 tkinter 你总是想调用update_idletasks()
方法
直接在检索任何几何图形之前,以确保返回的值是准确的。
有四种方法可以让我们确定外框的尺寸。
winfo_rootx()
将为我们提供窗口左上角的 x 坐标,不包括外框。
winfo_x()
将为我们提供外框左上角的 x 坐标。
它们的区别在于外框的宽度。
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = win.winfo_width() + (2*frm_width)
winfo_rooty()
和winfo_y()
之间的区别将是我们的标题栏/菜单栏的高度。
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = win.winfo_height() + (titlebar_height + frm_width)
您可以使用几何方法设置窗口的尺寸和位置。 几何字符串的前半部分是窗口的宽度和高度,不包括外框,
后半部分是外框左上角的 x 和 y 坐标。
win.geometry(f'{width}x{height}+{x}+{y}')
你看到窗户移动
防止看到窗口在屏幕上移动的一种方法是使用.attributes('-alpha', 0.0)
使窗口完全透明,然后在窗口居中后将其设置为1.0
。 为此,在 Windows 7 上,使用withdraw()
或iconify()
后跟deiconify()
似乎效果不佳。我使用deiconify()
作为激活窗口的技巧。
使其成为可选
您可能需要考虑为用户提供使窗口居中的选项,而不是默认居中; 否则,您的代码可能会干扰窗口管理器的功能。 例如,xfwm4 具有智能放置功能,可以将窗口并排放置,直到满屏为止。 也可以将其设置为所有窗口居中,在这种情况下,您不会遇到看到窗口移动的问题(如上所述)。
多台显示器
如果您关心多显示器场景,那么您可以查看screeninfo项目,或者查看使用Qt (PySide6)或GTK (PyGObject)可以完成的工作,然后使用其中一个工具包而不是 tkinter。 组合 GUI 工具包会导致过度依赖。
您可以尝试使用winfo_screenwidth
和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()
我在检索窗口的宽度和高度之前调用了update_idletasks
方法,以确保返回的值是准确的。
Tkinter看不到是否有 2 个或更多显示器水平或垂直扩展。 因此,您将获得所有屏幕的总分辨率,并且您的窗口最终将位于屏幕中间的某个位置。
另一方面, PyQt也看不到多显示器环境,但它只会获得左上角显示器的分辨率(想象 4 个显示器,2 个向上和 2 个向下组成一个正方形)。 因此,它通过将窗口放在该屏幕的中心来完成工作。 如果您不想同时使用PyQt和Tkinter ,那么从一开始就使用 PyQt 可能会更好。
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()
Tk 提供了一个辅助函数,可以作为tk::PlaceWindow执行此操作,但我不相信它已作为 Tkinter 中的包装方法公开。 您将使用以下方法将小部件居中:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()
此功能也应正确处理多个显示器。 它还具有将另一个小部件居中或相对于指针(用于放置弹出菜单)居中的选项,这样它们就不会从屏幕上掉下来。
这也适用于 Python 3.x 并在屏幕上居中显示窗口:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow . center')
app.mainloop()
我在这个网站上找到了相同问题的解决方案
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()
当然,我根据我的目的相应地更改了它,它有效。
利用:
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()
我使用框架和扩展选项。 很简单。 我想要屏幕中间的一些按钮。 调整窗口大小和按钮位于中间。 这是我的解决方案。
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)
在 PYTHON Tkinter 中居中窗口 这是 tkinter中最简单的事情,因为我们必须知道的只是窗口的尺寸以及计算机屏幕的尺寸。 我想出了以下代码,它可以以某种方式帮助某人,我确实添加了一些评论,以便他们可以跟进。
代码
# create a window first
root = Tk()
# define window dimensions width and height
window_width = 800
window_height = 500
# get the screen size of your computer [width and height using the root object as foolows]
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Get the window position from the top dynamically as well as position from left or right as follows
position_top = int(screen_height/2 -window_height/2)
position_right = int(screen_width / 2 - window_width/2)
# this is the line that will center your window
root.geometry(f'{window_width}x{window_height}+{position_right}+{position_top}')
# initialise the window
root.mainloop(0)
from tkinter import *
root = Tk()
# Gets the requested values of the height and widht.
windowWidth = root.winfo_reqwidth()
windowHeight = root.winfo_reqheight()
print("Width",windowWidth,"Height",windowHeight)
# Gets both half the screen width/height and window width/height
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2)
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
root.geometry("+{}+{}".format(positionRight, positionDown))
root.mainloop()
此方法是跨平台的,适用于多个监视器/屏幕(针对活动屏幕),并且除了 Tk 之外不需要其他库。 根窗口将居中显示,没有任何不需要的“闪烁”或动画:
import tkinter as tk
def get_geometry(frame):
geometry = frame.winfo_geometry()
match = re.match(r'^(\d+)x(\d+)\+(\d+)\+(\d+)$', geometry)
return [int(val) for val in match.group(*range(1, 5))]
def center_window(root):
"""Must be called after application is fully initialized
so that the root window is the true final size."""
# Avoid unwanted "flashing" by making window transparent until fully ready
root.attributes('-alpha', 0)
# Get dimensions of active screen/monitor using fullscreen trick; withdraw
# window before making it fullscreen to preserve previous dimensions
root.withdraw()
root.attributes('-fullscreen', True)
root.update_idletasks()
(screen_width, screen_height, *_) = get_geometry(root)
root.attributes('-fullscreen', False)
# Restore and get "natural" window dimensions
root.deiconify()
root.update_idletasks()
(window_width, window_height, *_) = get_geometry(root)
# Compute and set proper window center
pos_x = round(screen_width / 2 - window_width / 2)
pos_y = round(screen_height / 2 - window_height / 2)
root.geometry(f'+{pos_x}+{pos_y}')
root.update_idletasks()
root.attributes('-alpha', 1)
# Usage:
root = tk.Tk()
center_window(root)
请注意,在修改窗口几何图形的每个点,都必须调用update_idletasks()
以强制操作同步/立即发生。 它使用 Python 3 功能,但如有必要,可以轻松适应 Python 2.x。
我认为这是一个可能的解决方案:
import pyautogui
from tkinter import *
x=pyautogui.size()[0]
y=pyautogui.size()[1]
root=Tk()
root.geometry('300x200+'+str(int(x/2-150))+'+'+str(int(y/2-100)))
# x/2 and y/2 fin the display center and -<a half of x root> and -<a half of #y root> #serve to center root
root.mainloop()
我这样做的方法是从screeninfo
导入get_monitors
函数。 然后设置我的窗口的首选宽度和高度。 最后,我计算位置并将所有内容插入为.geometry()
方法输入的字符串。
from screeninfo import get_monitors
import tkinter as tk
# Set the size of my window to whatever I like
WIN_WIDTH = 350
WIN_HEIGHT = 250
root = tk.Tk()
root.geometry.(f"{WIN_WIDTH}x{WIN_HEIGHT}+{(get_monitors()[0].width - WIN_WIDTH)//2}+{(get_monitors()[0].height - WIN_HEIGHT)//2}")
这是一个不需要外部模块的简单的:
import tkinter as tk
root = tk.Tk()
WIDTH = 300
HEIGHT = 250
x = int((root.winfo_screenwidth() / 2) - (WIDTH / 2))
y = int((root.winfo_screenheight() / 2) - (HEIGHT / 2))
root.geometry(f'{WIDTH}x{HEIGHT}+{x}+{y}')
root.mainloop()
I used a combination of tkinter
and screeninfo
to be able to center windows on the currently active monitor in the case you have a root window and want to place a popup on the center of the screen the root window currently resides in.
在此示例中, root
是根 window, popup
是要放置在root
所在屏幕中心的弹出窗口。
如果您的屏幕以比彼此相邻更复杂的方式设置,例如在彼此之上,则此解决方案也适用。
import tkinter as tk
from screeninfo import get_monitors
def place_popup(popup: tk.Toplevel, root: tk.Tk, width: int, height: int) -> None:
"""Places a new window in the middle of the selected screen"""
monitor = get_monitor_from_coord(root.winfo_x(), root.winfo_y())
popup.geometry(
f"{width}x{height}+{(monitor.width - width) // 2 + monitor.x}+{(monitor.height - height) // 2+ monitor.y}")
def get_monitor_from_coord(x, y):
"""Find the active monitor from tkinter geometry coords"""
monitors = get_monitors()
for m in reversed(monitors):
if m.x <= x <= m.width + m.x and m.y <= y <= m.height + m.y:
return m
return monitors[0]
...
place_popup(popup, root, width, height)
这是一个方便的静态函数,它支持将窗口居中放置在父窗口上。
NJoy。
代码:
@staticmethod
def center_window(root, width=0, height=0, centering_on_parent=False):
'''
Centers a Tk window on screen or on parent window in use as a dialog
and sets geometry (width and height).
----------------------------------------------------------------------
usage for centered window on screen:
root.geometry(center_window(root, app_width, app_height)
usage for centering window on a parent window (like a dialog):
dialog.geometry(center_window(root, dialog_width, dialog_height, True)
----------------------------------------------------------------------
'''
x=None; y=None;
if centering_on_parent:
root_width = root.winfo_width()
root_height = root.winfo_height()
root_x = root.winfo_rootx()
root_y = root.winfo_rooty()
x = (root_x + (root_width/2))- width/2
y = (root_y + (root_height/2))- height/2 - 32 # height of titlebar of the window-border to fix a bit lower position
else:
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = (screen_width/2) - (width/2)
y = (screen_height/2) - (height/2)
return f'{width}x{height}+{int(x)}+{int(y)}'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.