You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何准确保存与恢复Tkinter主窗口的尺寸和位置

精准保存并恢复Tkinter窗口位置的问题(Ubuntu GNOME环境)

我尝试使用Tkinter保存并恢复主窗口的位置,但遇到了问题:保存geometry()返回的几何值(以及其他获取位置的方法)无法得到准确结果。恢复窗口时,位置会比之前的位置稍微偏左上;其他获取位置的方法返回的x值正确,但y值会偏移标题栏的高度。我的运行环境是Ubuntu(Pop!_OS),使用GNOME桌面。

以下是我的代码:

from tkinter import *
from os.path import exists
import json

settings = {}
SettingFile = "mysettings.json"

class MyRoot(Tk):
  def __init__(self):
    super().__init__()

    wndCfg = { 'Size': [400, 400], 'Pos': [100, 100]}

    if 'MainWnd' in settings:
      wndCfg = settings['MainWnd']
    else:
      settings['MainWnd'] = wndCfg

    s = wndCfg['Size']
    p = wndCfg['Pos']

    self.geometry(f"{s[0]}x{s[1]}+{p[0]}+{p[1]}")

    
  def destroy(self):
    wndGeometry = self.geometry()
    parts = wndGeometry.split('+')
    wndPos = [int(parts[1]), int(parts[2])]
    parts = parts[0].split('x')
    wndSize = [int(parts[0]), int(parts[1])]

    # Various other options for getting the window position, x is correct, 
    # y is off by the height of the title bar
    pos0 = [self.winfo_x(), self.winfo_y()]
    pos1 = [self.winfo_rootx(), self.winfo_rooty()]

    settings['MainWnd']['Pos'] = wndPos # pos0 pos1
    settings['MainWnd']['Size'] = wndSize
    super().destroy()


if __name__ == '__main__':

  if exists(SettingFile):
    with open(SettingFile, 'r') as cfgFile:
      settings = json.load(cfgFile)

  root = MyRoot()
  root.mainloop()

  with open(SettingFile, 'w') as cfgFile:
    json.dump(settings, cfgFile, indent=2)

后续测试更新

  • 尝试运行计算窗口装饰区域的代码,得到标题栏高度为65,但实际通过截图测量的标题栏高度是37。在原代码中使用winfo_x()和winfo_y()-37保存位置,恢复效果完美。
  • 运行另一篇获取标题栏高度的代码,得到的高度为137,结果明显不准确。
  • 尝试延迟设置geometry直到第一个Map事件发布后执行,和原代码效果无差异。进一步测试发现:只有移动窗口后退出再重启,才会出现位置偏移;如果不移动窗口,多次重启应用,窗口都会出现在同一位置。

内容的提问来源于stack exchange,提问作者Murrgon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 05:35:00