第六国际 2024-05-31 16:55 采纳率: 58.3%
浏览 27
已结题

Pyqt QWebChannel 如何结合Vue2.0框架


<html>
    <head>
        <meta charset="UTF-8" />
        <title>QWebChannel在vue版本的使用</title>
                <script src="./qwebchannel.js"></script>
        <!-- 引入Vue 注意地址-->
        <script type="text/javascript" src="./vue.min.js"></script>
    </head>

    <body>
         <h1>Python-JavaScript 交互测试</h1>
        <button onclick="send_message_to_python()">Call Python Function</button>
        <div id='app'>
            <input type='button' onclick='getInfo()' value="获取机器信息">
            <h3 >主机名: </h3>
            <h3 >IP: </h3>
            <h3 >操作系统: </h3>
            <h3 >CPU: </h3>
            <label id='info'></label>

        </div>
    </body>
    <!-- 引入demo  html中的QWebChannel.js -->

    <script>
        new Vue({
          el: '#app',
          mounted() {
              // qt通讯
              if (typeof qt != 'undefined') {
                window.channel = new QWebChannel(qt.webChannelTransport, (channel) => {
                  window.py_object = channel.objects.python_object;
                 alert("mounted")
                })
              }else{
                alert("qc对象未获取到!");
              }
          },
          methods: {
            // 前端主动调python数据
            getInfo() {
              window.py_object.putdata()
            },
            // python中通过putdata函数,回调onGetInfo渲染页面,此页面内容可由前端开发
            onGetInfo(info) {
              alter('info1',info)
              this.defaulitValue = JSON.stringify(info)
              var h3Tags = document.getElementsByTagName('h3');
              for (var i = 0; i < h3Tags.length; i++) {
                h3Tags[i].innerHTML += Object.values(JSON.parse(this.defaulitValue))[i];
              }
            },
            // 前端传参到python
            send_message_to_python() {
                alert(window.py_object)
              var channel = new QWebChannel(qt.webChannelTransport, function (channel) {
                // Get Python object
                // Call Python object's method
                window.py_object.receive_message("Hello from JavaScript!");
              });
            },
          }
        })
    </script>
</html>

Python 端代码

from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebChannel import QWebChannel
import sys
import os
import json
import socket
import platform
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--no-sandbox"

class PythonToJS(QObject):
    def __init__(self):
        super().__init__()

    @pyqtSlot(str, result=str)
    def receive_message(self, message):
        string = "Received message from JavaScript: " + message
        print(string)
        return 'true'

    @pyqtSlot()
    def putdata(self):
        hostname = socket.gethostname()
        ip = socket.gethostbyname(hostname)
        list_info = platform.uname()
        sys_name = list_info[0] + ' ' + list_info[2]
        cpu_name = list_info[5]
        dic_info = {"hostname": hostname, "ip": ip, "sys_name": sys_name, "cpu_name": cpu_name}
        print('Sending info:', dic_info)
        view.page().runJavaScript('%s(%s)' % ('onGetInfo', json.dumps(dic_info)))


if __name__ == "__main__":
    app = QApplication(sys.argv + ["--no-sandbox"])
    view = QWebEngineView()
    channel = QWebChannel()
    python_object = PythonToJS()
    channel.registerObject("python_object", python_object)
    view.page().setWebChannel(channel)
    curdir = os.getcwd()
    url = os.path.join(curdir, 'qtweb.html')
    view.load(QUrl.fromLocalFile(url))
    view.show()
    sys.exit(app.exec_())

我使用vue框架,通过QWebChannel实现页面与python端的数据交互,运行后,python端没有反应。不知问题出现在哪里,如果不用vue,纯js的话,python端是有反应的。

  • 写回答

20条回答 默认 最新

  • 叫兽-郭老师 Java领域新星创作者 2024-05-31 16:56
    关注

    🕒下午好,题主!目前:🟢[在线]
    📢参考通义千问、由郭老师整理提供!
    📣今日诗号:落霞与孤鹜齐飞,秋水共长天一色。

    你遇到的问题是在Vue组件的生命周期中使用QWebChannel时出现的常见错误。Vue组件的生命周期与PyQt的信号机制之间存在一些微妙的差异,导致你的代码无法正常工作。

    以下是解决问题的步骤和完整代码:

    1. 确保 QWebChannel 在 Vue 实例创建之前加载

    你需要确保 qwebchannel.js 在 Vue 实例创建之前加载完成。你可以将 qwebchannel.js 的引用放在 Vue 脚本标签之前,或者使用异步加载方式。

    2. 在 mounted 生命周期钩子中建立 QWebChannel 连接

    在 Vue 组件的 mounted 生命周期钩子中建立 QWebChannel 连接,确保 Vue 实例已经完全初始化。

    3. 使用 $nextTick 更新 DOM

    Vue 的数据更新是异步的,你需要使用 $nextTick 确保 DOM 更新后才执行操作 DOM 的代码。

    4. 正确调用 Python 函数

    确保你使用 window.py_object 正确调用 Python 函数,并传递正确的参数。

    以下是修改后的完整代码:

    HTML (qtweb.html):

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8" />
      <title>QWebChannel在vue版本的使用</title>
      <script src="./qwebchannel.js"></script>
      <script type="text/javascript" src="./vue.min.js"></script>
    </head>
    <body>
      <h1>Python-JavaScript 交互测试</h1>
      <button onclick="send_message_to_python()">Call Python Function</button>
      <div id='app'>
        <input type='button' @click="getInfo" value="获取机器信息">
        <h3>主机名:</h3>
        <h3>IP:</h3>
        <h3>操作系统:</h3>
        <h3>CPU:</h3>
        <label id='info'></label>
      </div>
      <script>
        new Vue({
          el: '#app',
          mounted() {
            // 确保 qwebchannel.js 加载完成
            if (typeof qt !== 'undefined') {
              window.channel = new QWebChannel(qt.webChannelTransport, (channel) => {
                window.py_object = channel.objects.python_object;
                console.log("QWebChannel connected");
              });
            } else {
              alert("qc对象未获取到!");
            }
          },
          methods: {
            getInfo() {
              if (window.py_object) {
                window.py_object.putdata();
              } else {
                console.error("Python object not available");
              }
            },
            onGetInfo(info) {
              console.log('Received info:', info);
              this.$nextTick(() => {
                const h3Tags = document.getElementsByTagName('h3');
                for (let i = 0; i < h3Tags.length; i++) {
                  h3Tags[i].innerHTML += ' ' + Object.values(info)[i];
                }
              });
            }
          }
        });
    
        // 将 send_message_to_python 函数放在全局作用域中
        window.send_message_to_python = function () {
          if (window.py_object) {
            window.py_object.receive_message("Hello from JavaScript!");
          } else {
            console.error("Python object not available");
          }
        };
      </script>
    </body>
    </html>
    

    Python 代码:

    from PyQt5.QtCore import QUrl, QObject, pyqtSlot
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    from PyQt5.QtWebChannel import QWebChannel
    import sys
    import os
    import socket
    import platform
    
    os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--no-sandbox"
    
    class PythonToJS(QObject):
        def __init__(self):
            super().__init__()
    
        @pyqtSlot(str, result=str)
        def receive_message(self, message):
            string = "Received message from JavaScript: " + message
            print(string)
            return 'true'
    
        @pyqtSlot()
        def putdata(self):
            hostname = socket.gethostname()
            ip = socket.gethostbyname(hostname)
            list_info = platform.uname()
            sys_name = list_info[0] + ' ' + list_info[2]
            cpu_name = list_info[5]
            dic_info = {"hostname": hostname, "ip": ip, "sys_name": sys_name, "cpu_name": cpu_name}
            print('Sending info:', dic_info)
            view.page().runJavaScript(f'onGetInfo({json.dumps(dic_info)})')
    
    if __name__ == "__main__":
        app = QApplication(sys.argv + ["--no-sandbox"])
        view = QWebEngineView()
        channel = QWebChannel()
        python_object = PythonToJS()
        channel.registerObject("python_object", python_object)
        view.page().setWebChannel(channel)
        curdir = os.getcwd()
        url = os.path.join(curdir, 'qtweb.html')
        view.load(QUrl.fromLocalFile(url))
        view.show()
        sys.exit(app.exec_())
    

    解释:

    • 在 HTML 中,我们将 qwebchannel.js 的引用放在了 Vue 脚本之前,并在 Vue 组件的 mounted 生命周期钩子中建立了 QWebChannel 连接。
    • 我们使用 @click 绑定 getInfo 方法,并在 onGetInfo 方法中使用 this.$nextTick 更新 DOM。
    • 我们将 send_message_to_python 函数放在了全局作用域中,以便按钮可以调用它。
    • 在 Python 代码中,我们使用 json.dumps 将字典转换为 JSON 字符串,并在 runJavaScript 函数中使用字符串插值构建 JavaScript 代码。

    通过以上修改,你的代码应该可以正常工作了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(19条)

报告相同问题?

问题事件

  • 系统已结题 6月15日
  • 已采纳回答 6月7日
  • 修改了问题 5月31日
  • 修改了问题 5月31日
  • 展开全部

悬赏问题

  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表
  • ¥15 DbVisualizer Pro 12.0.7 sql commander光标错位 显示位置与实际不符
  • ¥15 android 打包报错