1

I have created this very simple code that generates a message depending if I single or double click on a bar on a barplot.

What I don't understand is why it works for the first two times and the third time that click anywhere it generates an error.

It doesn't matter where I click, if it's left or right and so on. It's always the third time. I would be glad to understand why this happens.

The error that I get is

canvas = property(lambda self: self.ref_artist.figure.canvas)

AttributeError: 'NoneType' object has no attribute 'canvas'

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import mplcursors

# create tkinter app window
root = tk.Tk()
root.title("Barplot with Cursor")

# create Figure object in matplotlib
fig, ax = plt.subplots()


# add data to the plot
data = [5, 10, 15, 20, 25]
ax.bar(range(len(data)), data)

# embed plot into tkinter app using FigureCanvasTkAgg
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

# class to keep track of latest event
class LatestEvent:
    def __init__(self):
        self.event = None

    def update(self, event):
        self.event = event

    def get(self):
        return self.event

latest_event = LatestEvent()

# function to handle selection event
def on_select(sel):
    print(f"Selected region: ({sel.target[0]:.2f}, {sel.target[1]:.2f})")

# function to handle left-click event
def on_left_click(event):
    if event.dblclick:
        print('Left double')
    else:
        print('Left single')


# bind left-click events to on_left_click function
def left_click_handler(event):
    latest_event.update(event)
    root.after(300, on_left_click_wrapper)

def on_left_click_wrapper():
    event = latest_event.get()
    if event:
        on_left_click(event)
        latest_event.update(None)

canvas.mpl_connect("button_press_event", lambda event: left_click_handler(event) if event.button == 1 else None)

# function to handle right-click event
def on_right_click(event):
    if event.button == 3:
        if event.dblclick:
            print("Right double-click message")
        else:
            print("Right single-click message")


# bind right-click events to on_right_click function
canvas.mpl_connect("button_press_event", lambda event: on_right_click(event) if event.button in (1,3) else None)

# bind left-click events to on_select function
c = mplcursors.cursor(ax, hover=False)
c.connect("add", lambda sel: on_select(sel))

# start tkinter mainloop
root.mainloop()

1 Answers1

0

It's a bug of Matplotlib. See the issue#25440 for details.

For now, you can downgrade to the 3.7.0 version like this.

$ pip3 install matplotlib==3.7.0
relent95
  • 3,703
  • 1
  • 14
  • 17