首页 > 解决方案 > QWebEnginePage 与 javascript 交互不起作用?

问题描述

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

蟒蛇代码

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>

标签: pythonpython-3.xpyqtpyqt5qtwebchannel

解决方案


您有以下错误:

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

  • 在 .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>

推荐阅读