2

我知道 Tkinter 有时会让人感到沮丧,但我对调用 Tkinter/ttk Toplevel 小部件/窗口的“正确”序列感到困惑,这将:

  1. 将窗口显示在屏幕中央,不要将其偏离中心然后移动它。

  2. 适当调整窗口大小。

  3. 使窗口成为父窗体的顶层,但不是系统模式(即,不是系统上所有应用程序/窗口的顶层)。

  4. (可选)在 Windows 上创建任务栏按钮。

这是我到目前为止的当前代码,为简单起见,删除了一些不相关的位:

def __init_ui__(self):
    #// Basic setup.
    self.wm_overrideredirect(False)
    self.wm_resizable(False, False)
    self.configure(relief=FLAT, borderwidth=4)

    #// <Some extraneous widget-creation here>

    #// Done!
    self.update()
    self.withdraw()
    self.update_idletasks()
    self.grid()
    self.transient(self._parent)
    self.grab_set()
    self.form.initial_focus()  #// sets initial focus before the window is displayed
    center(self)  #// https://stackoverflow.com/a/10018670
    self.deiconify()
    self._parent._parent.wait_window(self) #// Reaches back to the root Tk() obj.
    # ENDIF
# END __init_ui__

此表单继承自我创建的自定义类,该类包装了一堆小部件创建调用,并且该类继承自object. 第二个继承来自ttk.Toplevel,使其可以访问各种self.wm_*调用和其他 Tkinter 好东西。

也就是说,我确信我的一些函数调用是不需要的。但是这个特殊的调用顺序似乎在 Windows 7 上运行良好。然而,在 X11-over-ssh 下(在 Windows 中使用Xming作为 X 服务器),事情变得有点奇怪。在这种情况下,如果我移动self.update()到 after self.withdraw(),则窗口在 Windows 7 上正确居中而无需重绘,但在 X11 上,它在隐藏时被绘制并正确居中,但几何图形为零(仅压缩窗口边框/装饰显示)。就好像网格传播没有触发一样。

但是self.update()现在在哪里,它在窗口和 X11 上正确调整窗口大小并将窗口居中 - 但您可以看到创建的窗口偏离中心然后移动到两者的中心。

如果我self.wm_attributes("-toolwindow", 1)在 Windows 上使用,那么窗口会在我看不到的情况下居中,但-toolwindow仅适用于 Windows 系统。这对 X11 和 Aqua 都是无效命令。

我想避免一直调用来tk::windowingsystem确定我的窗口管理器是什么,并且必须为 Windows 和 X11 应用不同的 hack。而且我无法测试 Mac/Aqua(不拥有,不会购买),所以我只希望最终外观在该平台上具有一定的功能。

此外,如果我在 Windows 和远程 X11 下单击另一个窗口/应用程序,则通过任务栏按钮单击主窗体仅显示主窗体 - 只有当您单击主窗体内的任何位置时,才会弹出子顶层窗口形式。 固定:(有点)-我忘记了self._transient()通过指定父级来添加一个参数来解决这个问题。今晚早些时候,我没有传递父参数,因此焦点不正确。

那么是否有某种久经考验的魔法配方或对古穆祭司的调用来获得 Tkinter/ttk 顶层窗口的大小、居中并在它不是根窗口的情况下正确获得焦点?使用最小的 X11,Motif-look,顺便说一句。

不,我没有使用 PyGTK、PyQT、wxPython 或其他一些工具包。它是标准的 Tkinter/ttk 或 bust,因为这是我过去几周学习和编写包装函数的目的。我设计的自动完成组合框是一个可爱的小装置。仍然有点错误,但这是另一个 SO 问题的主题......


PS,关于 Effbot 的 Tkinter 食谱已关闭。看起来像服务器崩溃。有没有人碰巧镜像了那个网站?

4

1 回答 1

2

解决了!不得不稍微调整调用的顺序:

#// Done!
self.withdraw()
self.grid()
self.transient(self._parent)
self.grab_set()
self.form.initial_focus()
center(self)
self.deiconify()
self._parent._parent.wait_window(self)

但真正的修复是在center()我从这个答案中提出的函数中,通过将调用更改为winfo_width()/winfo_height()winfo_reqwidth()/winfo_reqheight()并添加一个调用update()作为第一个调用center()。现在我让我的对话窗口在中心弹出而没有看到它们移动,焦点被正确应用,它适用于 Windows 和远程 X11。也许有一天,我会发现它在 Mac OS X/Aqua 上的表现如何。

于 2013-06-27T23:05:32.390 回答