如何获取 tkinter 窗口标题栏的高度

Dan*_*son 8 python tkinter

我试图弄清楚如何获得 tkInter 窗口标题栏的高度,但似乎找不到任何关于它是如何完成的信息。

我试过使用root.geometry(),似乎root.geometry()只返回窗口内容的大小,而不是带有标题栏和边框大小的窗口的总大小。我看到其他人说你需要向操作系统询问这些事情。我希望避免这种情况,因为它会使代码平台独立变得更加困难。必须有一种方法可以做到这一点,而无需为此前往操作系统。有谁知道我必须做什么才能获得这些信息?

我的系统:

操作系统:Linux

KDE 等离子: 5.16.4

KDE 框架: 5.61.0


import tkinter

root = tkinter.Tk()
root.geometry("250x250+100+100")
root.update_idletasks()

print('root.winfo_x() = ', root.winfo_x())
print('root.winfo_y() = ', root.winfo_y())
print('root.geometry() = ', root.geometry())

root.mainloop()
Run Code Online (Sandbox Code Playgroud)

测试代码结果:

    root.winfo_x() =  100
    root.winfo_y() =  100
    root.geometry() =  250x250+100+100
Run Code Online (Sandbox Code Playgroud)

使用屏幕标尺应用程序测量的窗口高度为:

x=102, y=286
Run Code Online (Sandbox Code Playgroud)

jiz*_*AMA 7

标题栏(默认)是系统设置。据我所知,它取决于很多因素。(系统缩放比例、不同的操作系统、DPI 意识等)。

在windows中,改变缩放比例会得到不同的高度值。


关于问题:tkinter在windows中会被识别为旧软件,需要设置DPI感知使其具有系统正常高度(如果系统缩放比例不是100%,则适合系统缩放比例)。

通常,系统标题栏的高度是相同的:但有些例外(我不太了解winapi),不同的 DPI 意识会显示标题栏的不同高度: 在此处输入图片说明 相同: 在此处输入图片说明

要使它们相同并获得标题栏的正常高度:

import tkinter
import ctypes

ctypes.windll.shcore.SetProcessDpiAwareness(2)
print(ctypes.windll.user32.GetSystemMetrics(4))
root = tkinter.Tk()

root.mainloop()
Run Code Online (Sandbox Code Playgroud)

结果: 在此处输入图片说明 在此处输入图片说明

请参阅:MSDN 文档:GetSystemMetricsDPI 意识DPI 意识的价值)。


Dan*_*son 3

我终于明白了这一点。为了获得标题栏的高度,我首先向窗口添加了一个框架并设置窗口几何形状('1x1')。我还必须使用 update_idletasks() 来更新 tkinter 内部数据。这样做之后我得到了正确的高度。必须这样做似乎很奇怪,但它确实有效。下面是我用来获取高度的代码。已在 Windows 和 Linux 上测试并运行。如果有人知道更正确的方法来做到这一点,我肯定想知道。另外,如果有人使用苹果,请告诉我下面的代码是否有效。

更新:我已经更新了代码,并且已经在(Linux、Windows 和 MacOS)中进行了测试,以给出正确的标题栏高度。我认为这是最好的方法,因为您不需要进行依赖于操作系统的系统调用。但我不知道它是否适用于任何缩放级别。


更新:现在可以适用于任何缩放级别。(在 Windows 10、Windows 7 中通过测试)

import tkinter as tk
from sys import platform


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        tk.Frame(self).update_idletasks()
        self.geometry('350x200+100+100')
        self.update_idletasks()

        offset_y = 0
        if platform in ('win32', 'darwin'):
            import ctypes
            try: # >= win 8.1
                ctypes.windll.shcore.SetProcessDpiAwareness(2)
            except: # win 8.0 or less
                ctypes.windll.user32.SetProcessDPIAware()
            offset_y = int(self.geometry().rsplit('+', 1)[-1])

        bar_height = self.winfo_rooty() - offset_y
        print(f'Height: {bar_height}\nPlatform: {platform}')
        #  self.destroy()


def main():
    app = App()
    app.mainloop()


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

  • 我已经在 macOS 上测试了代码,它给出了正确的标题栏高度。 (2认同)