PyQt6 与 Pyecharts 交互:将鼠标点击 html 页面某点时的提示框信息在 PyQt 界面显示

这篇具有很好参考价值的文章主要介绍了PyQt6 与 Pyecharts 交互:将鼠标点击 html 页面某点时的提示框信息在 PyQt 界面显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

版本信息

PyQt6:6.6.1
pyqt6-tools:6.4.2.3.3
PyQt6-WebEngine:6.6.0

pyqt6 官方文档:Reference Guide — PyQt Documentation v6.6.0

1. 知识点:信号与槽函数

在 PyQt 中,信号signal和槽slot是用来处理事件的机制。

信号是一个对象,当它被发射时,会通知所有连接的槽。槽是一个函数,当信号被发射时,它会被调用。

PyQt中常见控件及其对应的信号举例:

QPushButton:clicked()

QCheckBox:stateChanged() 

QLineEdit:textChanged() 

QSlider:valueChanged() 

QTableView:doubleClicked()

(1) 信号只能在QObject的子类中定义使用pyqtSignal函数可以创建未绑定的信号作为类的属性,信号可以传递多个参数,且可以指定参数类型(标准的python数据类型)。

(2) 与信号关联的槽函数可以实现当信号发射时,做什么事情。信号与槽函数通过connet连接;

(3) 使用emit可以发射信号,触发与信号关联的槽函数。

(4) 定义信号时要注意代码位置,不能在初始化中定义信号,否则会遇到报错PyQt5.QtCore.pyqtSignal‘ object has no attribute ‘connect‘,信号应作为类属性而不是实例属性

错误示范

class MyObject(QObject):
   
    def __init__(self):
        super().__init__()
        # 定义信号位置错误!!!
        self.show_infoes_signal = pyqtSignal(str)

正确示范

class MyObject(QObject):
    show_infoes_signal = pyqtSignal(str)
   
    def __init__(self):
        super().__init__()

更多信息参考下方链接

自定义信号signal和槽slot时报错‘PyQt5.QtCore.pyqtSignal‘ object has no attribute ‘connect‘解决方案_pyqt5.qtcore.pyqtsignal' object has no attribute '-CSDN博客

2. 将鼠标点击图上某点时所显示的提示框信息输出到界面PlainTextEdit

1 获取鼠标点击网页元素时,提示框的信息

首先看一下Pyecharts生成的网页内容(右键检查->元素):

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

由上述信息可知,第一个div的内容即为提示框信息对应的文本内容,可以在HTML文件中增加以下脚本进行确认,结果符合预期。


    <script>
        document.addEventListener("mousemove", function() {
            var web_info = document.getElementsByTagName("div")[0].innerText;
            console.log(web_info)
    })
    </script>

控制台打印结果: 

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

2 插曲(赶时间可跳过这段):mousePressEvent不能用于QWebEngineView对象

PyQt中,QWebEngineView对象可通过“对象名.page()”函数获得QWebEnginePage对象,QWebEnginePage类有一个runJavaScript方法,这个方法可以通过执行JS语句与页面交互,并可以通过回调函数接收执行结果,其语句如下:

QWebEnginePage.runJavaScript('JS语句', 回调函数)

因而,最初的想法是,通过mousePressEvent监控鼠标行为,当发生鼠标点击行为时,通过runJavaScript直接获取网页上所需变量的值,从而获得我想要的信息。然而尝试后发现,始终没有任何输出。

猜想mousePressEvent这部分有问题,通过如下代码验证:首先创建一个QMainWindow,其中有一个QWebEngineView控件,用于显示网页;然后重写mousePressEvent,如果识别到鼠标点击操作,就在控制台打印一个"yes",通过这种方式,看一下鼠标点击在界面不同位置的效果。运行代码后发现,鼠标点击在QWebEngineView控件内部时,控制台始终没有任何打印,因而上述思路不可行。

# 如下代码属于尝试阶段,可运行体验
from PyQt6.QtWidgets import QApplication, QMainWindow
import sys
import cdsn_show
from PyQt6.QtCore import QUrl, QFileInfo


class Ui_CDSN(cdsn_show.Ui_MainWindow, QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        url = QUrl("file:" + QFileInfo("cdsn_figure.html").absoluteFilePath())
        self.widget_figure.load(url)
        self.show()

    def mousePressEvent(self, event):
        print("yes")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    my_ui = Ui_CDSN()
    sys.exit(app.exec())

3 基于QWebChannel实现PyQt与HTML文件的交互

原理简述:QWebChannel是一种在Web页面和Python代码之间进行通信的机制。它的原理是通过JavaScript和Python之间的桥接,使得Web页面中的JavaScript代码可以调用Python中的代码,并且Python中的代码也可以调用Web页面中的JavaScript代码。

步骤一:下载qwebchannel.js文件

网址:https://github.com/qt/qtwebchannel/tree/dev/examples/webchannel/shared

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

步骤二:Python部分

(1) Ui界面文件<csdn_show.py>

界面主要包含一个qwebengineview控件widget_figure用于显示网页,一个plaintextedit控件用于显示信息。

from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6 import QtWebEngineWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(994, 722)
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.widget = QtWidgets.QWidget(parent=self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(40, 30, 921, 631))
        self.widget.setObjectName("widget")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.widget_figure = QtWebEngineWidgets.QWebEngineView(parent=self.widget)
        self.widget_figure.setObjectName("widget_figure")
        self.verticalLayout_2.addWidget(self.widget_figure)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.label = QtWidgets.QLabel(parent=self.widget)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        spacerItem = QtWidgets.QSpacerItem(20, 78, QtWidgets.QSizePolicy.Policy.Minimum,
                                           QtWidgets.QSizePolicy.Policy.Expanding)
        self.verticalLayout.addItem(spacerItem)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.plainTextEdit = QtWidgets.QPlainTextEdit(parent=self.widget)
        self.plainTextEdit.setObjectName("plainTextEdit")
        self.horizontalLayout.addWidget(self.plainTextEdit)
        self.verticalLayout_2.addLayout(self.horizontalLayout)
        self.verticalLayout_2.setStretch(0, 8)
        self.verticalLayout_2.setStretch(1, 3)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 994, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "提示信息"))

(2) Pycharts生成的HTML图

不做展开,请自行准备,参考Pyqt6与Pyecharts交互 -- 持续更新_pyside6 pyqt6 pyecharts-CSDN博客

(3) 程序运行文件<csdn_main.py>

说明:InteractObject部分

1. 创建一个QObject子类,后续会将其注册到QWebChannel对象中(必须是QObject子类)。

2. 定义了一个名为receive_message的槽函数,该槽函数将打印并返回传递给它的数据。

说明:Ui_CSDN部分

1. 创建了一个QWebChannel对象,并将其绑定到QWebEngineView对象上,以便在HTML页面和Python代码之间传递数据。

2. 创建了一个InteractObject对象self.obj,并将这个对象注册到WebChannel中,注册名为interact_object,HTML页面可以通过WebChannel对象调用InteractObject对象的方法和属性,借此传递页面消息给PyQt或获取来自PyQt的信息。

3. 将自定义信号self.obj.mySignal与自定义槽函数updata_plain_text_edit连接起来,以便将接收到的信息显示在PyQt界面上。

import sys
import csdn_show
from PyQt6.QtWebChannel import QWebChannel
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtCore import QUrl, QFileInfo, pyqtSlot, QObject, pyqtSignal


class InteractObject(QObject):
    mySignal = pyqtSignal(str)

    def __init__(self):
        super().__init__()

    @pyqtSlot(str, result=str)
    def receive_message(self, message):
        if isinstance(message, str):
            print(f"Received message from html:\n{message}")
            self.mySignal.emit(message)
            return message
        else:
            print("no message")
            return "no message"


class Ui_CSDN(cdsn_show.Ui_MainWindow, QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.channel = QWebChannel()
        self.widget_figure.page().setWebChannel(self.channel)
        self.obj = InteractObject()
        self.channel.registerObject("interact_object", self.obj)

        url = QUrl("file:" + QFileInfo("cdsn_figure.html").absoluteFilePath())
        self.widget_figure.load(url)
        self.show()
        self.obj.mySignal.connect(self.updata_plain_text_edit)

    @pyqtSlot(str)
    def updata_plain_text_edit(self, message):
        try:
            self.plainTextEdit.setPlainText(message)
        except Exception as e:
            self.plainTextEdit.setPlainText('No Message')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = Ui_CSDN()
    app.exec()

步骤三:Javascript部分

1. 引入qwebchannel.js文件,文件路径请根据实际情况调整。

2. 实例化QWebChannel(QWebChannel在qwebchannel.js中定义,因而需要先引入.js文件),并在回调函数中,通过channel.objects.bridge获取来自PyQt的共享对象interact_object,代码中的interact_object即为第二步注册时使用的名字,务必与前面注册时一致。

3. 增加鼠标点击事件监听,当发生鼠标点击事件时,将页面值通过interact_object返回给PyQt。

    <script type="text/javascript" src="D:/0_study_code/Sites3DFigDisplay/pyecharts-assets-master/assets/qwebchannel.js"></script>
    <script>
        document.addEventListener("DOMContentLoaded", function() {
	        //把对象赋值到JS中
	        var channel = new QWebChannel(window.qt.webChannelTransport, function(channel) {
		    // Get interact_object
		    window.interact_object = channel.objects.interact_object;
	    });
    });
        document.addEventListener("click", function() {
            var web_info = document.getElementsByTagName("div")[0].innerText;
            window.interact_object.receive_message(web_info);
    })
        
    </script>

pyecharts-html文件最终内容一览

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

QWebchannel部分研究了好久,感谢博主【天马小Q】的博文,让我豁然开朗,放在下面给大家参考。

参考链接:PyQt5 QWebEngineView中实现Python和JavaScript交互数据传递demo_pyqt5 qwebengineview js-CSDN博客

步骤四:编写函数,每次Pyecharts生成图像后,自动添加上述JS脚本

def add_content(filename):
    s_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "pyecharts-assets-master",
                                               "assets", "qwebchannel.js"))
    html_js_path = str(js_path).replace("\\", r'/')
    add_content = [
        '\t\t<script type="text/javascript" ' + f'src="{html_js_path}"></script>\n',
        '\t<script>\n',
        '\t\tdocument.addEventListener("DOMContentLoaded", function() {\n',
        '\t\t\tvar channel = new QWebChannel(window.qt.webChannelTransport, function(channel) {\n',
        '\t\t\twindow.interact_object = channel.objects.interact_object;\n',
        '\t\t\t});\n',
        '\t\t});\n',
        '\t\tdocument.addEventListener("click", function() {\n',
        '\t\t\tvar web_info = document.getElementsByTagName("div")[0].innerText;\n',
        '\t\t\twindow.interact_object.receive_message(web_info);\n',
        '\t\t})\n',
        '\t</script>\n']
    with open(filename, 'r') as file:
        html_content = file.readlines()

    insert_index = 7
    target_content = 'pyecharts-assets-master'
    if target_content not in html_content[5]:
        insert_index = -1
        for i in range(len(html_content)):
            if target_content in html_content[i]:
                insert_index = i + 1
                break
    if insert_index == '-1':
        print('无法确定内容插入位置')
        return False
    else:
        print('可进行内容插入')

    new_html_content = html_content[:insert_index] + add_content + html_content[insert_index:]
    with open(filename, 'w') as file:
        # 将修改后的HTML内容写回文件
        file.writelines(new_html_content)

    return True

3. 效果展示

当鼠标点击图上点时,提示框中的信息会同步显示在下方PlainTextEdit框中。

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

如果出现类似下图的报错,大概率是标黄的路径写的有问题,核对一下。

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts

pyqt6中显示html,PyQt,python,开发语言,pyqt,echarts文章来源地址https://www.toymoban.com/news/detail-858397.html

到了这里,关于PyQt6 与 Pyecharts 交互:将鼠标点击 html 页面某点时的提示框信息在 PyQt 界面显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PyQt实现QSlider滑块鼠标点击事件

    在PyQt添加SQlider滑动条后,发现鼠标点击时滑块只能按照设定步数一步步移动,不能点哪里滑块到哪里。网上查找资料后发现这方面相关参考资料比较少,且大多数文章表述对我个人来说比较难理解,最后综合参考几篇较好的文章后才实现功能,在这里记录一下具体实现方法

    2024年02月09日
    浏览(39)
  • PyQt6 和 PyQt5 的差异

    PyQt6 是 PyQt5 的下一个版本,但两个版本的写法基本上其实大同小异,这篇教学会介绍 PyQt6 和 PyQt5 有何差异。 快速预览: .exec_() 改为 .exec() 方法的位置或名称改变 不需要高 DPI 缩放属性 支援 Qt的资源 特定平台 其他细节差异 PyQt6 教学 - PyQt6 和 PyQt5 的差异 在 Python 2.7

    2024年02月15日
    浏览(42)
  • PyQT5和PyQt6的区别

    PyQt6和PyQt5是两个版本的PyQt框架,具有以下区别: 1.PyQt6是PyQt的最新版本,而PyQt5是较旧的版本。PyQt6提供了更多的功能和改进,以提供更好的用户体验和开发体验。 2.PyQt6支持Python 3.10及更高版本,而PyQt5支持Python 3.5到3.9版本。 3.PyQt6对底层Qt库的版本要求更高,支持Qt 6及更高

    2024年02月07日
    浏览(44)
  • PyQt6中文手册

    最后更新于 2021.04.22 本教程是 PyQt6 的入门教程。本教程的目的是让您开始使用 PyQt6 库。 关于 PyQt6 PyQt6 Digia 公司的 Qt 程序的 Python 中间件。Qt库是最强大的GUI库之一。PyQt6的官网:www.riverbankcomputing.co.uk/news。PyQt6是由Riverbank Computing公司开发的。 Digia和RiverBank的关系不太清楚,

    2024年02月10日
    浏览(67)
  • 【pyqt6】用pyqt做一个点菜小程序

    在本文中,我们将使用 PyQt6(Python的GUI库)创建一个简单的点菜小程序。该程序允许用户从菜单中选择菜品,将其添加到订单中,并通过点击“下单”按钮查看订单的总价。 随着Python在不同领域的应用不断增加,开发GUI应用程序成为一项重要的技能。PyQt是一个强大的工具,

    2024年01月25日
    浏览(48)
  • 基于easyx和C++实现的鼠标交互界面(点击按钮)| 系统设计

    实现效果一览: 当鼠标放上去后效果: 代码实现及详解: 欢迎讨论!

    2024年04月27日
    浏览(47)
  • HTML+JS樱花飘落特效+鼠标点击特效

    目录:     效果: index.html 代码: yinghua.js 代码(图片为base64编码,可根据具体情况修改): shubiaodianji.js 代码:

    2024年02月11日
    浏览(60)
  • 【HTML+CSS+JavaScript】实现鼠标点击烟花效果

    本文主要讲解三种烟花效果(爆炸型、心型、圆形),文章末尾附有完整的代码和图片获取链接。 效果图(一) - 心型 : 效果图(二) - 圆型 : 效果图(三) - 爆炸型 : (1) HTML部分代码 (2) CSS部分代码 (3) 内部的JavaScript部分代码 (1) HTML部分代码 (2) CSS部分代码 (3) 内部的JavaScript部分

    2024年02月01日
    浏览(91)
  • pyqt6 + pycharm 搭建+使用入门

            最近要写代码给小白使用,但是让对方装python环境还要运行添加各种库,对小白太不友好了,所以选择了使用pyqt6+pycharm配合生成可视化python程序,在打包成exe执行。         首先安装PyQt6和PyQt6-tools。使用如下命令:        但是运行后会报如下错误:          这

    2024年02月10日
    浏览(44)
  • 全网最详细的鼠标点击效果与禁用页面缩小放大

    🌏 博客首页: 水香木鱼 📑 文章摘要: 鼠标点击效果   vue2 💌 春波寄语: 故木秀于林,风必摧之;堆出于岸,流必湍之;行高于人,众必非之。 在public的index.html 内 body 下 添加即可。 在public的index.html 内 body 下 添加即可。 在utils文件夹下创建 coreSocialistValues.js 文件,并

    2024年01月23日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包