【问题标题】:PyQt5 retrieve form values using runJavaScriptPyQt5 使用 runJavaScript 检索表单值
【发布时间】:2019-09-20 16:28:43
【问题描述】:

我有一个form.html 文件,我使用 PyQt5 QWebEngineView 运行它。 单击提交按钮后,我想检索表单值。我经历了许多解决方案,但找不到完美的解决方案。 例如:我找到了this one,但它适用于URL Change

我只是在寻找一个可以点击提交按钮的解决方案。

这是我从上述链接中使用的代码,但我没有从表单返回任何值:

import os
import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from PyQt5.QtCore import QUrl, QEventLoop
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor

class WebPage(QWebEngineView):
    def __init__(self):
        QWebEngineView.__init__(self)
        filepath = os.path.abspath(os.path.join(os.path.dirname(__file__), 'form.html'))
        self.load(QUrl.fromLocalFile(filepath))
        self.loadFinished.connect(self._on_load_finished)

    def _on_load_finished(self):
        self.page().runJavaScript("document.getElementById('num1').value", self.store_value)

    def store_value(self, param):
        self.value = param
        print("Param: " +str(param))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    web = WebPage()
    web.show()
    sys.exit(app.exec_())

HTML:

<html>
    <body>
        <form>
            Number 1:<input type="text" id="num1">
            <br>
            Number 2:<input type="text" id="num2">
            <br>
            <input type="submit" id="sub1">
        </form>
    </body>
</html>

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qwebengineview


    【解决方案1】:

    基于我在my old answer中使用的策略,解决方案是通过QWebChannel注入一个QObject,并在其中与按钮点击事件进行绑定以更新插槽。在这种情况下,我使用Jinja2 来简化脚本的编写。

    import os
    import sys
    from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
    from jinja2 import Template
    
    
    class Element(QtCore.QObject):
        def __init__(self, name, parent=None):
            super(Element, self).__init__(parent)
            self._name = name
    
        @property
        def name(self):
            return self._name
    
        def script(self):
            raise NotImplementedError
    
    
    class FormObject(Element):
        numbersChanged = QtCore.pyqtSignal(str, str)
    
        def script(self):
            _script = r"""
            var btn = document.getElementById('sub1');
            btn.addEventListener("click", function(event){
                var number1 = document.getElementById('num1');
                var number2 = document.getElementById('num2');
                {{name}}.update(number1.value , number2.value);
            });
            """
            return Template(_script).render(name=self.name)
    
        @QtCore.pyqtSlot(str, str)
        def update(self, number1, number2):
            self.numbersChanged.emit(number1, number2)
    
    
    class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
        def __init__(self, *args, **kwargs):
            super(WebEnginePage, self).__init__(*args, **kwargs)
            self.loadFinished.connect(self.onLoadFinished)
            self._objects = []
    
        def add_object(self, obj):
            self._objects.append(obj)
    
        @QtCore.pyqtSlot(bool)
        def onLoadFinished(self, ok):
            if ok:
                self.load_qwebchannel()
                self.load_objects()
    
        def load_qwebchannel(self):
            file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
            if file.open(QtCore.QIODevice.ReadOnly):
                content = file.readAll()
                file.close()
                self.runJavaScript(content.data().decode())
            if self.webChannel() is None:
                channel = QtWebChannel.QWebChannel(self)
                self.setWebChannel(channel)
    
        def load_objects(self):
            if self.webChannel() is not None:
                objects = {obj.name: obj for obj in self._objects}
                self.webChannel().registerObjects(objects)
                _script = r"""
                {% for obj in objects %}
                var {{obj}};
                {% endfor %}
                new QWebChannel(qt.webChannelTransport, function (channel) {
                {% for obj in objects %}
                    {{obj}} = channel.objects.{{obj}};
                {% endfor %}
                }); 
                """
                self.runJavaScript(Template(_script).render(objects=objects.keys()))
                for obj in self._objects:
                    if isinstance(obj, Element):
                        self.runJavaScript(obj.script())
    
    
    class WebPage(QtWebEngineWidgets.QWebEngineView):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            page = WebEnginePage(self)
            self.setPage(page)
    
            formobject = FormObject("formobject", self)
            formobject.numbersChanged.connect(self.on_numbersChanged)
            page.add_object(formobject)
    
            filepath = os.path.abspath(
                os.path.join(os.path.dirname(__file__), "form.html")
            )
            self.load(QtCore.QUrl.fromLocalFile(filepath))
    
        @QtCore.pyqtSlot(str, str)
        def on_numbersChanged(self, number1, number2):
            print(number1, number2)
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        web = WebPage()
        web.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的帮助。该解决方案完美运行。但是,我有很多表单页面 (15-20),因为这里的所有内容都是硬编码的,所以我发现很难为更多页面编辑代码。而不是提交,我有下一个按钮,它将打开 form2.html 然后是 form3.html 等等......所有表单都有不同数量和类型的变量。有没有办法从所有表单中获取值?
    • 只是为了更清楚一点:我有 7 个表单,每个表单都有一个下一步按钮,最后一个表单有一个提交按钮。所有表单都有一个添加按钮,我可以使用它创建一个子表单,它是主表单的副本。无论我单击下一步按钮还是添加按钮或提交按钮......表单中的当前值必须由 python 变量检索。此外,还有一个上一个按钮单击,我可以转到上一个表单并编辑一个值并单击下一步(在这种情况下应该覆盖变量)。
    • 注意:所有表单都是单独的 HTML 文件,我通过 HTML 文件中的 javascript 加载(而不是通过 Python)。我擅长 Python 和 HTML,但我是 QWebEngineView 概念的初学者。如果您能提出一些建议(如果不是完整的解决方案),那就太好了。
    • @Enzy 我的答案取决于您在问题中提出的建议,我可以尝试概括,但为了概括,您需要更多您在问题中没有提供但在 cmets 中提供的信息,所以我的建议是您发布一个新问题,指出提供minimal reproducible example 的概括,我们可以帮助您:-)
    • 是的,当然。我想我将能够以自己的方式概括解决这个问题的方法,以进一步提高自己在这方面的能力。但我无能为力。那我会发布一个新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多