解决方案2
完全避免跨线程调用. 思路是在tk窗口线程中轮询某个信号量, 当出现指定的信号执行相应的动作. 代码如下:def _loop_query(root:tk.Tk, callback:callable):
'''tk线程内轮询'''
callback() # 调用回调函数
root.after(300, lambda: _loop_query(root, callback))
def Alarm(msg:str='提醒!',showTime:float=None):
'''提醒用户, 计划采用的方式是弹出提醒窗口; msg为可选提醒信息
showTime: 显示时间, 单位秒, 超过显示时间自动销毁
'23090801_AlarmClose': 关闭消息, 当收到此消息时关闭窗口
'''
start_time = time.time() # 窗口创建时间
def _check_close():
'''检查是否收到关闭通知, 收到后关闭窗口'''
notice = message.get_notice('23090901_CloseAlarm')
if notice!=None and notice.time>start_time:
root.destroy() # 销毁窗口
root = tk.Tk()
root.title('提醒框')
root.geometry("200x100+20+20")
tk.Label(root, text=msg).pack(side=tk.TOP,anchor=tk.W)
root.wm_attributes("-topmost", 1)
if showTime!=None: root.after(int(showTime*1000), lambda: root.destroy()) # 自动销毁窗口
_loop_query(root, _check_close) # 循环检查, 需要时关闭窗口
root.mainloop()
经过实践验证, 完美解决了我的问题.
测试代码如下:import TkExt
import time
import message
import Common
from TkExt import *
@Common.run_in_thread
def test_func():
Alarm('hzq test.')
print('hzq test2.')
test_func()
time.sleep(30)
message.pub_notice('23090901_CloseAlarm')
time.sleep(1000)