I am not familiar with javascript
and QWebEnginePage
.
When i set self.content.setText('text')
content, the QWebEngineView
content not changed?
The python code
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()
The index 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>
You have the following errors:
channel is a local variable that will be removed as soon as the "Demo" constructor is finished, and that is the intermediary between Python and Javascript communication. The solution is to extend the life cycle by passing it a parent (Qt style) or make it an attribute of the class.
In the .html you are trying to include qwebchannel.js but in general you should use <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
.
If you export a QObject to javascript then only the Q-Properties, QSlot and QSignals will be exported since QWebChannel uses the QMetaObject instropection, but "text" is neither of them so it will be undefined in javascript. The solution is to expose it as a 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>