如何自定义或禁用PyQt5中嵌入的离线Plotly图表右键菜单?
解决方案
你可以通过两种路径实现需求,无需修改Plotly原生配置,直接通过PyQt5或注入JS即可实现:
方案1:直接禁用右键菜单(2种可选实现)
实现1:修改QWebEngineView上下文菜单属性
这是最简单的方案,仅需添加1行代码即可禁用默认右键菜单:
- 首先导入Qt常量:
from PyQt5.QtCore import Qt - 创建
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.
相关产品推荐
相关产品推荐

