是否可以将 tkinter.simpledialog window 居中?
Is it possible to center a tkinter.simpledialog window?
我在一个更大的脚本中包含了条件密码捕获。代码如下所示:
if thing: # found token, don't need password
do stuff
else: # no token, get password in popup
try:
import tkinter as tk
import tkinter.simpledialog
tk.Tk().withdraw()
passwd = tkinter.simpledialog.askstring("Password", "Enter password:", show="*")
return passwd
功能上没问题,但我的大多数用户都在 3840x1600 分辨率的显示器上,所以当对话框在左上角弹出时,很容易错过。
是否有一种简单的方法来覆盖简单对话框 class 以告诉它出现在监视器上的某个 X/Y,或者我唯一的选择是构建一个完整的 mainloop()
?
我找不到覆盖任何 classes 以直接修改基础 _QueryString
class 的方法(而且它是私有的,所以我不想使用它,无论如何我可能都找不到简单的方法)。所以我只是写了一个自定义 askstring
函数。该功能是这样的,您需要提供父级和几何图形,它将首先安排一个内部函数(可以是一个适当的外部函数,但它应该没问题)以获取该父级的小部件中的最后一个小部件,并在预定之后时间应该是新对话框,所以它应该得到那个。 (检查以检查该小部件是否派生自 dialog.Dialog
,而 dialog.Dialog
是 _QueryString
继承的)。然后只需更改几何(因为在继承链上有 Toplevel
显然有一个 geometry
方法):
import tkinter as tk
import tkinter.simpledialog as dialog
def askstring(title, prompt, geometry='', **kwargs):
def change_geometry():
if not geometry:
return
widget = kwargs['parent'].winfo_children()[-1]
if isinstance(widget, dialog.Dialog):
widget.geometry(geometry)
if 'parent' in kwargs:
kwargs['parent'].after(10, change_geometry)
return dialog.askstring(title, prompt, **kwargs)
root = tk.Tk()
root.withdraw()
askstring('Title', 'Prompt', geometry='300x200+200+200', parent=root)
有用:
- source code for
tkinter.simpledialog
这就是我用来解决这个问题的方法(也是根据以前的经验)
so when the dialog pops up at the top left it's easy to miss.
如果指定可选参数 parent,对话框将出现在 window 的中间并在内部获得焦点。确保你的 window 是通过 .update_idletasks()
映射的,以获得相应的坐标。您也可以考虑让您的 window 透明而不是撤回。
import tkinter as tk
import tkinter.simpledialog
def ask_pw():
pw = tkinter.simpledialog.askstring("Password",
"Enter password:",
show="*",
parent=root)
root = tk.Tk()
root.geometry('250x250+500+500')
root.update_idletasks()
ask_pw()
#root.withdraw()
root.mainloop()
由于对话框是相对于其父级的位置放置的,因此您可以将其父级居中,即根 window 在您的例子中:
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
# center root window
root.tk.eval(f'tk::PlaceWindow {root._w} center')
root.withdraw()
# set parent=root
passwd = simpledialog.askstring('Password', 'Enter password:', show='*', parent=root)
我在一个更大的脚本中包含了条件密码捕获。代码如下所示:
if thing: # found token, don't need password
do stuff
else: # no token, get password in popup
try:
import tkinter as tk
import tkinter.simpledialog
tk.Tk().withdraw()
passwd = tkinter.simpledialog.askstring("Password", "Enter password:", show="*")
return passwd
功能上没问题,但我的大多数用户都在 3840x1600 分辨率的显示器上,所以当对话框在左上角弹出时,很容易错过。
是否有一种简单的方法来覆盖简单对话框 class 以告诉它出现在监视器上的某个 X/Y,或者我唯一的选择是构建一个完整的 mainloop()
?
我找不到覆盖任何 classes 以直接修改基础 _QueryString
class 的方法(而且它是私有的,所以我不想使用它,无论如何我可能都找不到简单的方法)。所以我只是写了一个自定义 askstring
函数。该功能是这样的,您需要提供父级和几何图形,它将首先安排一个内部函数(可以是一个适当的外部函数,但它应该没问题)以获取该父级的小部件中的最后一个小部件,并在预定之后时间应该是新对话框,所以它应该得到那个。 (检查以检查该小部件是否派生自 dialog.Dialog
,而 dialog.Dialog
是 _QueryString
继承的)。然后只需更改几何(因为在继承链上有 Toplevel
显然有一个 geometry
方法):
import tkinter as tk
import tkinter.simpledialog as dialog
def askstring(title, prompt, geometry='', **kwargs):
def change_geometry():
if not geometry:
return
widget = kwargs['parent'].winfo_children()[-1]
if isinstance(widget, dialog.Dialog):
widget.geometry(geometry)
if 'parent' in kwargs:
kwargs['parent'].after(10, change_geometry)
return dialog.askstring(title, prompt, **kwargs)
root = tk.Tk()
root.withdraw()
askstring('Title', 'Prompt', geometry='300x200+200+200', parent=root)
有用:
- source code for
tkinter.simpledialog
这就是我用来解决这个问题的方法(也是根据以前的经验)
so when the dialog pops up at the top left it's easy to miss.
如果指定可选参数 parent,对话框将出现在 window 的中间并在内部获得焦点。确保你的 window 是通过 .update_idletasks()
映射的,以获得相应的坐标。您也可以考虑让您的 window 透明而不是撤回。
import tkinter as tk
import tkinter.simpledialog
def ask_pw():
pw = tkinter.simpledialog.askstring("Password",
"Enter password:",
show="*",
parent=root)
root = tk.Tk()
root.geometry('250x250+500+500')
root.update_idletasks()
ask_pw()
#root.withdraw()
root.mainloop()
由于对话框是相对于其父级的位置放置的,因此您可以将其父级居中,即根 window 在您的例子中:
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
# center root window
root.tk.eval(f'tk::PlaceWindow {root._w} center')
root.withdraw()
# set parent=root
passwd = simpledialog.askstring('Password', 'Enter password:', show='*', parent=root)