0

I have a matplotlib figure embedded in a tkinter application and I attached a custom toolbar to it. Here is the code of the toolbar:

class CustomToolbar(NavigationToolbar2Tk):

    def __init__(self, canvas_, parent_, background_color):

        self.toolitems = (
            ('Home', 'Réinitialiser la vue', 'home', 'home'),
            ('Back', 'Retour à la vue précédente', 'back', 'back'),
            ('Forward', 'Avancer à la vue suivante', 'forward', 'forward'),
            (None, None, None, None),
            ('Pan', 'Clic gauche : Déplacer le graphe\nClic droit: Dilater/compresser les axes', 'move', 'pan'),
            ('Zoom', 'Zoomer', 'zoom_to_rect', 'zoom'),
            (None, None, None, None)
        )

        super().__init__(canvas_, parent_)

        self.background_color = background_color
        self.configure(bg=self.background_color)
        self.get_message_label().config(background=self.background_color)
        self.update()

    def get_message_label(self):
        return self._message_label

    def pan(self):
        super().pan(self)
        self.mode = "Déplacer/Dilater"
        self.set_message(self.mode)

    def zoom(self):
        super().zoom(self)
        self.mode = "Zoomer"
        self.set_message(self.mode)

I redefine a pan and zoom method in order to set a new mode when the pan or zoom buttons are active, and I do so because I want to change the text appearing in _message_label. I did as indicated by the answer to this question: Matplotlib/Tkinter - customizing toolbar tooltips.

However, this solution doesn't seem to work in 2020 because modes are predefined in the _Mode class in matplotlib.backend_bases as class members:

class _Mode(str, Enum):
    NONE = ""
    PAN = "pan/zoom"
    ZOOM = "zoom rect"

    def __str__(self):
        return self.value

    @property
    def _navigate_mode(self):
        return self.name if self is not _Mode.NONE else None

I tried to change the class members PAN and ZOOM in my script but the __setattr__ method of the Enum class won't let me:

    def __setattr__(cls, name, value):
        """Block attempts to reassign Enum members.

        A simple assignment to the class namespace only changes one of the
        several possible ways to get an Enum member from the Enum class,
        resulting in an inconsistent Enumeration.

        """
        member_map = cls.__dict__.get('_member_map_', {})
        if name in member_map:
            raise AttributeError('Cannot reassign members.')
        super().__setattr__(name, value)

So is it possible to simply change the class members PAN and ZOOM without messing with the matplotlib.backend_bases.py file ?

Thank you for your time,

Paul

Pauuuuuuul
  • 253
  • 3
  • 12

1 Answers1

0

Ok so i found a solution, it seems to work when wrapping the set_message of the NavigationToolbar2Tk class like so:

    def set_message(self, s):
        if s == "pan/zoom":
            self.message.set("Déplacer/Dilater")

        elif s == "zoom rect":
            self.message.set("Zoomer")

This solution was indicated in the post I mentionned in the question but I guess I simply did not saw it.

Pauuuuuuul
  • 253
  • 3
  • 12