【发布时间】:2020-10-13 22:56:45
【问题描述】:
请您,StackOverflow 的干瘪长老们,
我正在尝试使用 PyQt5 制作一个小型 GUI 应用程序,其中 matplotlib.FigureCanvas 对象用作小部件来显示数据,我还希望通过使用 matplotlib 的回调函数来使其更具交互性。但是,这些回调似乎不适用于 PyQt5 窗口中嵌入的 FigureCanvas。
我认为实例化 Qt5 应用程序可能会干扰 matplotlib 的事件处理程序,但我不确定如何继续。有没有办法让 matplotlib 事件引发 Qt5 信号?我可以有两个单独的线程,两个事件处理程序都可以在其中运行吗?
下面的例子是我能简化的最简单的例子,它说明了这个问题。
案例 A:在 Matplotlib 窗口中运行
首先按原样运行,注意所需的行为:onclick 函数在弹出时在图中单击时被调用。 (还要注意第二个代码块,案例 B 不会在第一个之后运行)
案例 B:在 PyQt5 中运行
现在,注释掉Case A代码块,运行:点击图中不调用回调函数。
import sys
import numpy as np
from PyQt5 import QtCore, QtWidgets, uic
import matplotlib
matplotlib.use('QT5Agg')
import matplotlib.pylab as plt
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
matplotlib.rcParams["toolbar"] = "toolmanager"
def onclick(event):
'''example callback function'''
print('got click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
( event.button, event.x, event.y, event.xdata, event.ydata))
class MPLWidget(QtWidgets.QWidget):
'''
Widget which should act like a matplotlib FigureCanvas, but embedded in PyQt5
'''
def __init__(self, parent=None, **kwargs):
super().__init__(parent, **kwargs)
# Making Matplotlib figure object with data
fig, ax = plt.subplots()
fig.suptitle("Plot in PyQt5: click and look in console")
ax.plot(np.linspace(0,1,2))
# Attaching matplotlib callback function which doesnt seem to work
cid = fig.canvas.mpl_connect('button_press_event', onclick)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0)
self.plotWidget = FigureCanvas(fig)
self.toolbar = NavigationToolbar(self.plotWidget, self)
self.layout.addWidget(self.toolbar)
self.layout.addWidget(self.plotWidget)
class TestWindow(QtWidgets.QMainWindow):
'''Window which is a stand in for the larger PyQt5 application which needs a plot embedded'''
def __init__(self):
super().__init__()
self.mplwidget = MPLWidget(self)
self.setCentralWidget(self.mplwidget)
if __name__ == '__main__':
# Case A: Using matplotlib without PyQt5,
# Note that the callback is triggered and something is printed when you click in the figure
fig, ax = plt.subplots()
fig.suptitle("Standalone matplotlib: click and look in console")
ax.plot(np.linspace(0,1,2))
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
# Case B: Running PyQt5 + Matplotlib widget
# Note that nothing is printed when you click in the figure
app = QtWidgets.QApplication(sys.argv)
window = TestWindow()
window.show()
sys.exit(app.exec_())
【问题讨论】:
标签: python matplotlib pyqt5