Python 如何在Tkinter中使屏幕上的窗口居中?

Python 如何在Tkinter中使屏幕上的窗口居中?,python,tkinter,centering,Python,Tkinter,Centering,我正试着把一扇窗户放在中间。我知道我可以通过编程获得窗口的大小和屏幕的大小,并使用它们来设置几何图形,但我想知道是否有一种更简单的方法可以使窗口在屏幕上居中。您可以尝试使用分别返回宽度和高度的方法winfou screenwidth和winfou screenheight(以像素为单位)的Tk实例(窗口),通过一些基本的数学运算,您可以将窗口居中: import tkinter as tk from PyQt4 import QtGui # or PySide def center(to

我正试着把一扇窗户放在中间。我知道我可以通过编程获得窗口的大小和屏幕的大小,并使用它们来设置几何图形,但我想知道是否有一种更简单的方法可以使窗口在屏幕上居中。

您可以尝试使用分别返回宽度和高度的方法
winfou screenwidth
winfou 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\u idletasks
方法,以确保返回的值是准确的

Tkinter不知道是否有2个或多个监视器延伸水平或垂直。因此,你将得到所有屏幕的总分辨率,而你的窗口将在屏幕中间某个地方结束。

另一方面,PyQt也看不到多监视器环境,但它只能获得左上角监视器的分辨率(想象4个监视器,2个向上和2个向下组成一个正方形)。因此,它通过将窗口放在屏幕中心来完成工作。如果您不想同时使用PyQt和Tkinter,那么最好从一开始就使用PyQt。

最简单(但可能不准确)的方法是使用,它将顶级窗口的属性作为参数。主窗口的路径名是

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,您总是希望调用方法
在检索任何几何图形之前,确保返回的值准确无误

有四种方法允许我们确定外部框架的尺寸。
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}')

您可以看到窗口移动

    #  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)
防止窗口在屏幕上移动的一种方法是使用 使窗口完全透明,然后在窗口居中后将其设置为
1.0
。在Windows 7上,使用
draw()
iconify()
之后再使用
deiconify()
似乎效果不好。我使用
deiconify()
作为激活窗口的技巧


使其成为可选的

您可能想考虑为用户提供一个窗口的选项,而不是默认为中心;否则,您的代码会干扰窗口管理器的功能。例如,XFWM4具有智能布局,它将窗口并排放置到屏幕满。它还可以设置为所有窗口的中心,在这种情况下,您将获得我看不到车窗移动的问题(如上所述)


多个监视器


如果多监视器场景与您有关,那么您可以查看项目,或者查看使用or可以完成的任务,然后使用这些工具箱中的一个,而不是tkinter。组合GUI工具箱会导致不合理的大依赖性。

Tk提供了一个帮助器函数,可以这样做,但我不相信它必须如此en在Tkinter中作为包装方法公开。您可以使用以下命令将小部件居中放置:

from tkinter import *

app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.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)

我已经为同样的问题找到了解决办法

当然,我根据我的目的相应地更改了它,它可以工作。

使用:

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()
这个答案对于初学者来说更容易理解 #
这也适用于Python 3.x,并使窗口位于屏幕中央:

from tkinter import *

app = Tk()
app.eval('tk::PlaceWindow . center')
app.mainloop()

在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)

此方法是跨平台的,适用于多个监视器/屏幕(以活动屏幕为目标),不需要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\u idletasks()
以强制同步/立即执行操作。它使用Python 3功能,但如果需要,可以轻松地适应Python 2.x。

不太强大有点主观。它与其他工具包一样具有强大的“功能”(取决于你对“权力”的定义),它只是没有那么多的牵手作用。它是用预制墙(一些其他工具包)建造房子和用一堆木材(Tk)建造房子的区别.你几乎可以在Tkinter中做任何你可以在其他工具包中做的事情,你只是有时需要为它做一点工作。@Bryan-这正是我所说的权力。当然你可以在Yugo(m)中穿越美国
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()
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()