Python、PySide6; JS 没有从 QWebChannel 接收数据

问题描述 投票:0回答:1

这个问题我看了很多答案,但还是不明白。 我制作了两个文件,一个是带有 qrc 定义的 html + 新的 QWebChannel,第二个是带有 Object 和 QWebEngineView 的 python 文件。 JS 脚本似乎不起作用。它不会将通道对象绑定到本地变量。 我已经尝试了许多页面上的许多示例,寻找原生 QT 语言或 C++,我无法弄清楚。 找到 QWebChannel 定义和 qt 对象。

也许 PySide6 有什么问题?请帮我解决一下。

我的代码:

index.html

<head>
    <title>Test</title>
     <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
    <script type="text/javascript">
        let dataSource = null
        window.onload = function () {
            alert('before') //works
            new QWebChannel(qt.webChannelTransport, function (channel) {
                    alert('inside') //not working
                    dataSource = channel.objects.backend;
                }
            );
            alert('after') //works
            alert(dataSource) //null
        }
   </script>
</head>
<body>
<p>Hello</p>
</body>
</html>

主.py

import sys, os

from PySide6.QtCore import Signal, QUrl, Slot, QObject
from PySide6.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QWidget
from PySide6.QtWebEngineWidgets import *
from PySide6.QtWebEngineCore import *
from PySide6.QtWebChannel import QWebChannel


class Backend(QObject):
    @Slot(result=int)
    def getValue(self):
        return 1

    @Slot(int)
    def printValue(self, val):
        print(val)


class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow,self).__init__(*args, **kwargs)
        self.browser = QWebEngineView()

        backend = Backend()
        channel = QWebChannel()
        channel.registerObject("backend", backend)
        self.browser.page().setWebChannel(channel)

        current_dir = os.path.dirname(os.path.realpath(__file__))
        filename = os.path.join(current_dir, "index.html")
        url = QUrl.fromLocalFile(filename)
        self.browser.load(url)

        self.setCentralWidget(self.browser)
        self.resize(1200,900)
        self.show()

app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())

更新:

我扩展了视图,添加了开发工具和 jquery 来检查对象 - 这就是我所拥有的:

console log result on objects

更新2: 我删除了 PySide6,安装了 PyQt5 并使用了这里的示例: 如何使用QWebChannel从python接收数据到js?

一切正常:/ 我花了一整天的时间来弄清楚。我不知道为什么它不起作用。

python qt python-3.10 pyside6 qtwebengine
1个回答
0
投票

我最近遇到了同样的问题,结果发现QWebChannel无法在QMainWindow内工作。按照这个示例,我尝试了解 QWebChannel 如何与 PySide6 配合使用。当然,下面的示例可以按预期工作:

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
        <script type="text/javascript">
            var backend = null;
            window.onload = function()
            {
                new QWebChannel(qt.webChannelTransport, function(channel) {
                    backend = channel.objects.backend;
                    var x = {a: "1000", b: ["Hello", "From", "JS"]}
                    backend.getRef(JSON.stringify(x), function(y) {
                        js_obj = JSON.parse(y);
                        js_obj["f"] = false;
                        backend.printRef(JSON.stringify(js_obj));
                    });
                });
            }
        </script>
    </head>
</html>

import json

from PySide6 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel


class Backend(QtCore.QObject):
    @QtCore.Slot(str, result=str)
    def getRef(self, o):
        print("inside getRef", o)
        py_obj = json.loads(o)
        py_obj["c"] = ("Hello", "from", "Python")
        return json.dumps(py_obj)

    @QtCore.Slot(str)
    def printRef(self, o):
        py_obj = json.loads(o)
        print("inside printRef", py_obj)



if __name__ == "__main__":
    import os
    import sys

    app = QtWidgets.QApplication(sys.argv)

    backend = Backend()

    view = QtWebEngineWidgets.QWebEngineView()

    channel = QtWebChannel.QWebChannel()
    view.page().setWebChannel(channel)
    channel.registerObject("backend", backend)

    current_dir = os.path.dirname(os.path.realpath(__file__))
    filename = os.path.join(current_dir, "index.html")
    url = QtCore.QUrl.fromLocalFile(filename)
    view.load(url)
    view.show()
    sys.exit(app.exec())

但是,当我尝试将 QWebChannel 引入 QMainWindow 时,它不起作用:

import json
import os
import sys

from PySide6.QtCore import Slot, QUrl, QObject
from PySide6 import QtWebChannel
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PySide6.QtWebEngineWidgets import QWebEngineView


class Backend(QObject):
    @Slot(str, result=str)
    def getRef(self, o):
        print("inside getRef", o)
        py_obj = json.loads(o)
        py_obj["c"] = ("Hello", "from", "Python")
        return json.dumps(py_obj)

    @Slot(str)
    def printRef(self, o):
        py_obj = json.loads(o)
        print("inside printRef", py_obj)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.widget = QWidget()

        self.browser = QWebEngineView()

        backend = Backend()
        channel = QtWebChannel.QWebChannel()
        self.browser.page().setWebChannel(channel)
        channel.registerObject("backend", backend)

        current_dir = os.path.dirname(os.path.realpath(__file__))
        filename = os.path.join(current_dir, "index.html")
        url = QUrl.fromLocalFile(filename)
        self.browser.load(url)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.browser)
        self.setLayout(self.layout)

        self.setCentralWidget(self.widget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    app.exec()

我找到的解决方案是引入 QWebChannel,它的工作原理与上面的第一个 Python 代码相同。

import json
import os
import sys

from PySide6.QtCore import Slot, QUrl, QObject
from PySide6 import QtWebChannel
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PySide6.QtWebEngineWidgets import QWebEngineView


class Backend(QObject):
    @Slot(str, result=str)
    def getRef(self, o):
        print("inside getRef", o)
        py_obj = json.loads(o)
        py_obj["c"] = ("Hello", "from", "Python")
        return json.dumps(py_obj)

    @Slot(str)
    def printRef(self, o):
        py_obj = json.loads(o)
        print("inside printRef", py_obj)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.widget = QWidget()

        self.browser = QWebEngineView()

        current_dir = os.path.dirname(os.path.realpath(__file__))
        filename = os.path.join(current_dir, "index.html")
        url = QUrl.fromLocalFile(filename)
        self.browser.load(url)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.browser)
        self.setLayout(self.layout)

        self.setCentralWidget(self.widget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()

    backend = Backend()
    channel = QtWebChannel.QWebChannel()
    window.browser.page().setWebChannel(channel)
    channel.registerObject("backend", backend)
    
    window.show()

    app.exec()

我不知道为什么会这样,我希望其他人可以对此提供一些见解。

© www.soinside.com 2019 - 2024. All rights reserved.