[Python-checkins] bpo-42685: Improve placing of simple query windows. (GH-23856)

serhiy-storchaka webhook-mailer at python.org
Thu Dec 24 13:26:37 EST 2020


https://github.com/python/cpython/commit/c6c43b28746b0642cc3c49dd8138b896bed3028f
commit: c6c43b28746b0642cc3c49dd8138b896bed3028f
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: serhiy-storchaka <storchaka at gmail.com>
date: 2020-12-24T20:26:28+02:00
summary:

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.

files:
A Misc/NEWS.d/next/Library/2020-12-19-17-32-43.bpo-42685.kwZlwp.rst
M Lib/tkinter/simpledialog.py

diff --git a/Lib/tkinter/simpledialog.py b/Lib/tkinter/simpledialog.py
index b882d47c961bd..638da87c8765d 100644
--- a/Lib/tkinter/simpledialog.py
+++ b/Lib/tkinter/simpledialog.py
@@ -55,36 +55,8 @@ def __init__(self, master,
                 b.config(relief=RIDGE, borderwidth=8)
             b.pack(side=LEFT, fill=BOTH, expand=1)
         self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window)
-        self._set_transient(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
+        self.root.transient(master)
+        _place_window(self.root, master)
 
     def go(self):
         self.root.wait_visibility()
@@ -157,11 +129,7 @@ def __init__(self, parent, title = None):
 
         self.protocol("WM_DELETE_WINDOW", self.cancel)
 
-        if parent is not None:
-            self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
-                                      parent.winfo_rooty()+50))
-
-        self.deiconify() # become visible now
+        _place_window(self, parent)
 
         self.initial_focus.focus_set()
 
@@ -251,6 +219,37 @@ def apply(self):
         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
 
diff --git a/Misc/NEWS.d/next/Library/2020-12-19-17-32-43.bpo-42685.kwZlwp.rst b/Misc/NEWS.d/next/Library/2020-12-19-17-32-43.bpo-42685.kwZlwp.rst
new file mode 100644
index 0000000000000..068546a34c57a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-12-19-17-32-43.bpo-42685.kwZlwp.rst
@@ -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.



More information about the Python-checkins mailing list