python做界面我首先想到的是pyqt5,但是笔者之前基本是用wpf做界面,再用其他的做界面都有点不畅快的感觉。直接用到了HTML + CSS + js。随着前端技术的快速发展,如VUE,AUI这类框架的兴起,做个炫酷的页面,远比后端做个界面要快捷方便的多。
但是HTML + CSS + js是运行在浏览器里的,这个系列文章就是要打破python和前端的壁垒,让它们携手打造桌面程序。
那么这个心思路就是,利用pyqt5的QtWebEngineWidgets和QtWebChannel来做媒介,
python完成后台功能,HTML + CSS + js完成全部的界面功能。
界面需要python功能时,js方便的调用python函数并获取返回值。这样各自完成擅长部分,想想都有点小激动呢。
那这样是否靠谱呢?
根据笔者的目前尝试,感觉还是很靠谱的:
1 运行不卡顿,相对于纯的pyqt我感觉这种界面运行起来更流畅。
2 QtWebEngineWidgets移植V8引擎,基本和谷歌的效果是一样的。Vue这样的框架也可以直接引用。
讲QtWebEngineWidgets的文章有很多,我学习这个时候看到网上的很多文章也和受益,但是,基本都是讲的一样的,没有深挖。
首先,QtWebEngineWidgets和QtWebChannel是可以实现双向交互的,但是,在应用的过程中我发现,python调用js会比较简单,有现成的语法可用,而且传输过程中有的数据的类型都不用转换。而且能获取到js的返回值。
而js调用python就复杂一点,传递类型也只能字符串和int(目前我测试的结果是这样),目前网上大多的例子就是基于共享属性这个概念,js是可以调用python函数,但是没法获取到返回值。
但是应用中你就会发现,基本都是js调用python,比如界面中的按钮点击后需要执行数据分析,然后将结果渲染在界面上。那么过程就是js调用py并获取返回值。
铺垫到此结束,接下来介绍js如何调用py,并获取返回值
工程目录结构
""
js调用python并获取返回值.py
""
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebChannel import QWebChannel
from shared import Myshared
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('js py')
self.resize(330, 220)
self.layout = QVBoxLayout()
self.btn_test = QPushButton('test')
# self.btn_test.clicked.connect(self.test)
# 创建一个 QWebEngineView 对象
self.web = QWebEngineView()
file_path = QFileInfo("./test.html").absoluteFilePath()
self.web.load(QUrl(file_path))
# 把QWebView和button加载到layout布局中
self.layout.addWidget(self.web)
self.layout.addWidget(self.btn_test)
self.setLayout(self.layout)
self.channel = QWebChannel()
self.shared = Myshared()
self.set_channel()
def set_channel(self):
# 注册一个共享空间,取名"conn_shared",记住这个名字
# js中会用到
self.channel.registerObject("conn_shared", self.shared)
self.web.page().setWebChannel(self.channel)
def __del__(self):
'''
删除相关对象
'''
self.web.deleteLater()
# 让系统加快释放这部分内存,避免QWebEngineView崩溃
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
app.exit(app.exec_())
from PyQt5.QtWidgets import QWidget, QMessageBox
from PyQt5.QtCore import *
class Myshared(QWidget):
'''
共享类 shared.py
'''
@pyqtSlot(str, result=int)
def test_str_int(self, one_str):
print(one_str)
try:
r = int(one_str)
except Exception:
return -1
return r
@pyqtSlot(int, result=str)
def test_int_str(self, num):
return str(num + 111)
Title{{a}}
var vm = new Vue({
el: '#app',
data:{
a : "js调用py,并获取返回值"
},
created: function () {
},
methods: {
on_test: function () {
// alert("123")
window.connection.test_str_int("3333", function(return_value){
alert(return_value);
});
window.connection.test_int_str(666, function(return_value){
alert(return_value);
});
}
}
})
document.addEventListener("DOMContentLoaded", function () {
new QWebChannel(qt.webChannelTransport, function(channel) {
window.connection = channel.objects.conn_shared;
});
// 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发。
// 这样我们就新建一个QWebChannel对象(针对qwebchannel.js里的)。
// Web页面可以通过channel.objects属性访问所有已发布的对象,这里对象的id是“conn_shared”。
// 我们将其设置成JavaScript的全局变量:window.connection。
});
小结:
1 首先python中需要注册共享空间,js里才能访问到py。
2 js需要去获取channel.objects,他可以访问py中已发布的对象
3 js在调用py时,第二参数是一个回调,回调的参数结束py的返回值。
今天的内容就是这些,喜欢的可以点赞支持,如果点赞较多,关于这个知识点我将继续做一期有趣的内容。谢谢!