Skip to content

[Bug]: Draggable legend with use_blit hides legend after legend picking #28129

Closed

Description

@dallas74

Bug summary

Using the legend picking example (https://matplotlib.org/stable/gallery/event_handling/legend_picking.html) and changing the next last line from leg.set_draggable(True) to leg.set_draggable(True, use_blit=True) then legend is not showing after picking it. Clicking again over its position makes it visible again.
Setting the legend draggable again (after being picked/clicked) with use_blit=False does not help.
Best regards, Daniel

Code for reproduction

# https://matplotlib.org/stable/gallery/event_handling/legend_picking.html

import matplotlib.pyplot as plt
import numpy as np

t = np.linspace(0, 1)
y1 = 2 * np.sin(2 * np.pi * t)
y2 = 4 * np.sin(2 * np.pi * 2 * t)

fig, ax = plt.subplots()
ax.set_title('Click on legend line to toggle line on/off')
(line1, ) = ax.plot(t, y1, lw=2, label='1 Hz')
(line2, ) = ax.plot(t, y2, lw=2, label='2 Hz')
leg = ax.legend(fancybox=True, shadow=True)

lines = [line1, line2]
map_legend_to_ax = {}  # Will map legend lines to original lines.

pickradius = 5  # Points (Pt). How close the click needs to be to trigger an event.

for legend_line, ax_line in zip(leg.get_lines(), lines):
    legend_line.set_picker(pickradius)  # Enable picking on the legend line.
    map_legend_to_ax[legend_line] = ax_line


def on_pick(event):
    # On the pick event, find the original line corresponding to the legend
    # proxy line, and toggle its visibility.
    legend_line = event.artist

    # Do nothing if the source of the event is not a legend line.
    if legend_line not in map_legend_to_ax:
        return

    ax_line = map_legend_to_ax[legend_line]
    visible = not ax_line.get_visible()
    ax_line.set_visible(visible)
    # Change the alpha on the line in the legend, so we can see what lines
    # have been toggled.
    legend_line.set_alpha(1.0 if visible else 0.2)
    fig.canvas.draw()


fig.canvas.mpl_connect('pick_event', on_pick)

# Works even if the legend is draggable. This is independent from picking legend lines.
leg.set_draggable(True, use_blit=True)

plt.show()

Actual outcome

The legend is not showing after picking it. Clicking again over its position makes it visible again.

Expected outcome

Legend is visible at all times.

Additional information

No response

Operating system

Windows

Matplotlib Version

3.8.1

Matplotlib Backend

TkAgg

Python version

3.9.7

Jupyter version

No response

Installation

pip

Activity

  1. tacaswell commented on May 22, 2024

    @tacaswell
    Member

    The issue is that when you click on the line there are two pick callbacks that run: yours and the on_pick from the DraggableOffsetbox. They both have a fig.canvas.draw() and the one in offsetbox sets the legend to be animated (which excludes it from the normal draw process so we can grab the background to re-draw on top of for blitting to work). Thus the sequence of events seems to be:

    • the offset box on_pick fires, makes the legend animated, re-draws, caches the background, draws the legend on top and blits to screen
    • your callback fires, changes the visible state of the main line, the alpha of your legend lined and re-draws
    • the second re-draw skips drawing the legend
    • the on_release callback in offset box makes the legend not-animated again
    • any future re-draws will "fix" everything (e.g. from resizing or clicking on the ghost legend)

    You can break the cycle by adding

       leg.set_animated(False)

    just above fig.canvas.draw() in your callback (and it is better to use fig.canvas.draw_idle() in your case). It will still do weird things if you click on the line and then drag (as the cached background the dragging code has includes your line being visible), but that is better than the legend disappearing!

    This is an unfortunate thing about the (low) level of abstraction we provide on top of blitting. Because it is all managed with local state it is really easy to have two things step on each others toes like this.

  2. changed the title [-]Draggable legend with use_blit hides legend after legend picking [Bug]: [/-] [+][Bug]: Draggable legend with use_blit hides legend after legend picking[/+] on Jun 5, 2026
  3. QuLogic commented on Jun 5, 2026

    @QuLogic
    Member

    This should have been fixed by #28271.

  4. added this to the v3.9.3 milestone on Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions