我们已经完成了基本的编辑器,运行之后的界面如下图所示。
最终的界面则是这样。
一个明显的区别就是:第一幅图中,编辑器工具栏是包含在网页里面的,没有像第二幅图中那样通过wxPython构建的。
除了界面上的明显区别以外,还有一个严重的问题需要解决:编辑器页面在Windows系统上无法正常显示。这是因为 wx.html2.webview 组件在Windows上模拟了IE7浏览器,而我们使用的Quill编辑器并不支持IE7。
一些解决方案
所以如果我们选择一个可以支持IE7的web编辑器组件,Windows系统上应该就可以正常显示了。还有个思路是,通过修改注册表让 webview 组件模拟IE10浏览器,这样看起来也可以。
上面的两种思路似乎能够解决当下的问题,但因为受限于 webview 组件,我们无法直接和网页通信,例如获取编辑器内容这个需求就不能很好满足,为什么需要获取编辑器内容呢?因为这个笔记本应用需要对笔记进行管理,这些笔记在编辑之后当然需要保存下来。
webview确实提供了一些基本的API,例如获取网页源码,并能够产生网页标题变化的事件。我们能够根据这些API来获取编辑器内容,思路很简单:当编辑器编辑的时候,我们会把编辑器的内容同步到网页标题,也就是 title 节点上,这时webview会发出标题变化的事件,我们监听这个事件来获取对应的title内容,也就获取到了编辑器的内容。
但这样做会有问题,一方面是如果编辑器内容里含有代码块的话,代码块里面一般会含有很多空格,例如代码缩进就会产生空格,而根据HTML的规范,标题将自动移除多余的空格,这就会造成代码块格式混乱。另外如果我们要实现原生的编辑器工具栏,必然要涉及到和网页通信,例如点击工具栏的列表按钮,会在网页当前光标的位置生成一个列表项,这就涉及到了Python和JavaScript的通信。
那么是否可以使用向服务器通信的方式呢?应该是可以的,例如开一个本地的HTTP服务器,网页内部就能通过Ajax请求来进行数据交换。这种思路是可以的,但为了从根本上解决这个问题,并且为了简化数据传递开销,我们引入CEFPython来替换掉wxPython提供的webview组件。
引入CEF Python
CEF的全称是 Chromium Embedded Framework,是一个可以将Chromium浏览器嵌入到应用程序里面的框架。cefpython的项目地址是cefpython,它是基于CEF的Python绑定实现。
通过使用CEF Python来替代原生的 wx.html2.webview,浏览器渲染能够保持一致性,就可以达到在不同系统下相同的浏览体验,更为重要的是,CEF Python让Python和JavaScript的通信更加简单了,我们能够在Python代码里面执行JavaScript函数,也可以在JavaScript里面调用Python方法。
CEFPython的用法整体而言比较简单,但也要注意多平台兼容性的问题,接下来我们将使用它来显示编辑器页面。
首先安装 cefpython。
cefpython3
安装好了之后,我们在项目的 views 目录下新建一个 webview.py 文件,用于替代之前使用的 wx.html2.webview 组件。
代码如下:
import
在 _init_cef 方法中,通过 sys.excepthook = cef.ExceptHook 使得当程序出现异常时,CEF的子进程能够正常的退出。接着通过 wx.Platform 判断当前系统并进行专门的处理,保证了兼容性。最后通过 cef.Initialize 方法初始化了CEF框架。
接下来在 _init_browser 方法里面,通过 cef.CreateBrowserSync 方法创建了一个浏览器对象。
最后在 _init_event 方法里面,绑定了CEF正常运行所必须的事件处理方法。cefpython也有自己的事件循环,通过 MessageLoopWork() 方法来启用。
上述的这些代码参考了cefpython的wxPython示例代码,更加详细的用法参考项目主页的文档。
加载编辑器网页
通过cefpython我们实现了一个全平台兼容的浏览器组件,接下来让它来加载编辑器页面。
在前面的 _init_ 方法里面,我们创建了一个 browser 对象,调用它的 LoadUrl 方法即可加载网页,例如:self.browser.LoadUrl('https://www.zhihu.com') 就可以加载知乎首页。
为了简化调用,我们定义一个 load_url 方法,编辑 views / webview.py 文件。
def
接下来编辑 views / text_editor.py 文件,作如下修改。
首先引入刚刚创建的 Webview 组件,移除之前的 wx.html2。(灰色表示删除,绿色表示新增)
接着更新 webview 对象。
可以发现,通过组件化开发,代码变更就比较方便了。
接着运行 main.py 文件,可以看到编辑器网页正常显示。
并且在Windows系统上也能够正常显示出来。
总结
借助 cefpython 可以实现跨平台的web页面渲染体验,于是我们封装了一个 webview 组件,编辑器页面可以正常显示了。
目前编辑器的工具栏是由web页面提供的,我们将在后面的文章中实现原生的编辑器工具栏,其中会涉及到 Quill 编辑器的相关API以及 cefpython 的JavaScript绑定功能。工具栏完成之后,将连接数据库,并逐渐实现笔记本应用的常见功能。