你如何增加 matplotlib Line2D 艺术家的 pickradius?

How do you increase the pickradius of a matplotlib Line2D artist?

我想创建一个情节,其中每个点都是可以挑选的个人艺术家。这是我目前的解决方案:

import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import \
    FigureCanvasQTAgg as FigureCanvas
import matplotlib.patheffects as PathEffects

from PyQt5.QtWidgets import QDialog, QApplication, QVBoxLayout


class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.fig, self.ax = plt.subplots()
        self.canvas = FigureCanvas(self.fig)

        a = [np.random.randint(100) for _ in range(100)]
        b = [np.random.randint(100) for _ in range(100)]
        self.artists = []
        self.last_artist = None
        for x, y in zip(a, b):
            artist = self.ax.plot(
                x, y, 'o', picker=True, pickradius=6, color='#ff4500'
            )
            self.artists += artist

        self.canvas.draw()

        self.cid_motion = self.fig.canvas.mpl_connect(
            'motion_notify_event', self.hover
        )

        layout = QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def hover(self, event):
        if event.inaxes == self.ax:
            ind = 0
            cont = None
            while (
                ind in range(len(self.artists))
                and not cont
            ):
                artist = self.artists[ind]
                cont, _ = artist.contains(event)
                if cont:
                    if artist is not self.last_artist:
                        if self.last_artist is not None:
                            self.last_artist.set_path_effects(
                                [PathEffects.Normal()]
                            )
                            self.last_artist.set_zorder(2)
                        artist.set_path_effects(
                            [PathEffects.withStroke(
                                linewidth=7, foreground="c", alpha=0.4
                            )]
                        )
                        artist.set_zorder(3)
                        self.last_artist = artist
                ind += 1

            if not cont and self.last_artist is not None:
                self.last_artist.set_path_effects([PathEffects.Normal()])
                self.last_artist.set_zorder(2)
                self.last_artist = None
            self.canvas.draw()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    GUI = MainWindow()
    GUI.show()
    sys.exit(app.exec_())

但是,如果您将 正好悬停在数据点的中心上方,突出显示 有效,如果您增加pickradius。所以我想也许我可以更改 contains 方法,但我不知道如何更改。我发现 matplotlib Artists 带有 set_contains method which you can use to come up with your own contains method. But I don't know how to do that. I was hoping I could learn from how the default contains method is implemented and looked at the source code,但不幸的是这并没有解释任何东西。

pickradius 结合 picker 作为 bool 应该实现你想要的。然而,它并没有这样做。另一方面,picker 如果定义了一个浮点数,则用作以点为单位的拾取半径。因此,直接将公差指定为 picker 可以使事情正常进行。更改以下行:

        artist = self.ax.plot(
            x, y, 'o', picker=True, pickradius=6, color='#ff4500'
        )

        artist = self.ax.plot(
            x, y, 'o', picker=6, color='#ff4500'
        )