我一直试图这样做一段时间,但是没有想出办法。
我有一个tkinter脚本,在按下按钮时会创建一个弹出窗口。但是,我不希望用户能够从此窗口点击任何以前创建的窗口。我已经使用root.grab_set(),但没有迹象表明用户必须留在该窗口。
class popup(object):
def __init__(self, parent):
self.root=Toplevel(parent)
self.root.grab_set() #prevents the user clicking on the parent window
#But the window doesnt 'flash' when an attempt to click away is made
例如,如果您有一个由filedialogue模块创建的窗口,如果您尝试单击另一个窗口,则该文件对话窗口将保持在顶部并且具有“闪烁”状态。动画让用户知道他们无法点击。有没有办法可以重现这种效果?通过文件对话的来源对我来说并不富有成效,也没有谷歌搜索。
答案 0 :(得分:3)
以下是使用user32
dll中的FlashWindowEx
的Windows解决方案。您需要将FLASHWINFO
对象传递给它。 grab_set
确保弹出窗口保持清晰并禁用主窗口中的任何小部件,使弹出窗口瞬态确保它始终位于主窗口之上。 <Button-1>
事件用于检查鼠标单击,winfo_containing
检查是否单击了弹出窗口以外的其他窗口。然后我将焦点设置回弹出窗口并将焦点闪烁(然后始终是弹出窗口)。
您需要pywin32才能使用此功能。
import Tkinter as tk
from ctypes import *
import win32con
class popup(object):
def __init__(self, parent):
self.parent = parent
self.root=tk.Toplevel(self.parent)
self.root.title("Popup")
self.root.grab_set()
self.root.transient(self.parent)
self.root.bind("<Button-1>", self.flash)
def flash(self, event):
if self.root.winfo_containing(event.x_root, event.y_root)!=self.root:
self.root.focus_set()
number_of_flashes = 5
flash_time = 80
info = FLASHWINFO(0,
windll.user32.GetForegroundWindow(),
win32con.FLASHW_ALL,
number_of_flashes,
flash_time)
info.cbSize = sizeof(info)
windll.user32.FlashWindowEx(byref(info))
class FLASHWINFO(Structure):
_fields_ = [('cbSize', c_uint),
('hwnd', c_uint),
('dwFlags', c_uint),
('uCount', c_uint),
('dwTimeout', c_uint)]
main = tk.Tk()
main.title("Main")
pop = popup(main)
main.mainloop()
就像现在一样,闪光灯仅在单击主窗口的主体时发生,因此单击标题栏只会将焦点返回到弹出窗口而不会闪烁。为了让它在发生这种情况时也可以尝试使用<FocusOut>
事件,但你必须确保它只在焦点传递到主窗口时发生,但它从来没有真正发生过{{1} } 用来。您可能想要弄清楚,但现在它的效果非常好。所以它并不完美,但我希望它有所帮助。
答案 1 :(得分:2)
我能想到的最简单的方法是使用一个事件和焦点命令,以及windows bell
命令:
#!python3
import tkinter as tk
class popup(object):
def __init__(self, parent):
self.root=tk.Toplevel(parent)
self.root.title("Popup")
self.root.bind("<FocusOut>", self.Alarm)
def Alarm(self, event):
self.root.focus_force()
self.root.bell()
main = tk.Tk()
main.title("Main")
pop = popup(main)
main.mainloop()