对于某些 tkinter 应用程序想要保存/恢复 Windows 配置。使用geometry()方法。得到我无法理解的结果,我在下面编写了一个例子来说明问题。
$ python
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from tkinter import *
>>> t1 = Toplevel()
>>> t1.title('T1')
''
>>> m = Menu(t1)
>>> t1.config(menu=m)
>>> m.add_command(label='Save')
>>> t2 = Toplevel()
>>> t2.config(menu=m)
>>> t2.title('T2')
''
用鼠标将T1移动到屏幕上的任意位置(最好不要在左上角)。
>>> t2.geometry(t1.geometry())
''
>>>
尽管 Geometry() 报告相同的大小/位置,但窗口在屏幕上的放置方式不同(x、y 相差 10 个像素)。 “手动”移动 T1 窗口至关重要,如果通过 Geometry() 移动,则不会观察到位移。
使用 Debian GNU/Linux 11(靶心)、GNOME Shell 3.38.6
9/20 更新
在执行以下命令之前,通过鼠标使T1、T2具有相同的大小/位置:
>>> t2.geometry(t1.geometry())
该命令按预期工作,窗口[继续]具有相同的大小/位置,并且 .geometry() 报告相同的结果。
PS 当 OP 中的示例在没有任何位移的情况下工作时发现异常。当窗口设置完毕后,发出命令就足够了:
>>> t1.geometry('200x200+-10+19')
PPS 如果在其他平台尝试一下会有很大帮助。
更新9/21
找到了一种从另一个侧面说明问题的方法。
以下代码使 T1、T2 窗口在屏幕上的大小/位置相同:
import tkinter as tk
r = tk.Tk()
r.withdraw()
t1, t2 = tk.Toplevel(r), tk.Toplevel(r)
t1.title('T1')
t2.title('T2')
def reset2(w):
'''Kind of sync window manager and geometry function'''
def pos(w):
g = w.geometry()
return g[g.find('+'):]
r.update_idletasks()
p = pos(w)
r.update_idletasks()
w.geometry('+-10+19')
r.update_idletasks()
w.geometry(p)
reset2(t1)
reset2(t2)
t2.geometry(t1.geometry())
tk.mainloop()
更新9/24
问题简而言之:通过鼠标移动窗口(与通过调用 .geometry() 方法移动)后, .geometry() 方法报告错误的位置(x、y 相差 10 像素)
更新9/25
>>> from tkinter import Tk,Toplevel
>>> r = Tk()
>>> r.withdraw()
''
>>> t1 = Toplevel(r)
>>> t1.title('T1')
''
>>> t2 = Toplevel(r)
>>> t2.title('T2')
''
>>> g1 = t1.winfo_geometry()
>>> x, y = map(int, g1.split('+')[1:])
>>> y -= 37
>>> t2.geometry(f'+{x}+{y}')
''
现在 T1、T2 窗口在屏幕上视觉上无法区分
>>> t1.winfo_geometry(), t2.winfo_geometry()
('200x200+88+152', '200x200+88+152')
>>>
>>> t1.geometry(), t2.geometry()
('200x200+78+107', '200x200+88+115')
我想我需要更好地理解 .geometry() 是如何工作的
这是一个解决方法。
class T1(tk.Toplevel):
def __init__(self):
super().__init__()
menu = tk.Menu(self, tearoff=0)
self.config(menu=menu)
menu.add_command(label='Sway', command=self.sway)
def getxy(self, g=None):
if g is None:
g = self.geometry()
return map(int, g.split('+')[1:])
def sway_needed(self):
xg, _ = self.getxy()
xw, _ = self.getxy(self.winfo_geometry())
return xw != xg
def sway(self):
if not self.sway_needed():
return
x0, y0 = self.getxy()
self.geometry(f'+{x0 + 1}+{y0}')
self.update_idletasks()
self.geometry(f'+{x0 - 1}+{y0}')
self.geometry(f'+{x0}+{y0}')
self.update_idletasks()
用鼠标移动T1窗口后(到任意位置):
>>> t1 = T1()
>>> t1.geometry()
'200x200+776+535'
报告的位置是+776+535,但t1在屏幕上的实际位置是+786+545。调用“Sway”菜单项后,窗口明显移动,实际位置 (+776+535) 和报告的位置变得相同(由 screenruler 验证)
sway_needed()方法用于检测报告位置与实际位置不匹配。 sway() 方法——希望“修复”这个问题
我最初的目标是保存Toplevel Windows 配置。因为它是按需完成的,所以我可以调用 sway()。 .sway() 不影响窗口几何形状。我测试了 sway() 由 .after()
安排