Reputation: 245
I'm trying to define a popup window with a combobox, which does something in the parent window.
It's more or less done (perhaps not the best way...), except that the popup window wouldn't come up in the right place: it would always show in the upper-left corner, even if the main window was elsewhere.
I suppose this behavior is to be expected from Toplevel windows.
Now, in order to make it show centralized with the main window and with the right size, I used geometry
method on the popup window.
But for this to work, I have to apply the update
method, so that the size of the window is known.
That gives me the popup window in the right place and with the correct dimensions.
However, another problem arises: the window shows up, in the upper-left corner, for a fraction of a second, before it shows in the right place.
This is certainly because the call of update
is before the positioning and resizing.
Here's the code.
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()
I tried with the commented methods withdraw
before update
and iconify
or deiconify
after.
With deiconify
the observed behavior is exactly the same;
with iconify
the program blocks.
There must be a better way. Any ideas?
Thanks in advance.
Upvotes: 1
Views: 201
Reputation: 8072
I can't reproduce your problem on my computer. It seems like it depends on system speed. But a solution can be:
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
Upvotes: 1