【发布时间】:2020-06-28 15:46:26
【问题描述】:
我正在尝试将 Tk 子类化,它会暂停音频当且仅当整个应用程序失去焦点(即 Tk 实例失去焦点并且焦点没有传递给 @ 987654324@ 或 messagebox 小部件)。
我设法让它与'hack'一起工作 - 当messagebox 打开时,它是Tk 实例的最后一个孩子,也没有孩子。这是我尝试过的:
class TkWin(Tk):
def __init__(self, title):
super().__init__(className=title, baseName=title)
self.bind('<FocusOut>', lambda event: self.pause_audio())
def pause_audio(self):
if self.has_focus():
return
else:
pass
# pause the audio
def has_focus(self):
children = self.winfo_children()
if any(isinstance(x, Toplevel) for x in children):
return True
if len(children[-1].winfo_children()) == 0:
return True
return False
win = TkWin('test')
win.mainloop()
上述解决方案解决了在打开Toplevel 或messagebox 时不暂停音频的问题。但是,如果打开 Toplevel 或 messagebox 小部件并且 然后另一个窗口获得焦点,它会失败。
(我知道如果您打开 messagebox 会失败然后创建了一个包含一些小部件的容器,但它适用于我构建应用程序的方式)
有没有更好的方法来解决这个问题?
尝试@Atlas345 的解决方案,在尝试打开messagebox 时遇到此错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/usr/lib/python3.6/tkinter/__init__.py", line 749, in callit
func(*args)
File "/home/inkblot/Desktop/win test.py", line 12, in check
if self.focus_get() is None:
File "/usr/lib/python3.6/tkinter/__init__.py", line 699, in focus_get
return self._nametowidget(name)
File "/usr/lib/python3.6/tkinter/__init__.py", line 1353, in nametowidget
w = w.children[n]
KeyError: '__tk__messagebox'
编辑:
尝试覆盖 focus_get 方法让我有所收获,但我还有最后一个问题:
from tkinter import messagebox, Tk, Button, Label, Toplevel
class TkWin(Tk):
def __init__(self, title):
super().__init__(className=title, baseName=title)
self.focus_id = self.after(10, self.has_focus)
def focus_get(self):
try:
return super().focus_get() is not None
except KeyError:
print('messagebox is open')
return True
def has_focus(self):
print('resume audio') if self.focus_get() else print('pause audio')
self.focus_id = self.after(50, self.has_focus)
def popupmsg(msg):
popup = Toplevel(win)
popup.wm_title("Warning!")
Label(popup, text=msg).pack(side="top", fill='both', expand=True)
Button(popup, text="okay", command = popup.destroy).pack()
win = TkWin('test')
Button(win, text='top', command=lambda: Toplevel(win)).pack()
Button(win, text='msg', command=lambda: messagebox.showinfo('title', 'msg')).pack()
Button(win, text='popup', command= lambda: popupmsg('I dare you!')).pack()
win.mainloop()
这让上述错误静默失败,但我现在注意到如果 topmost 小部件没有焦点,focus_get() 方法会返回 None。这意味着,如果打开了任何类型的弹出窗口,然后单击根窗口(或不是最近创建的任何弹出窗口),它会假定整个应用程序没有焦点,因此暂停音频,这不应该说最少。
【问题讨论】:
-
@Atlas435 感谢您的链接,但如果可能,我想避免使用任何非标准软件包。