Tkinter:尝试点击时窗口闪烁

时间:2015-02-16 12:23:32

标签: python tkinter

我一直试图这样做一段时间,但是没有想出办法。

我有一个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模块创建的窗口,如果您尝试单击另一个窗口,则该文件对话窗口将保持在顶部并且具有“闪烁”状态。动画让用户知道他们无法点击。有没有办法可以重现这种效果?通过文件对话的来源对我来说并不富有成效,也没有谷歌搜索。

2 个答案:

答案 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()