QWebEnginePage 与 javascript 交互不起作用?

Posted

技术标签:

【中文标题】QWebEnginePage 与 javascript 交互不起作用?【英文标题】:QWebEnginePage interactive with javascript not working? 【发布时间】:2020-07-18 09:58:10 【问题描述】:

我不熟悉javascriptQWebEnginePage。 当我设置self.content.setText('text') 内容时,QWebEngineView 内容没有改变?

python 代码

class Document(QObject):
    textChanged = pyqtSignal(str)
    def __init__(self):
        super().__init__()
        self.text  = ''
    
    def setText(self, text):
        self.text = text
        self.textChanged.emit(text)
        print('emit')

class Demo(QWebEngineView):
    def __init__(self):
        super().__init__()
        self.content = Document()
        page = self.page()
        channel = QWebChannel()
        channel.registerObject('content', self.content)
        page.setWebChannel(channel)
        with open('index.html') as f:
            self.setHtml(f.read())

        self.content.setText('text')

app = QApplication([])
demo = Demo()
demo.resize(500, 400)
demo.show()
app.exec()

索引html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
    <script src="qwebchannel.js"></script>
</head>
<body>
<div id="placeholder">22</div>
<script>
    'use strict';

    var placeholder = document.getElementById('placeholder');

    var updateText = function (text) 
        placeholder.innerHTML = text;
        console.log(text);
    

    new QWebChannel(qt.webChannelTransport,
        function (channel) 
            var content = channel.objects.content;
            updateText(content.text);
            content.textChanged.connect(updateText);
        
    );
</script>
</body>
</html>

【问题讨论】:

【参考方案1】:

您有以下错误:

channel 是一个局部变量,一旦“Demo”构造函数完成就会被删除,它是 Python 和 Javascript 通信的中介。解决方案是通过将其传递给父级(Qt 样式)或使其成为类的属性来延长生命周期。

您尝试在 .html 中包含 qwebchannel.js,但通常您应该使用 &lt;script src="qrc:///qtwebchannel/qwebchannel.js"&gt;&lt;/script&gt;

如果您将 QObject 导出到 javascript,则只会导出 Q-Properties、QSlot 和 QSignals,因为 QWebChannel 使用 QMetaObject instropection,但“文本”不是它们,因此它在 javascript 中是未定义的。解决方案是将其公开为 pyqtProperty。

import os
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebChannel import QWebChannel


CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


class Document(QObject):
    textChanged = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self._text = ""

    def text(self):
        return self._text

    def setText(self, text):
        self._text = text
        self.textChanged.emit(text)
        print("emit")

    text = pyqtProperty(str, fget=text, fset=setText, notify=textChanged)


class Demo(QWebEngineView):
    def __init__(self):
        super().__init__()

        self.content = Document()

        channel = QWebChannel(self)
        channel.registerObject("content", self.content)
        self.page().setWebChannel(channel)

        filename = os.path.join(CURRENT_DIR, "index.html")
        self.load(QUrl.fromLocalFile(filename))

        self.content.setText("text")


def main():
    app = QApplication([])
    demo = Demo()
    demo.resize(500, 400)
    demo.show()
    app.exec()


if __name__ == "__main__":
    main()
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
    <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder">22</div>
<script>
    'use strict';

    var placeholder = document.getElementById('placeholder');

    var updateText = function (text) 
        placeholder.innerHTML = text;
        console.log(text);
    

    new QWebChannel(qt.webChannelTransport,
        function (channel) 
            var content = channel.objects.content;
            updateText(content.text);
            content.textChanged.connect(updateText);
        
    );
</script>
</body>
</html>

【讨论】:

了解更多,第三季度。

以上是关于QWebEnginePage 与 javascript 交互不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

QWebEnginePage:toHtml 返回一个空字符串

qt5.7 中的信号和槽 - QWebEnginePage

QWebEnginePage 中的 setFeaturePermission 成员函数如何工作?

将 QWebEngineHistory 保存并加载到 QWebEnginePage

是否可以在屏幕外渲染 QWebEnginePage/QWebEngineView?

如何为不同的 QWebEnginePage 实例设置不同的代理?