文章目录
- 单向交互
- 双向传值
- 案例
单向交互
QWebEngineView加载web页面,web页面中点击按钮,执行js代码,js的返回值传给QWebEnginePage,使用python进行保存结果。
单向,js向python(PySide2)端传输数据。
- 前端实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
<title>单向传值</title>
</head>
<body>
<button id="btn" onclick="jsFunc()">测试单向传值</button>
<script type="text/javascript">
function jsFunc(){
let data1 = 20;
let data2 = "js transport value to python"
let data3 = {
origin: "javascript",
target: "python"
}
// js将数据打印出来
console.log("js打印:", data1) // 打印出来
console.log("js打印:", data2)
console.log("js打印:", data3)
}
</script>
</body>
</html>
使用Live Server启动服务器,加载html页面。
VS code 中安装Live server 插件;
alt+l; alt+o 启动;或者右键-Open With Live Server
2. PySide2 Qt端实现
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWebEngineWidgets import QWebEnginePage, QWebEngineView, QWebEngineProfile
# 自定义页面类
class MyWebEnginePage(QWebEnginePage):
def javaScriptConsoleMessage(self, level:QWebEnginePage.JavaScriptConsoleMessageLevel,
message:str, lineNumber:int, sourceID:str):
# 接收js控制台 打印的信息
print("接收js数据:", message)
# 保存的动作
return super(MyWebEnginePage, self).javaScriptConsoleMessage(level, message, lineNumber, sourceID)
# 自定义web引擎类
class MyWebEngineView(QWebEngineView):
def __init__(self):
QWebEngineView.__init__(self)
self.setPage(MyWebEnginePage(self))
class MyWindow(QWidget):
def __init__(self, title="laufing"):
super(MyWindow, self).__init__()
# 窗口的尺寸及居中
self.resize(800, 600)
desk = QDesktopWidget().geometry()
width, height = desk.width(), desk.height()
self.move(width//2 - self.width()//2, height//2 - self.height()//2)
# 窗口标题
self.setWindowTitle(title)
self.setWindowIcon(QIcon("./imgs/dog.jpg"))
#
self.set_ui()
def set_ui(self):
vb = QVBoxLayout(self)
self.web_view = MyWebEngineView()
vb.addWidget(self.web_view)
# 加载页面
self.web_view.page().load(QUrl("http://127.0.0.1:5500/testWeb/test.html"))
if __name__ == '__main__':
import sys
# 创建应用程序
app = QApplication(sys.argv)
win = MyWindow("测试可视化")
win.show()
# 进入消息循环
sys.exit(app.exec_())
只能单向传递数值、字符串,对象必须json序列化才可以传递。
双向传值
Qt 与javascript 双向传值,需要借助qwebchannel.js 工具。
- 前端index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
<title>Document</title>
</head>
<body>
<button id="btn" onclick="jsFunc()">向python传值</button>
<button onclick="getValue()">获取python值</button>
<!-- 加载qwebchannel.js -->
<script src="qwebchannel.js"></script>
<script type="text/javascript">
// 页面加载完成,执行函数
window.addEventListener("DOMContentLoaded", function(){
// 创建Webchannel,与 Qt 端建立连接
// qt.webChannelTransport 不用管,自动传过来
new QWebChannel(qt.webChannelTransport, function(channel) {
// 通过channel 获取Qt端的对象
window.pyObj = channel.objects.lauf;
// Qt对象的note信号 连接到js的函数
window.pyObj.note.connect(function(arg){
alert("qt信号触发js函数: ", arg);
});
});
})
function jsFunc(){
let data = {
name: "lauf",
age: 28
}
// js 调用 qt 端的函数,并传入参数(json序列化的数据)
window.pyObj.py_func(JSON.stringify(data))
}
function getValue(){
// js调用qt对象的属性,获取数据
let data = window.pyObj.name;
alert("获取的python数据:", data)
}
</script>
</body>
</html>
目录结构:
以Liver Server服务器启动,Qt端加载test.html页面。
2. PySide2 Qt端
from PySide2.QtWebEngineWidgets import QWebEnginePage, QWebEngineView, QWebEngineProfile
from PySide2.QtWebChannel import QWebChannel
# 定义一个类,继承QObject, 创建共享(Qt & js)的对象
class Lauf(QObject): # 必须继承QObject
# 信号
note = Signal(str)
_name = "pypy"
# 定义方法
@Slot(str, result=str) # 必须装饰为槽函数 说明传值类型
def py_func(self, data: str):
print("py func run:", data)
# 定义属性
@Property(str) # 必须装饰Property
def name(self, *args):
return self._name
class MyWindow(QWidget):
def __init__(self, title="laufing"):
super(MyWindow, self).__init__()
# 窗口的尺寸及居中
self.resize(800, 600)
desk = QDesktopWidget().geometry()
width, height = desk.width(), desk.height()
self.move(width//2 - self.width()//2, height//2 - self.height()//2)
# 窗口标题
self.setWindowTitle(title)
self.setWindowIcon(QIcon("./imgs/dog.jpg"))
#
self.set_ui()
def set_ui(self):
vb = QVBoxLayout(self)
self.btn = QPushButton("点击")
self.btn.clicked.connect(self.do_click)
vb.addWidget(self.btn)
self.web_view = QWebEngineView()
vb.addWidget(self.web_view)
# 创建共享对象
self.lauf = Lauf()
# 创建通道
self.web_channel = QWebChannel()
self.web_channel.registerObject("lauf", self.lauf)
# 页面设置通道
self.web_view.page().setWebChannel(self.web_channel)
# 加载页面
self.web_view.page().load(QUrl("http://127.0.0.1:5500/testWeb/test.html"))
def do_click(self, *args):
self.lauf.note.emit("qt端点击")
if __name__ == '__main__':
import sys
# 创建应用程序
app = QApplication(sys.argv)
win = MyWindow("测试可视化")
win.show()
# 进入消息循环
sys.exit(app.exec_())
案例
- 前端 react + typescript
- Qt 端使用PySide2
实现web js 与 Qt 之间的双向传值