一般稍微复杂的软件都有帮助文档,用来引导用户慢慢熟悉软件功能,介绍软件的使用细节,今天我也想在分析软件中添加这个功能,实现帮助文档功能其实有几种方式,一种是只实现一个超链接功能,然后把文档做在线上网站上,一种是离线的文档,直接在软件中打开,今天主要是实现离线文档的方式,因为这种方式涉及到的技术点更多,那种在线的其实跟桌面开发就没什么关系了。
第一步,技术路线,一般这种帮助文档都是有图和文本的,如果只是单纯的文本,就好办很多,最简单的用一个text框就能实现了,但是有图有文这种富文本的我觉得html是比较合适的,所以我这里采用是用pyqt5呈现html的方式实现。
第二步,技术路线确定后,那么就开始查找相关资料看pyqt5中怎么显示html,这块我之前接触过一些,但是是很多年前了,那时候pyqt中有个叫webkit的东西,它是苹果开源的一个浏览器组件,后来被qt项目集成了,对应的python绑定为qtwebkit,但是因为年代太久远了,最新的百度显示这个组件已经逐渐被废弃了,qt又集成一个新的浏览器组件,叫pyqtwebengine,于是我就开始研究这个组件,但是第一步安装就出问题了,不知道是我环境的问题还是怎么,不是缺这个就是缺那个,经过一番折腾,终于确定要安装的包,我这里是
pyqtwebengine-qt5==5.15.2
pyqtwebengine==5.15.6
开始我以为这两个包是一个东西,装一个就行,在网上看一般只装其中的一个,装下面的那个居多,但是在我这,单独装哪个都报错,所以我测试的结果是两个都装。
第三步,依赖装好后,就可以调代码了,其实要想显示个html还是比较简单的,下面是一个示例:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.web_view = QWebEngineView()
self.setCentralWidget(self.web_view)
def load_html(self, html_content):
self.web_view.setHtml(html_content)
def main():
app = QApplication(sys.argv)
window = MainWindow()
html_content = """
<html>
<head><title>PyQt5 HTML Page</title></head>
<body><h1>Hello, HTML!</h1></body>
</html>
"""
window.load_html(html_content)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
这个是文心一言给的一段代码(可以直接运行),演示了怎么是用pyqt显示html,主要逻辑就是创建一个webEngineView,然后调用setHtml方法就可以显示html页面了,但是我们一般不会用这种方式,我们最常用的方式还是传一个url,然后加载页面,这里有两种情况,一种是普通的http/https这种的url,这个没什么好说的,很简单,也没什么太多需要注意的问题,下面是一段加载在线网页的代码:
import sys
from PyQt5.Qt import *
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.web_view = QWebEngineView()
self.setCentralWidget(self.web_view)
def load_html(self, url):
self.web_view.load(QUrl(url))
def main():
app = QApplication(sys.argv)
window = MainWindow()
url = "https://www.baidu.com"
window.load_html(url)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
然后重点说下加载本地网页的代码,当然逻辑其实不复杂,主要注意一点是url的处理,第一点如果加载本地网页,路径必须用绝对路径,什么是绝对路径,就是从盘符开始的那种路径,而不能用相对路径,第二点,必须调用QUrl.fromLocalFile方法处理,否则会报错,示例代码如下
import sys
from PyQt5.Qt import *
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.web_view = QWebEngineView()
self.setCentralWidget(self.web_view)
def load_html(self, url):
self.web_view.load(QUrl.fromLocalFile(url))
def main():
app = QApplication(sys.argv)
window = MainWindow()
url = "https://www.baidu.com"
local_url = r"E:\Projects\Webapp\11.html"
window.load_html(local_url)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
和上面代码的主要区别就是url这块的处理。
好的,最简单的显示网页的功能其实就已经实现了,然后说下这个文档的处理,我这里原始的帮助文档是一个word格式的,但是我需要的是html格式的,怎么办,这个其实很好办,只要用word另存一份html版本的就可以了,但是存的的时候要注意,word里支持很多中html格式,比如单个网页(mhtml),网页(htm,html),筛选过的网页(htm,html),经过我的测试,这里需要选择筛选过的网页,其它两种我试过本地打开后都没有图片,不知道怎么回事,也没去细究,好在有个能用的,文档转好以后(转换后包含两个文件一个htm,一个资源文件就是图片什么的,都要拷贝到项目目录)就可以拷贝到项目目录了。
至此,其实功能部分已经实现了,本以为可以开开心心打包发布的时候,打包又出问题了,报错截图
开始我以为是pyinstaller的问题,有些资源没打包进来,但是我一搜,其实这个文件已经被打包进来了,那为什么还报找不到呢,于是就开始百度,搜到一篇博文说是要把一些文件拷贝到项目根目录,参考知乎使用pyinstaller打包pyside2程序时出现找不到qtwebengineprocess.exe问题的解决方案 - 知乎 (zhihu.com)
按照博文操作一番后,别说,确实管用了,至少进程不退出了,但是也没有太完美,还有一些警告说找不到资源什么的,于是我在想有没有更好的解决方案,就又开始一通百度,终于找到另一个说法Qt5 问题:Could not find QtWebEngineProcess.exe-CSDN博客,第一个注意事项,编译目录有没有中文,这个不用检查,因为我这个项目一直是在含有中文路径下打包的,一直没出过问题,直到今天,于是我换了一个路径,结果直接就好了,也不用拷贝那些exe还有conf到项目根目录了,就是中文路径的问题,qt直接懵逼了,给我也整懵逼了,难受。为了不再因为中文路径出问题,我永久的更换了项目目录。
总结,原本一个以为很简单的功能,做了一天,各种坑啊,所以编程这东西就跟拆盲盒一样,你永远不知道迎接你的是什么东西。