pyqt QWebEngineView-python和js交互

PyQt下QWebEngine,QWebChannel简单使用。

PyQt下使用QWebEngine,QWebChannel整体流程与C++版类似

参见项目
github
gitee

0. QWebEngineView

直接加载网页,无交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

from PyQt5.QtWidgets import QFrame, QVBoxLayout
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl


class Covid19Charts(QFrame):
def __init__(self, parent=None):
super().__init__(parent)

webView = QWebEngineView(self)
webView.load(QUrl.fromLocalFile("/Covid19Charts/charts.html"))
webView.show()

layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(webView)
self.setLayout(layout)

需要在当前路径放入html和js文件以及Qtqwebchannel.js

1.js调用python

js调用python 需要借助QWebChannel

Covid19Charts类代码改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

from PyQt5.QtWidgets import QFrame, QVBoxLayout
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtCore import QUrl

class Covid19Charts(QFrame):
def __init__(self, parent=None):
super().__init__(parent)

webView = QWebEngineView(self)
webView.load(QUrl.fromLocalFile("/Covid19Charts/charts.html"))
webView.show()

layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(webView)
self.setLayout(layout)

webChannel = QWebChannel(self) #步骤1
self.__webObject = ChartsWebClass(self) #步骤2
webChannel.registerObject("webObject", self.__webObject) #步骤2
webView.page().setWebChannel(webChannel) #步骤1

整体分为两个步骤

  1. 通过QWebEngineView.setWebChannel()设置WebChannel
  2. 通过QWebChannel.registerObject()中注册对象。
    • 该对象需继承自QObject类。
    • QWebChannel.registerObject()第一个参数字符串对应js中的对象名

ChartsWebClass类代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13

from PyQt5.QtCore import QObject, pyqtSlot


class ChartsWebClass(QObject): #注意1

def __init__(self, parent=None):
super().__init__(parent)

@pyqtSlot() #注意3
def pageLoadFinished(self): #注意2
# todo

此处有三个注意事项

  1. ChartsWebClass需继承自QObject
  2. pageLoadFinished()函数名需与js中对应
  3. pageLoadFinished()函数需为槽函数

html/js代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title></title>
<script src="qwebchannel.js"></script>
<script>
new QWebChannel(qt.webChannelTransport,
function (channel) {
var webObject = channel.objects.webObject; //注意1
window.webObject = webObject;
window.webObject.pageLoadFinished(); //注意2
});
</script>
</head>

<body>
<div id="today" style="width: 1600px;height:500px;"></div>
<div id="total" style="width: 1600px;height:500px;"></div>
</body>
</html>

  1. 注意1中channel.objects.webObject中的对象名webObject需与QWebChannel.registerObject()注册名称相同
  2. 注意2中pageLoadFinished()函数名需与ChartsWebClass类中的槽函数名称相同

2.python调用js

1.js调用python类似,也是通过需要借助QWebChannel
Covid19Charts类不变。
ChartsWebClass类代码改为

1
2
3
4
5
6
7
8
9
10

class ChartsWebClass(QObject):
setData = pyqtSignal(str, str, str) #注意1

def __init__(self, parent=None):
super().__init__(parent)

def setDatas(self, datas): #无关代码,外层调用
self.setData.emit(datas[0], datas[1], datas[2]) #注意2

  1. 声明信号setData(), 信号名需与js中对应。
  2. 在合适的时机发射信号。

html/js代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title></title>
<script src="qwebchannel.js"></script>
<script>
var updateData = function (todayData, totalData, updateTime) {
//todo
}

new QWebChannel(qt.webChannelTransport,
function (channel) {
var webObject = channel.objects.webObject; //注意1
window.webObject = webObject;
window.webObject.setData.connect(updateData); //注意2
});
</script>
</head>

<body>
<div id="today" style="width: 1600px;height:500px;"></div>
<div id="total" style="width: 1600px;height:500px;"></div>
</body>
</html>

  1. 注意1中channel.objects.webObject中的对象名webObject需与QWebChannel.registerObject()注册名称相同
  2. 注意2中window.webObject.setData函数名需与ChartsWebClass类中的信号名称相同