QWebEnginePage 与 javascript 交互不起作用?

QWebEnginePage interactive with javascript not working?

我不熟悉 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>

您有以下错误:

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

    的属性来延长生命周期
  • 在 .html 中你试图包含 qwebchannel.js 但通常你应该使用 <script src="qrc:///qtwebchannel/qwebchannel.js"></script>.

  • 如果您将 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>