1

Get variable from js QWebEngineView to python.

I am using PyQt5 with QT Designer of python3 and I am using QWebEngineView to load an html and js. Inside the html there is an input and a button, pressing the button executes a js function that saves the value of the input in a variable.

How can I get that variable out of js and go to python?

Code HTML:

<input id="input">
<button id="button" onclick="x()"></button>
<script>
function x() {
    var a = document.getElementById("input").value;
}
</script>

Code Python:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(449, 391)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        Form.setWindowIcon(icon)
        Form.setWindowOpacity(0.8)
        self.webEngineView = QtWebEngineWidgets.QWebEngineView(Form)
        self.webEngineView.setGeometry(QtCore.QRect(-1, 0, 451, 391))
        self.webEngineView.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.webEngineView.setStyleSheet("width: 100%")
        self.webEngineView.setUrl(QtCore.QUrl("file:///C:/xampp/htdocs/indexx.html"))
        self.webEngineView.setObjectName("webEngineView")
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Bancus"))
from PyQt5 import QtWebEngineWidgets

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
Oni
  • 41
  • 8

1 Answers1

2

The description of your question is unclear, but assuming you want to get the text placed in the input in python when the button is pressed and you can modify the HTML then a possible solution is to use QWebChannel:

from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel


class Backend(QtCore.QObject):
    valueChanged = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self._value = ""

    @QtCore.pyqtProperty(str)
    def value(self):
        return self._value

    @value.setter
    def value(self, v):
        self._value = v
        self.valueChanged.emit(v)


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.webEngineView = QtWebEngineWidgets.QWebEngineView()
        self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.webEngineView, stretch=1)
        lay.addWidget(self.label, stretch=1)

        backend = Backend(self)
        backend.valueChanged.connect(self.label.setText)
        backend.valueChanged.connect(self.foo_function)
        self.channel = QtWebChannel.QWebChannel()
        self.channel.registerObject("backend", backend)
        self.webEngineView.page().setWebChannel(self.channel)

        path = "C:/xampp/htdocs/indexx.html"
        self.webEngineView.setUrl(QtCore.QUrl.fromLocalFile(path))

    @QtCore.pyqtSlot(str)
    def foo_function(self, value):
        print(value)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>        
        <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
    </head>
    <body> 
         <input id="input">
         <button id="button">Click me</button>
    </body>
    <script>
        var backend = null;
        new QWebChannel(qt.webChannelTransport, function (channel) {
            backend = channel.objects.backend;
        });
        document.getElementById("button").addEventListener("click", function(){
            backend.value = document.getElementById("input").value;
        });
    </script>
</html>

If what I assumed is wrong somewhere then feel free to point it out to provide a suitable solution.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I would like to click on the button to execute a python function that uses the input text as an argument – Oni Nov 20 '19 at 00:38
  • @Oni I have modified my code by adding the function foo_function that will be called when the button is pressed, in my example it prints that value. – eyllanesc Nov 20 '19 at 00:43
  • Sorry for the delay, but it's just what I needed. Thanks +1 – Oni Nov 20 '19 at 14:46