如何在 Tkinter 中将窗口置于屏幕中央?

2025-02-20 09:22:00
admin
原创
33
摘要:问题描述:我正在尝试将 tkinter 窗口置于中央。我知道我可以通过编程获取窗口的大小和屏幕的大小,并使用它来设置几何形状,但我想知道是否有更简单的方法将窗口置于屏幕中央。解决方案 1:最简单(但可能不准确)的方法是使用tk::PlaceWindow,它将顶层窗口的路径名作为参数。主窗口的路径名是.impo...

问题描述:

我正在尝试将 tkinter 窗口置于中央。我知道我可以通过编程获取窗口的大小和屏幕的大小,并使用它来设置几何形状,但我想知道是否有更简单的方法将窗口置于屏幕中央。


解决方案 1:

最简单(但可能不准确)的方法是使用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)

您可以使用geometry 方法设置窗口的尺寸和位置。 geometry 字符串的前半部分是窗口的宽度和高度(不包括外框),

后半部分是外框左上角的 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 工具包会导致不合理的大依赖性。

解决方案 2:

您可以尝试使用方法winfo_screenwidthwinfo_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 个下,形成一个正方形)。因此,它通过将窗口放在屏幕中央来完成工作。如果您不想同时使用PyQtTkinter,也许最好从一开始就使用 PyQt。

解决方案 3:

这个答案更适合初学者理解

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

解决方案 4:

Tk 提供了一个辅助函数,可以将其作为tk::PlaceWindow执行此操作,但我不相信它已在 Tkinter 中作为包装方法公开。您可以使用以下命令将小部件居中:

from tkinter import *

app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()

此功能还应正确处理多个显示。它还具有将另一个小部件置于中心或相对于指针(用于放置弹出菜单)的选项,以便它们不会脱离屏幕。

解决方案 5:

这也适用于 Python 3.x,并将窗口置于屏幕中心:

from tkinter import *

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

解决方案 6:

我在这个网站上找到了同一问题的解决方案

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

当然,我根据我的目的对它进行了相应的更改,它起作用了。

解决方案 7:

使用:

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:

这是一个简单的,不需要外部模块:

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

解决方案 9:

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

解决方案 10:

多显示器解决方案(甚至复杂的几何形状)

如果您有一个根窗口并且想要在根窗口当前所在的屏幕中心放置一个弹出窗口,我使用了tkinter和的组合,以便能够将窗口置于当前活动监视器的中心。screeninfo

在这个例子中,root是根窗口,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)

解决方案 11:

我使用框架和扩展选项。非常简单。我想在屏幕中间放置一些按钮。调整窗口大小,按钮保持在中间。这是我的解决方案。

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)

解决方案 12:

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

解决方案 13:

此方法是跨平台的,适用于多个显示器/屏幕(以活动屏幕为目标),并且不需要除 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。

解决方案 14:

我认为这是一个可能的解决方案:

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

解决方案 15:

我的做法是get_monitors从 导入函数screeninfo。然后设置我喜欢的窗口宽度和高度。最后,我计算位置并将所有内容作为字符串.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}")

解决方案 16:

截至 2024 年 11 月,以下内容适用于 Python 3.13.0 和 Tkinter 8.6:

import tkinter as tk


def scale_and_center_window(window: tk.Tk, pct: float = 0.75, multiple_of: int = 100) -> None:
    """
    Scale and center the Tkinter window in the middle of the screen using the specified percentage,
    rounded to the specified multiple of value.
    :param window: The Tkinter window to size and center.
    :param pct: Percentage of the available device width and height to use (between 0 and 1).
    :param multiple_of: The multiple of value that the scaled window should be rounded to.
    """
    window.update_idletasks()

    device_width = window.winfo_screenwidth()
    scaled_width = int(device_width * pct / multiple_of) * multiple_of

    device_height = window.winfo_screenheight()
    scaled_height = int(device_height * pct / multiple_of) * multiple_of

    x = int((device_width - scaled_width)) // 2
    y = int((device_height - scaled_height)) // 2

    window_geometry = f'{scaled_width}x{scaled_height}+{x}+{y}'
    print(f'{window_geometry=}')
    window.geometry(window_geometry)

例子:

root = tk.Tk()    
scale_and_center_window(root, 4./5, multiple_of = 32)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用