要解决python与js的交互问题,可以基于qwebchannel来实现
文章末尾附有简单的demo
1. 准备阶段
由于我的python使用的是Anaconda,内置了pyqt,因此直接引入即可。
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QObject, pyqtSlot, QUrl
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView
在前端部分,引入qwebchannel.js(不想在网上找的话,直接文章末尾的代码自己新建一个文件即可)首先,创建一个QApplication对象app,参数sys.argv是一个序列,具体含义在此不多深究
然后我们创建QWebEngineView对象,相当于内置的浏览器,用于在python中打开web窗口
定义QWebChannel对象,这是通信的频道
为浏览器窗口设置通信频道
load方法用于打开窗口,在QUrl中输入文件路径即可打开本地HTML文件
最后要用show方法让页面显示出来
2. 建立通信
python部分
app =QApplication(sys.argv)
myWeb=QWebEngineView()
myChannel=QWebChannel()
myweb.page().setWebChannel(myChannel)
myWeb.load(QUrl("C:/Users/asus2018/Desktop/test/font-end.html"))
myWeb.show()
通信过程主要是通过函数调用,因此我们还需要在Python中创建一个通信类,并将这个通信类的对象注册到通信频道之中:
class myClass(QObject):
@pyqtSlot()
def testPy2JS(self):
myweb.page().runJavaScript('waitingMessage="message from python"')
@pyqtSlot(str)
def testJS2Py(self,msg):
print(msg)
testWeb=myClass()#用于通信的对象
myChannel.registerObject('testObject',testWeb)#注册,testObject是自己起的名字
这样,在js中就将可以使用这个通信对象的函数。
函数前的pyqtSlot()作用是接收网页发出的信号
注意:没有这行代码,底下的这个函数将无法正常执行**
JS部分:
```javascript
new QWebChannel(qt.webChannelTransport, function (channel) {
window.pyjs = channel.objects.testObject;
//testObject是注册时起的通信类名称,注意前后一致
});
```
新建一个QwebChannel对象即可完成通信连接,回调函数中将Python中的通信类绑定为window的全局变量,方便后续操作中调用该通信类中的函数
3.数据交互
现在,我们已经可以用python来打开HTML页面,并且将python中的通信类赋值给了JS。要进行通信,只需要在JS中调用通信类中的方法,即可完成数据的传输
JS=>Python
pyjs.testJS2Py('message from js');
//testJS2Py是通信类中自己定义的函数,将在python控制台中打印接收到的数据
Python=>JS
pyjs.testPy2JS()//testPy2JS也是通信类中定义的函数
testPy2JS函数实现的原理,是在python中运行JS代码
myweb.page().runJavaScript('waitingMessage="message from python"')
其中waitingMessage是我们在JS中定义的变量,用于接收python中传过来的值。
要传递一个python中定义好的变量x,可以再创建一个字符串变量,在变量x外加上引号,即可加入到字符串中,当做JS代码执行
x=2020
y="'" + x + "'"
myweb.page().runJavaScript('waitingMessage='+ y +';')
注意,不能在JS中接收我们定义的通信类中方法的返回值
4. 示例代码
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QObject, pyqtSlot, QUrl
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView
info="2"
class myClass(QObject):
@pyqtSlot()
def testPy2JS(self):
myWeb.page().runJavaScript('waitingMessage='+info+';')
@pyqtSlot(str)
def testJS2Py(self,msg):
print(msg)
if __name__ == '__main__':
testWeb=myClass()#用于通信的实例化对象
app = QApplication(sys.argv)
myWeb=QWebEngineView()
myChannel=QWebChannel()
myweb.page().setWebChannel(myChannel)
myChannel.registerObject('testO