具体实现
整个工程文件已经上传到我的代码仓库。
正式开始
项目结构
数据存储
因为本系统为自用而非商用,并且偏向功能性,所以直接用一个config.json文件保存所有的用户数据,就不用加密了。
原型设计
如图,本系统一共包含两个用户页面,由主页和设置页构成(设置页内置三个分页)。全部都是简单的控件,包括:文本框、按钮、输入框、单选按钮、纯文字。
UI设计
懒得找icon文件的小伙伴建议直接用的我的ui文件。对布局不熟悉的小伙伴建议直接用绝对布局(就是直接把控件拖到你想要的位置)。下面是用qt designer进行布局设计的主要流程:
1、将控件拖动到预设位置
2、为控件命名
3、调整控件大小
4、加载图标(记得把文字删掉)
图标文件需要自己事先保存,可以白嫖阿里云的。
模块设计
在前篇测试时我们其实已经将大部分功能做出来了,但是为了组合成一个自恰的系统,需要将功能抽象,做成模块。下面是一个简化的UML组件图,实线表示 模块A→提供服务给→模块B,虚线表示 模块A→依赖于→模块B。
识别+翻译模块
因为识别和翻译模块在提供功能的地位上极其相似,所以这里放在一起讲。回到我们的用户操作面板,找出所有本模块相关功能控件:
发现本模块一共要提供5个接口:
- API参数设置(初始化)
包括识别语言、翻译语言、api参数等等数据的初始化和修改。
# OCR.py OffOCR.py Tran.py OffTran.py
def initOptions(self, config): # 按照config进行设置
- 开始识别+翻译
因为识别和翻译过程是一键完成的,所以需要组合识别图片和翻译文字的接口。
# OCR.py OffOCR.py
def ocrPath(self, path): # 识别path地址的图片
# Tran.py OffTran.py
def trans(self, content): # 翻译content的文字
- 修改识别语言
注意:识别语言更改了,翻译源语言一样要改。
# OCR.py OffOCR.py
def changeSource(self, lan_key): # lan_key为键,隐含了键值映射
- 修改目标翻译语言
这个只用修改翻译目标语言。
# Tran.py OffTran.py
def initTran(self, config): # 按照config进行设置
- 是否启用离线模式
因为离线和在线模式调用的接口类不同,所以这个过程实际是由控制器控制的。
但是我们发现“修改识别语言”和“修改目标翻译语言”,其实本质上也是在修改参数,所以最终抽象成三个接口:
因为源代码量大,所以这里只列出函数名,详见我的代码仓库,/api下的py文件 和 run.py文件。
另外设计上(识别+翻译)模块只控制一次识图翻译过程,所以很多被认为是这个模块的功能其实并没有出现在上面。
划取选区模块
前篇测试中我们已经做出了一个简单的定位模块,它的功能非常简单:提供截图区域的坐标。但是之前的模块还存在两个主要问题:
1、可绘制矩形区域不是全屏,我们不能选取屏幕上任意的区域;
2、矩形区域内并不是透明的,即使我们截取了区域图像,也只是白茫茫一片。
好在qt中为我提供了简单的函数用以解决:
# 取消原生标题栏 | 窗口置顶 | 取消任务栏self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)# 窗口全屏self.showFullScreen()# 设置透明度self.setWindowOpacity(0.3)
详见我的代码仓库,SelectArea.py文件
选区控制模块
这个模块是我花时间最多的地方,因为国内的中文qt教程很少,也没有实现(虚线边框+透明背景)窗口的例子。不过qt存在和css类似的qss,所以在我的不懈摸索下最终实现了如下效果(加上划取选区的演示):
除了视图层外,改模块还聚合了识别和翻译的功能,为控制器提供了识别并翻译选区的接口:
详见我的代码仓库,ControlArea.py文件
主要功能模块/内部设置模块
做到这里我们会发现,上面的模块已经达到了最初的需求了,我们最后仅仅需要一个显示翻译结果的面板和几个调用上面功能的按钮。
这两个模块能说的点非常少,基本几个按钮控件对应一个函数、对应一个功能。就不过多赘述了,看代码应该看得懂。
详见我的代码仓库,MainWindow.py文件和Setting.py文件