amrsa
amrsa

Reputation: 245

How to toggle legend on and off together with respective lines

With the following code I can toggle the lines on a chart on and off by clicking a check-button.
However, the legend keeps on all the time for both series.
I wanted the legend of one series to disappear whenever the series does.
Notice that I don't want something like this. Here the user clicks on the legend to toggle both the series on and off and when the series in turned off, the alpha of the line of its legend graph is changed to became almost transparent.
What I wanted was (by an event exterior to the chart itself) both the line series to hide and the corresponding entry in the legend to disappear, and then coming back into existence again with another toggling.

Here's the code:

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


class App(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.btn = tk.Label(parent, text='A simple plot')
        self.btn.grid(row=0, column=0, padx=20, pady=10)

        self.lfr = tk.LabelFrame(parent)
        self.lfr.grid(row=1, column=0)

        self.var_y = tk.IntVar()
        self.var_z = tk.IntVar()
        self.check_y = tk.Checkbutton(self.lfr, text="Chart of y", variable=self.var_y, command=self.checkbutton_changed)
        self.check_z = tk.Checkbutton(self.lfr, text="Chart of z", variable=self.var_z, command=self.checkbutton_changed)
        self.check_y.grid(column=0, row=1)
        self.check_z.grid(column=1, row=1)

        self.check_y.select()
        self.check_z.select()

        self.x = range(1, 11)
        self.y = [1, 2, 3, 2, 1, 3, 4, 5, 5, 5]
        self.z = [3, 1, 1, 3, 4, 5, 3, 2, 2, 2]

        fig = plt.figure(figsize=(8, 5))
        self.ax = fig.add_subplot(111)

        self.plot_y = self.ax.plot(self.x, self.y, label="data y")[0]
        self.plot_z = self.ax.plot(self.x, self.z, label="data z")[0]

        self.plot_y.set_visible(self.var_y.get())
        self.plot_z.set_visible(self.var_z.get())

        plt.legend()
        plt.gca().invert_yaxis()

        plt.xticks(self.x, rotation=60)

        self.canvas = FigureCanvasTkAgg(fig, master=parent)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(row=2, column=0, ipadx=40, ipady=20)

    def checkbutton_changed(self):
        self.plot_y.set_visible(self.var_y.get())
        self.plot_z.set_visible(self.var_z.get())

        self.ax.figure.canvas.draw()


if __name__ == '__main__':
    root = tk.Tk()
    App(root)
    root.mainloop()


I suppose I should do with the legend something similar with what I did with the series (making them class variables, so that I can later use them in the method that commands the checkbuttons), but I can't see what exactly...

Other improvements would also be appreciated.
Thanks in advance

Upvotes: 0

Views: 1099

Answers (1)

Ynjxsjmh
Ynjxsjmh

Reputation: 30050

Update matplotlib.pyplot.legend() with handles and labels in each toggle.

    def checkbutton_changed(self):
        print('---')
        self.plot_y.set_visible(self.var_y.get())
        self.plot_z.set_visible(self.var_z.get())

        handles = []
        labels = []

        if self.var_y.get():
            handles.append(self.plot_y)
            labels.append('data y')

        if self.var_z.get():
            handles.append(self.plot_z)
            labels.append('data z')

        plt.legend(handles, labels)

        self.ax.figure.canvas.draw()

Upvotes: 1

Related Questions