Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Description
Bug summary
I recently managed to find the source of a long-standing bug in my application that was quite tricky to find.
It turned out to be a consequence of thecontains
method of a line returningtrue
even when the line was set to not visible at the time. Although from what I can see in the documentation there is nothing prohibiting this, I think almost everyone would wantcontains
to return false for objects which have been plotted and set to invisible.
Moreover, a non-exhaustive look through the code shows that there are class-specific checks in place for visibility for some objects, but not others. Specifically, the following do not have checks:
lines.Line2Dpatches.Patchquiver.QuiverKey
But these ones do (though not explicitly documented.)
collections.Collectiontext.Textimage.BboxImage
It seems like a fix might put the check for visibility in the_default_contains
method ofArtist
. This is called by the child implementations, but as of now seems to provide only a bail-out if the event is outside the figure canvas. Although I guess maybe it was done that way if there are some specific exceptions where you would actually wantcontains
to return true (maybe bounding boxes or more abstract things not plotted directly).
Code for reproduction
frommatplotlibimportpyplotaspltclassDemo:def__init__(self):fig,ax=plt.subplots()self.lines= []self.lines.append(ax.axhline(1))self.lines.append(ax.axhline(-1))self.lines[0].set_visible(False)self.vis_points=ax.scatter([-0.5,0.5], [0,0])self.invis_points=ax.scatter([0], [0])self.invis_points.set_visible(False)self.points= [self.vis_points,self.invis_points]fig.canvas.mpl_connect('button_press_event',self.clicked)plt.show()defclicked(self,event):at_obj=lambdax:x.contains(event)[0]ifany(at_obj(l)forlinself.lines):print(f"Clicked on a line at{event.ydata:0.3f}")elifany(at_obj(p)forpinself.points):print(f"Clicked point at{event.ydata:0.3f}")else:print('Clicked elsewhere')if__name__=='__main__':demo=Demo()
Actual outcome
It is possible to click anywhere near the invisible line at y=1 and see click registered message.
However, clicking at [0,0], the location of an invisible scatter point does not show a point clicked message (expected behavior).
Expected outcome
Clicking anywhere y=1 should not generate a line click message --- just as clicking at 0,0 does not generate a point clicked message.
Additional information
No response
Operating system
Arch linux, Linux mint, Windows
Matplotlib Version
3.5.0
Matplotlib Backend
qt
Python version
3.9.9
Jupyter version
No response
Installation
No response