.contains 方法适用于 matplotlib 3.4.3 和 python 3.8.19 不再适用于更新的环境。
该方法返回一个布尔值和字典。 即使鼠标悬停在数据点上,它也始终返回 False 和空字典。
使用 matplotlib 版本 3.4.3 和 python 版本 3.8.19 迁移回原始环境,以确认问题是由环境更新引起的。
查找相关帖子并挖掘 matplotlib 库以尝试排除故障。终于找到了创建注释的替代方法,但我想知道为什么 .contains 方法不再起作用。
最小工作示例:
import sys
import numpy
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import \
FigureCanvasQTAgg as FigureCanvas
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QVBoxLayout,
QWidget,
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Live Charts")
self.statusbar = self.statusBar()
self.setCentralWidget(GraphWidget())
class GraphWidget(QWidget):
def __init__(self):
super().__init__()
self.prev_ind = None
self.canvas = FigureCanvas()
vertical_layout = QVBoxLayout(self)
vertical_layout.addWidget(self.canvas)
self.fig = plt.figure(figsize=(4, 4), dpi=100)
self.fig.set_tight_layout(True)
self.ax = self.fig.add_subplot()
self.canvas.figure = self.fig
x = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
y = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
self.sc = self.ax.scatter(x,
y,
edgecolors='Midnightblue',
color='cornflowerblue')
self.annot = self.ax.annotate("", (x, y),
annotation_clip=True,
size=7, textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
self.annot.set_visible(False)
self.fig.canvas.mpl_connect("motion_notify_event", self.hover)
self.canvas.draw()
def hover(self, event):
vis = self.annot.get_visible()
if event.inaxes == self.ax:
print("event: " + str(event))
self.cont, self.ind = self.sc.contains(event)
print("self.ind: " + str(self.ind))
print("self.cont: " + str(self.cont))
if self.cont:
self.update_annot(self.ind)
self.annot.set_visible(True)
self.prev_ind = self.ind
self.canvas.draw()
else:
if vis:
self.annot.set_visible(False)
self.prev_ind = None
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.showMaximized()
window.activateWindow()
sys.exit(app.exec())
问题似乎出在我构建图表/类的方式上。
这篇文章有帮助:如何在 pyqt5 中使 matplotlib 绘图具有交互性
import sys
import numpy as np
from matplotlib.backends.backend_qt5agg import \
FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QVBoxLayout,
QWidget,
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Live Charts")
self.statusbar = self.statusBar()
self.setCentralWidget(GraphWidget())
class GraphWidget(FigureCanvas):
def __init__(self):
fig = Figure()
super(GraphWidget, self).__init__(fig)
self.prev_ind = None
vertical_layout = QVBoxLayout(self)
vertical_layout.addWidget(self)
self.x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
self.y = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
self.ax = self.figure.add_subplot()
self.ax.scatter(self.x, self.y)
self.annot = self.ax.annotate("", (self.x, self.y),
annotation_clip=True,
size=7, textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
self.annot.set_visible(False)
fig.canvas.mpl_connect("motion_notify_event", self.hover)
self.draw()
def hover(self, event):
vis = self.annot.get_visible()
if event.inaxes == self.ax:
self.cont, self.ind = self.ax.collections[0].contains(event)
print("self.ind: " + str(self.ind))
print("self.cont: " + str(self.cont))
if (self.prev_ind is None or self.ind.values()
!= self.prev_ind.values()):
self.x_data = event.xdata
self.y_data = event.ydata
if self.cont:
self.update_annot(self.ind)
self.annot.set_visible(True)
self.prev_ind = self.ind
self.draw()
else:
if vis:
self.annot.set_visible(False)
self.prev_ind = None
self.draw()
else:
pass