3 回答
TA贡献1829条经验 获得超7个赞
最简单(但可能不准确)的方法是使用tk :: PlaceWindow,该方法将顶级窗口的ID作为参数。
使窗口居中的一般方法是为窗口的左上像素计算适当的屏幕坐标:
x = (screen_width / 2) - (window_width / 2)
y = (screen_height / 2) - (window_height / 2)
使用tkinter时,您总是希望 在检索任何几何图形之前直接调用该update_idletasks()方法
,以确保返回的值是准确的。
例如:
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))
另请参阅:winfo_reqwidth(),winfo_reqheight()
然而,这是不足够准确在某些平台上为中心的Tkinter的窗口(例如,Windows 7),或者更具体地使用某些时窗口管理器,因为窗口的宽度和高度由返回任何方法将不包括最外层框架,与该标题和最小/最大/关闭按钮。它还不包括菜单栏 (带有文件,编辑等)。幸运的是,有一种方法可以找到这些尺寸。
首先,您需要了解该方法使用的几何字符串geometry()。
前半部分是窗口的宽度和高度(不包括外部框架),
后半部分是外部框架的左上角x和y坐标。
有四种方法可以让我们确定外框的尺寸。
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)
在一个有效的示例中,这是完整的功能:
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()
一种防止看到窗口在屏幕上移动的方法是 .attributes('-alpha', 0.0)使窗口完全透明,然后将其设置1.0为居中后。为此,在Windows 7上,使用withdraw()或iconify()稍后再使用deiconify()似乎不太理想,请注意,我将deiconify()以此作为激活窗口的技巧。
您可能需要考虑向用户提供标记和/或选项来使窗口居中,而不是默认居中;否则,您的代码可能会干扰窗口管理器的功能。例如,xfwm4具有智能位置,该位置可以并排放置窗口,直到屏幕满为止。也可以将其设置为使所有窗口居中,在这种情况下,您将不会看到窗口移动的问题(如上所述)。
TA贡献1812条经验 获得超5个赞
Tk提供了一个辅助功能,可以像tk :: PlaceWindow一样执行此操作,但我不认为它已在Tkinter中作为包装方法公开。您可以使用以下命令将小部件居中:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()
此功能也应正确处理多个显示。它还具有使另一个控件居中或相对于指针居中的选项(用于放置弹出菜单),以使它们不会从屏幕上掉落。
添加回答
举报