PySide2 QWebEngine与Web js交互
python使用PySide2与Web js进行交互
Qt与js单向交互
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序列化才可以传递。
添加QWebEngineView控件,必须在主线程。
Qt与js双向传值
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
from PySide2.QtCore import QObject, Signal, Slot, Property, QUrl
from PySide2.QtWidgets import QWidget, QDesktopWidget, QVBoxLayout, QPushButton, QApplication
from PySide2.QtGui import QIcon
# 定义一个类,继承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 MyPage(QWebEnginePage):
def javaScriptConsoleMessage(self, level, message:str, lineNumber:int, sourceID:str):
print("Qt js console:", message)
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()
self.web_view.setPage(MyPage(self.web_view))
vb.addWidget(self.web_view)
# 创建共享对象
self.lauf = Lauf()
# 创建通道
self.web_channel = QWebChannel(self.web_view)
# 页面设置通道
self.web_view.page().setWebChannel(self.web_channel)
self.web_channel.registerObject("lauf", self.lauf)
# 加载页面
self.web_view.page().load(QUrl("http://127.0.0.1:5500/index.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_())

Qt与typescript双向传值
-
前端 react + typescript
-
Qt 端使用PySide2
实现web ts 与 Qt 之间的双向传值
这里借助WebSocketServer,ts中创建socket,连接QT中开启的socket server。
代码实现找博主要,关注+收藏 -
typescript中不能直接使用qwebchannel.js,需要编写头文件,所以在react + typescript的项目中做如下配置。
-
正常安装,npm install -s qwebchannel
-
配置ts头文件,在项目的根目录下创建一个types目录,添加一个qwebchannel.d.ts文件
-
配置tsconfig.ts的编译项,include中添加"./types"
-
// qwebchannel.d.ts
declare module "qwebchannel"{
const content:any;
export content
}
最后就可以在ts项目中引用:
import qwebchannel from 'qwebchannel'
- 具体逻辑
- web 端创建socket 客户端,向socket server发起连接请求;
- Qt端创建一个socket server,并包裹socket连接为transport传输层;可以放入子线程,但不能被垃圾回收。
- 包裹层将transport 传给QWebChannel.connectTo函数;
- Qt 创建共享对象(继承QObject),并设置对应的Slot、Property装饰的函数,共享对象注册到QWebChannel中。
- 共享对象通过transport 传给web 客户端,实现共享。
更多推荐




所有评论(0)