Skip to content

Commit

Permalink
完善托盘/后台运行机制
Browse files Browse the repository at this point in the history
  • Loading branch information
hiroi-sora committed Sep 26, 2022
1 parent b44af20 commit 1c278b8
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 29 deletions.
39 changes: 29 additions & 10 deletions ui/tray.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
from logging import raiseExceptions
from ui.systray.traybar import SysTrayIcon
from utils.asset import Asset
from utils.config import Config
from utils.config import Config, ClickTrayModeFlag

import atexit # 退出处理


class Tray:

def __init__(self):
menuOptions = (
('屏幕截图', Asset.getPath('screenshot24ico'), self.screenshot),
('粘贴图片', Asset.getPath('paste24ico'), self.clipboard),
("显示界面", Asset.getPath('app24ico'), self.showWin),
)
self.tray = None

def start(self):
aa = ('显示面板', Asset.getPath('app24ico'), self.showWin)
bb = ('屏幕截图', Asset.getPath('screenshot24ico'), self.screenshot)
cc = ('粘贴图片', Asset.getPath('paste24ico'), self.clipboard)
clickTrayMode = Config.get('clickTrayMode').get(
Config.get('clickTrayModeName'), ClickTrayModeFlag.show)
print(f'clickTrayMode: {clickTrayMode}')
menuOptions = ()
if clickTrayMode == ClickTrayModeFlag.show:
menuOptions = (aa, bb, cc)
elif clickTrayMode == ClickTrayModeFlag.screenshot:
menuOptions = (bb, cc, aa)
elif clickTrayMode == ClickTrayModeFlag.clipboard:
menuOptions = (cc, bb, aa)
self.tray = SysTrayIcon(
Asset.getPath('umiocr24ico'),
'Umi-OCR', menuOptions,
quit_name='退出',
quit_icon=Asset.getPath('exit24ico'),
on_quit=self.quit)

def start(self):
self.tray.start()
atexit.register(self.stop) # 注册程序终止时执行强制停止子进程
self.main = Config.main
# 注册事件,防止跨线程调用方法
# self.main.win.bind(
# '<<QuitEvent>>', lambda *e: self.main.onClose())
self.main.win.bind(
'<<QuitEvent>>', lambda *e: self.main.onClose())
'<<QuitEvent>>', lambda *e: self.main.exit())
self.main.win.bind(
'<<ClipboardEvent>>', lambda *e: self.main.runClipboard())
# <<ScreenshotEvent>> 在主窗类内已注册
Expand All @@ -32,7 +47,10 @@ def stop(self):
'''关闭托盘显示的接口。必须在主线程调用,禁止在托盘线程内调用!'''
# https://github.com/Infinidat/infi.systray/issues/26
# https://github.com/Infinidat/infi.systray/issues/32
if not self.tray:
return
self.tray.shutdown()
self.tray = None # 将引用置空,主窗口第二次按下关闭时可强行关闭

def showWin(self, e=None):
self.main.gotoTop()
Expand All @@ -44,7 +62,8 @@ def clipboard(self, e=None):
self.main.win.event_generate('<<ClipboardEvent>>')

def quit(self, e=None):
self.main.win.event_generate('<<QuitEvent>>')
if self.main.win:
self.main.win.event_generate('<<QuitEvent>>')


SysTray = Tray() # 托盘单例
60 changes: 41 additions & 19 deletions ui/win_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,22 @@ def initSoftwareFrame(): # 软件行为设置
ipady=2, pady=LabelFramePadY, padx=4)
fr1 = tk.Frame(fSoft)
fr1.pack(side='top', fill='x', pady=2, padx=5)
wid = ttk.Checkbutton(fr1, text="调试模式",
variable=Config.getTK('isDebug'))
wid.grid(column=0, row=0, sticky="w")
fr1.grid_columnconfigure(1, weight=1)
self.balloon.bind(fr1, '下次打开软件生效')
wid = ttk.Checkbutton(fr1, text='显示系统托盘图标',
variable=Config.getTK('isTray'))
wid.grid(column=0, row=0, sticky='w')
Widget.comboboxFrame(fr1, ',双击图标', 'clickTrayMode').grid(
column=1, row=0, sticky='w')

fr2 = tk.Frame(fSoft)
fr2.pack(side='top', fill='x', pady=2, padx=5)
self.balloon.bind(fr2, '显示系统托盘图标期间才生效')
tk.Label(fr2, text='  关闭主面板:').pack(side='left')
ttk.Radiobutton(fr2, text='最小化到托盘',
variable=Config.getTK('isBackground'), value=True).pack(side='left')
ttk.Radiobutton(fr2, text='退出软件',
variable=Config.getTK('isBackground'), value=False).pack(side='left', padx=15)
self.lockWidget.append(wid)
initSoftwareFrame()

Expand All @@ -260,8 +273,7 @@ def quickOCR(): # 快捷识图设置
# 避免子线程直接唤起截图窗导致的窗口闪烁现象
self.win.bind('<<ScreenshotEvent>>',
self.openScreenshot) # 绑定截图事件
cbox = Widget.comboboxFrame(
fQuick, '截图模式: ', 'scsMode', self.lockWidget)
cbox = Widget.comboboxFrame(fQuick, '截图模式: ', 'scsMode')
cbox.pack(side='top', fill='x', padx=4)
frss = tk.Frame(fQuick)
frss.pack(side='top', fill='x')
Expand Down Expand Up @@ -541,6 +553,9 @@ def initAbout(): # 关于面板
labelWeb.pack() # 文字
labelWeb.bind( # 绑定鼠标左键点击,打开网页
'<Button-1>', lambda *e: webOpen(Umi.website))
wid = ttk.Checkbutton(self.optFrame, text='调试模式',
variable=Config.getTK('isDebug'))
wid.pack(side='right')
initAbout()

def initOptFrameWH(): # 初始化框架的宽高
Expand All @@ -560,10 +575,13 @@ def onCanvasMouseWheel(event): # 绑定画布中滚轮滚动事件
1 if event.delta < 0 else -1, "units")
self.optCanvas.bind_all("<MouseWheel>", onCanvasMouseWheel)
initOptFrameWH()

initTab3()

SysTray.start() # 启动托盘
self.win.protocol('WM_DELETE_WINDOW', self.onCloseWin)
if Config.get('isTray'):
SysTray.start() # 启动托盘
self.win.wm_protocol( # 注册窗口关闭事件
'WM_DELETE_WINDOW', self.onCloseWin)
self.gotoTop()
self.win.mainloop()

Expand Down Expand Up @@ -862,24 +880,28 @@ def closeScreenshot(self, flag, errMsg=None): # 关闭截图窗口,返回T表

def onCloseWin(self): # 关闭窗口事件
print('onCloseWin!')
# TODO : 判断
self.win.withdraw() # 隐藏窗口
if Config.get('isBackground'):
self.win.withdraw() # 隐藏窗口
else:
self.onClose() # 直接关闭

def onClose(self): # 关闭窗口事件
def onClose(self): # 关闭软件
OCRe.stop() # 强制关闭引擎进程,加快子线程结束
if OCRe.engFlag == EngFlag.none and OCRe.msnFlag == MsnFlag.none: # 未在运行
self.win.destroy() # 直接关闭
self.exit()
else:
self.win.after(50, self.waitClose) # 等待关闭,50ms轮询一次是否已结束子线程

def waitClose(self): # 等待线程关闭后销毁窗口
Log.info(f'关闭中,等待 {OCRe.engFlag} | {OCRe.msnFlag}')
if OCRe.engFlag == EngFlag.none and OCRe.msnFlag == MsnFlag.none: # 未在运行
self.win.destroy() # 销毁窗口
Log.info(f'主窗 exit =====================')
exit(0)
else:
self.win.after(50, self.waitClose) # 等待关闭,50ms轮询一次是否已结束子进程
def onClose(self): # 关闭软件
if SysTray.tray: # 开启了托盘
SysTray.stop() # 通过托盘线程关闭软件
else: # 无托盘,直接关
self.exit()

def exit(self):
# 等待一段时间,保证托盘线程关闭,图标从系统注销
# 然后强制终止主进程,防止引擎子线程苟且偷生
self.win.after(100, lambda: os._exit(0))

def showTips(self, tipsText): # 显示提示
if not OCRe.msnFlag == MsnFlag.none:
Expand Down
31 changes: 31 additions & 0 deletions utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ class ScsModeFlag(Enum):
system = 1 # 系统截屏模式


class ClickTrayModeFlag(Enum):
'''点击托盘时模式标志'''
show = 0 # 显示主面板
screenshot = 1 # 截屏
clipboard = 2 # 粘贴图片


# 配置文件路径
ConfigJsonFile = 'Umi-OCR_config.json'

Expand All @@ -37,6 +44,30 @@ class ScsModeFlag(Enum):
'isSave': True,
'isTK': True,
},
'isTray': { # T时展示托盘图标
'default': True,
'isSave': True,
'isTK': True,
},
'isBackground': { # T时点关闭进入后台运行
'default': False,
'isSave': True,
'isTK': True,
},
'clickTrayModeName': { # 当前选择的点击托盘图标模式名称
'default': '',
'isSave': True,
'isTK': True,
},
'clickTrayMode': { # 点击托盘图标模式
'default': {
'显示面板': ClickTrayModeFlag.show,
'屏幕截图': ClickTrayModeFlag.screenshot,
'粘贴图片': ClickTrayModeFlag.clipboard,
},
'isSave': False,
'isTK': False,
},
# 快捷识图设置
'isHotkeyClipboard': { # T时启用读剪贴板快捷键
'default': False,
Expand Down

0 comments on commit 1c278b8

Please sign in to comment.