QWebEngineView中Plotly图表无法同步的问题求助
解决PyQt5中QWebEngineView嵌入Plotly图表无法同步缩放/平移的问题
问题描述
将实现Plotly多图表同步缩放/平移的HTML代码,放入PyQt5的三个独立QWebEngineView组件后,图表的平移或缩放操作完全没有同步效果,但单独运行该HTML文件时功能正常。已尝试更新Plotly、QWebEngineView及清除缓存,均无效。
问题根源
每个QWebEngineView都对应一个独立的浏览器JavaScript运行环境,三个视图之间的JS上下文完全隔离。原代码中监听的plotly_relayout事件只能在当前视图内部生效,无法跨视图传递同步信号,因此三个图表无法联动。
解决方案
使用单个QWebEngineView加载包含三个图表的HTML页面,让所有图表处于同一个JS运行环境中,这样事件监听和同步逻辑就能正常工作。
修正后的代码
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget from PyQt5.QtWebEngineWidgets import QWebEngineView class SynchronizedPlotWindow(QMainWindow): def __init__(self): super().__init__() # 只使用一个Web视图加载包含三个图表的页面 self.graph_view = QWebEngineView() # 加载包含同步图表的HTML内容 html_content = """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Plotly Synchronized Charts</title> <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> </head> <body> <h2>Resize any chart, the others will get the same zoom level applied</h2> <div id="myDiv"></div> <div id="myDiv2"></div> <div id="myDiv3"></div> <script> var myDiv = document.getElementById("myDiv"); var myDiv2 = document.getElementById("myDiv2"); var myDiv3 = document.getElementById("myDiv3"); var startTime = new Date().getTime(); var timeStep = 60000; var myDivMax = 70; var myDiv2Max = 9000; var myDiv3Max = 500; var d3 = Plotly.d3, N = 40, x = d3.range(N).map(() => { return new Date((startTime += timeStep)); }), y = d3.range(N).map(() => Math.random() * myDivMax), data = [{ x: x, y: y }]; var layout = { height: 200, margin: { l: 45, t: 5, r: 45, b: 45 }, xaxis: { tickfont: { size: 10, color: "#7f7f7f" } }, yaxis: { fixedrange: true, tickfont: { size: 10, color: "#7f7f7f" } } }; var layout2 = { height: 200, margin: { l: 45, t: 5, r: 45, b: 45 }, xaxis: { tickfont: { size: 10, color: "#7f7f7f" } }, yaxis: { fixedrange: true, tickfont: { size: 10, color: "#7f7f7f" } } }; var layout3 = { height: 200, margin: { l: 45, t: 5, r: 45, b: 45 }, xaxis: { tickfont: { size: 10, color: "#7f7f7f" } }, yaxis: { fixedrange: true, tickfont: { size: 10, color: "#7f7f7f" } } }; Plotly.plot(myDiv, data, layout); var data2 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv2Max) }]; Plotly.plot(myDiv2, data2, layout2); var data3 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv3Max) }]; Plotly.plot(myDiv3, data3, layout3); var divs = [myDiv, myDiv2, myDiv3]; function relayout(ed, divs) { if (Object.entries(ed).length === 0) {return;} divs.forEach((div, i) => { let x = div.layout.xaxis; if (ed["xaxis.autorange"] && x.autorange) return; if (x.range[0] != ed["xaxis.range[0]"] ||x.range[1] != ed["xaxis.range[1]"]) { var update = { 'xaxis.range[0]': ed["xaxis.range[0]"], 'xaxis.range[1]': ed["xaxis.range[1]"], 'xaxis.autorange': ed["xaxis.autorange"], }; Plotly.relayout(div, update); } }); } var plots = [myDiv, myDiv2, myDiv3]; plots.forEach(div => { div.on("plotly_relayout", function(ed) { relayout(ed, divs); }); }); </script> </body> </html> """ self.graph_view.setHtml(html_content) # 布局设置 layout = QVBoxLayout() layout.addWidget(self.graph_view) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) if __name__ == "__main__": app = QApplication(sys.argv) window = SynchronizedPlotWindow() window.show() sys.exit(app.exec_())
内容的提问来源于stack exchange,提问作者Diego Alexis
相关产品推荐
相关产品推荐

