You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义或禁用PyQt5中嵌入的离线Plotly图表右键菜单?

解决方案

你可以通过两种路径实现需求,无需修改Plotly原生配置,直接通过PyQt5或注入JS即可实现:

方案1:直接禁用右键菜单(2种可选实现)

实现1:修改QWebEngineView上下文菜单属性

这是最简单的方案,仅需添加1行代码即可禁用默认右键菜单:

  1. 首先导入Qt常量:from PyQt5.QtCore import Qt
  2. 创建QWebEngineView实例后添加配置:
plot_widget = QWebEngineView()
plot_widget.setContextMenuPolicy(Qt.NoContextMenu) # 新增这行即可禁用右键

实现2:HTML注入JS禁用右键

如果需要让生成的HTML本身就不响应右键,脱离Qt环境也生效,可以在拼接HTML代码时加入禁用右键的JS逻辑:

html = '<html><body>'
# 新增以下JS代码
html += '<script>document.addEventListener("contextmenu", e => e.preventDefault())</script>'
html += plotly.offline.plot(fig, output_type='div', include_plotlyjs='cdn')
html += '</body></html>'

方案2:自定义右键菜单

如果需要添加专属操作,可以继承QWebEngineView重写右键菜单事件,自定义菜单项和触发逻辑,示例代码如下:

from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QAction
from PyQt5.QtCore import Qt
import plotly.graph_objects as go
import plotly
import numpy as np

# 自定义带专属右键菜单的WebView组件
class PlotWebView(QWebEngineView):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def contextMenuEvent(self, event):
        # 构建自定义菜单
        custom_menu = QMenu(self)
        # 添加自定义操作项
        export_png_action = QAction("导出为PNG图片", self)
        export_png_action.triggered.connect(self.export_plot_png)
        reset_view_action = QAction("重置图表视图", self)
        reset_view_action.triggered.connect(self.reset_plot_view)
        
        custom_menu.addAction(export_png_action)
        custom_menu.addAction(reset_view_action)
        # 在鼠标点击位置弹出菜单
        custom_menu.exec_(event.globalPos())
    
    def export_plot_png(self):
        # 调用Plotly原生JS方法实现导出
        self.page().runJavaScript("""
            const plot = document.querySelector('.js-plotly-plot');
            Plotly.downloadImage(plot, {format: 'png', filename: '我的图表', width: 1200, height: 800});
        """)
    
    def reset_plot_view(self):
        # 调用Plotly原生JS方法重置视图
        self.page().runJavaScript("""
            const plot = document.querySelector('.js-plotly-plot');
            Plotly.relayout(plot, {xaxis: {autorange: true}, yaxis: {autorange: true}});
        """)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        x = np.arange(1000)
        y = x**2
        fig = go.Figure(go.Scatter(x=x, y=y))
        html = '<html><body>'
        html += plotly.offline.plot(fig, output_type='div', include_plotlyjs='cdn')
        html += '</body></html>'
        # 使用自定义的PlotWebView
        plot_widget = PlotWebView()
        plot_widget.setHtml(html)
        self.setCentralWidget(plot_widget)

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

以上两种方案都可以满足需求,不会影响Plotly原有的缩放、平移等左键交互功能。

内容的提问来源于stack exchange,提问作者Victor Y.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:48:03