tk.顶层窗口出现在错误的位置



我试图定义一个带有组合框的弹出窗口,它在父窗口中做一些事情。
它或多或少完成了(也许不是最好的方式…),除了弹出窗口不会出现在正确的地方:它总是显示在左上角,即使主窗口在其他地方。
我想顶层窗口应该有这种行为。

现在,为了使它与主窗口显示集中,大小合适,我在弹出窗口上使用了geometry方法。
但是要做到这一点,我必须应用update方法,以便窗口的大小是已知的。
这给了我弹出窗口在正确的位置和正确的尺寸。然而,另一个问题出现了:窗口在左上角显示了几分之一秒,然后才显示在正确的位置。
这当然是因为update的调用是在定位和调整大小之前。

代码如下:

import tkinter as tk
from tkinter import ttk
class PopupCombobox():
def __init__(self, p_app, values):
self.master = p_app.root
self.parent = p_app
self.gui = tk.Toplevel(self.master)
# Drop the maximize button, and prevent to resize the window
self.gui.resizable(width=tk.FALSE, height=tk.FALSE)
self.gui.wait_visibility()
self.gui.grab_set()
self.gui.title("Pop up")
self.gui.combo = ttk.Combobox(self.gui, values=values, width=15, state='readonly')
self.gui.combo.grid(column=0, row=0, padx=8, pady=4)
# self.gui.withdraw()
self.gui.update()
# self.gui.iconify()
# self.gui.deiconify()
self.centralize_widget()
self.gui.combo.bind("<<ComboboxSelected>>", self.callback)
def callback(self, event):
self.parent.e.configure(text=self.gui.combo.get())
self.gui.destroy()
def centralize_widget(self):
# (x,y) is the root upper-left corner
x = self.master.winfo_x()
y = self.master.winfo_y()
# The width and height of the root
w_master = self.master.winfo_width()
h_master = self.master.winfo_height()
# The width and height of the widget
w = self.gui.winfo_width()
h = self.gui.winfo_height()
self.gui.geometry("%dx%d+%d+%d" % (w, h, x + (w_master - w)/2, y + (h_master - h)/2))

class App:
def __init__(self, root):
self.root = root
self.root.geometry("300x100+450+300")
self.e = ttk.Label(root, text="text")
self.e.grid()
self.b = ttk.Button(root, text="Pop it up!", command=self.do_it)
self.b.grid()
self.choice = None
def do_it(self):
PopupCombobox(self, values=('a', 'b', 'c', 'd'))

win = tk.Tk()
app = App(win)
win.mainloop()

我尝试了withdraw之前的updateiconifydeiconify之后的注释方法。
对于deiconify,观察到的行为完全相同;使用iconify,程序阻塞。

一定有更好的办法。什么好主意吗?

提前感谢。

我无法在我的电脑上重现你的问题。这似乎取决于系统速度。但解决方案可以是:

self.gui.attributes('-alpha', 0) #makes window invisible
self.gui.update_idletaks() #get true values
self.gui.after_idle(lambda : self.gui.attributes('-alpha', 1)) #makes window visble again

最新更新