bpo-42685: Improve placing of simple query windows. (GH-23856)

* If parent is specified and mapped, the query widget is
  centered at the center of parent. Its position and size
  can be corrected so that it fits in the virtual root window.
* Otherwise it is centered at the center of the screen.
This commit is contained in:
Serhiy Storchaka 2020-12-24 20:26:28 +02:00 committed by GitHub
parent 6ec0adefad
commit c6c43b2874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 35 deletions

View File

@ -55,36 +55,8 @@ class SimpleDialog:
b.config(relief=RIDGE, borderwidth=8) b.config(relief=RIDGE, borderwidth=8)
b.pack(side=LEFT, fill=BOTH, expand=1) b.pack(side=LEFT, fill=BOTH, expand=1)
self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window) self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window)
self._set_transient(master) self.root.transient(master)
_place_window(self.root, master)
def _set_transient(self, master, relx=0.5, rely=0.3):
widget = self.root
widget.withdraw() # Remain invisible while we figure out the geometry
widget.transient(master)
widget.update_idletasks() # Actualize geometry information
if master.winfo_ismapped():
m_width = master.winfo_width()
m_height = master.winfo_height()
m_x = master.winfo_rootx()
m_y = master.winfo_rooty()
else:
m_width = master.winfo_screenwidth()
m_height = master.winfo_screenheight()
m_x = m_y = 0
w_width = widget.winfo_reqwidth()
w_height = widget.winfo_reqheight()
x = m_x + (m_width - w_width) * relx
y = m_y + (m_height - w_height) * rely
if x+w_width > master.winfo_screenwidth():
x = master.winfo_screenwidth() - w_width
elif x < 0:
x = 0
if y+w_height > master.winfo_screenheight():
y = master.winfo_screenheight() - w_height
elif y < 0:
y = 0
widget.geometry("+%d+%d" % (x, y))
widget.deiconify() # Become visible at the desired location
def go(self): def go(self):
self.root.wait_visibility() self.root.wait_visibility()
@ -157,11 +129,7 @@ class Dialog(Toplevel):
self.protocol("WM_DELETE_WINDOW", self.cancel) self.protocol("WM_DELETE_WINDOW", self.cancel)
if parent is not None: _place_window(self, parent)
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
parent.winfo_rooty()+50))
self.deiconify() # become visible now
self.initial_focus.focus_set() self.initial_focus.focus_set()
@ -251,6 +219,37 @@ class Dialog(Toplevel):
pass # override pass # override
# Place a toplevel window at the center of parent or screen
# It is a Python implementation of ::tk::PlaceWindow.
def _place_window(w, parent=None):
w.wm_withdraw() # Remain invisible while we figure out the geometry
w.update_idletasks() # Actualize geometry information
minwidth = w.winfo_reqwidth()
minheight = w.winfo_reqheight()
maxwidth = w.winfo_vrootwidth()
maxheight = w.winfo_vrootheight()
if parent is not None and parent.winfo_ismapped():
x = parent.winfo_rootx() + (parent.winfo_width() - minwidth) // 2
y = parent.winfo_rooty() + (parent.winfo_height() - minheight) // 2
vrootx = w.winfo_vrootx()
vrooty = w.winfo_vrooty()
x = min(x, vrootx + maxwidth - minwidth)
x = max(x, vrootx)
y = min(y, vrooty + maxheight - minheight)
y = max(y, vrooty)
if w._windowingsystem == 'aqua':
# Avoid the native menu bar which sits on top of everything.
y = max(y, 22)
else:
x = (w.winfo_screenwidth() - minwidth) // 2
y = (w.winfo_screenheight() - minheight) // 2
w.wm_maxsize(maxwidth, maxheight)
w.wm_geometry('+%d+%d' % (x, y))
w.wm_deiconify() # Become visible at the desired location
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# convenience dialogues # convenience dialogues

View File

@ -0,0 +1,4 @@
Improved placing of simple query windows in Tkinter (such as
:func:`tkinter.simpledialog.askinteger`). They are now centered at the
center of the parent window if it is specified and shown, otherwise at the
center of the screen.