QtWebkit和QWebEngineView与Javascript交互

以前还是QWebView的时候和Javascript交互起来很方便,但是到了Qt5.6以后改用了QWebEngineView,并通过其提供的qwebchannel.js来进行交互。可能是由于刚出来的原因,这玩意儿有个bug就是必须在每次加载页面的时候手动注入,跳转页面后就失效了,需要手动注入,目前有没有修复具体未测试。这里对QWebViewQWebEngineView与Js交互都做了一个示例。

说明

  1. 针对QWebView通过QWebFrameaddToJavaScriptWindowObject把对象传递到Javascript
  2. 针对QWebEngineView通过QWebChannel.registerObject('Bridge', QObject)把对象传递到Javascript
  3. 可以通过@pyqtSlot装饰器来申明该方法可以暴露给Javascript调用
@pyqtSlot(str)
def callFromJs(self, text):
    QMessageBox.information(self, "提示", "来自js调用:{}".format(text))
  1. 针对QWebViewJavascript中获取该对象,可以通过该对象对窗口属性以及信号和暴露出的方法进行调用
// 这里绑定窗口的标题变化信号(这个信号是由QWidget内部的)
Bridge.windowTitleChanged.connect({fun: function(title) {
    showLog("标题被修改为:" + title);
}}, "fun");

// 绑定自定义的信号customSignal
Bridge.customSignal.connect({fun: function(text) {
    showLog("收到自定义信号内容:" + text);
}}, "fun");
  1. 针对QWebEngineViewJavascript中获取该对象,可以通过该对象对窗口属性以及信号和暴露出的方法进行调用
new QWebChannel(qt.webChannelTransport,
    function(channel) {
        window.Bridge = channel.objects.Bridge;

        // 这里绑定窗口的标题变化信号(这个信号是由QWidget内部的)
        Bridge.windowTitleChanged.connect(function(title) {
            showLog("标题被修改为:" + title);
        });

        // 绑定自定义的信号customSignal
        Bridge.customSignal.connect(function(text) {
           showLog("收到自定义信号内容:" + text);
        });
    }
);

代码

QWebViewhttps://github.com/PyQt5/PyQt/blob/master/QWebView/JsSignals.py

QWebEngineViewhttps://github.com/PyQt5/PyQt/blob/master/QWebEngineView/JsSignals.py

  1. 针对QWebView的核心实现
class WebView(QWebView):

    customSignal = pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super(WebView, self).__init__(*args, **kwargs)
        self.initSettings()
        # 暴露接口对象
        self.page().mainFrame().javaScriptWindowObjectCleared.connect(self._exposeInterface)

    def _exposeInterface(self):
        """向Js暴露调用本地方法接口
        """
        self.page().mainFrame().addToJavaScriptWindowObject('Bridge', self)

    # 注意pyqtSlot用于把该函数暴露给js可以调用
    @pyqtSlot(str)
    def callFromJs(self, text):
        QMessageBox.information(self, "提示", "来自js调用:{}".format(text))

    def sendCustomSignal(self):
        # 发送自定义信号
        self.customSignal.emit('当前时间: ' + str(time()))
  1. 针对QWebEngineView的核心实现
class WebEngineView(QWebEngineView):

    customSignal = pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super(WebEngineView, self).__init__(*args, **kwargs)
        self.channel = QWebChannel(self)
        # 把自身对象传递进去
        self.channel.registerObject('Bridge', self)
        # 设置交互接口
        self.page().setWebChannel(self.channel)

    # 注意pyqtSlot用于把该函数暴露给js可以调用
    @pyqtSlot(str)
    def callFromJs(self, text):
        QMessageBox.information(self, "提示", "来自js调用:{}".format(text))

    def sendCustomSignal(self):
        # 发送自定义信号
        self.customSignal.emit('当前时间: ' + str(time()))

效果图

JsSignals


文章目录
  1. 1. 说明
  2. 2. 代码
  3. 3. 效果图
|