Skip to content

Advanced legend

This section show how to create interactive legend for these cases:

  • Twinx figure
  • 2 legends in same axis
  • group legend

advanced_legend example

Example

based on 'example_advance_interactive_legend' example

from kivy.utils import platform
from kivy.config import Config

#avoid conflict between mouse provider and touch (very important with touch device)
#no need for android platform
if platform != 'android':
    Config.set('input', 'mouse', 'mouse,disable_on_activity')
else:
    #for android, we remove mouse input to not get extra touch 
    Config.remove_option('input', 'mouse')

from kivy.lang import Builder
from kivy.app import App

import matplotlib.pyplot as plt

from kivy_matplotlib_widget.uix.legend_widget import MatplotlibInteractiveLegend  #also register all widgets to kivy register


KV = '''
BoxLayout:

    orientation:'vertical'
    BoxLayout:
        size_hint_y:0.2
        Button:
            text:"home"
            on_release:app.home()

        ToggleButton:
            group:'touch_mode'
            state:'down'
            text:"pan" 
            on_release:
                app.set_touch_mode('pan')
                self.state='down'    
        ToggleButton:
            group:'touch_mode'
            text: 'ZoomBox'
            on_press: 
                app.set_touch_mode('zoombox')
                self.state='down'
        ToggleButton:
            group:'touch_mode'
            text:"drag legend"  
            on_release:
                app.set_touch_mode('drag_legend')
                self.state='down'                  

    BoxLayout: 
        ScreenManager:
            id:sm
            Screen1:
            Screen2:
            Screen3:

    BoxLayout:
        size_hint_y:0.1
        Button:
            text:"previous screen"
            on_release:app.previous_screen()
        Button:
            text:"next screen"
            on_release:app.next_screen()

<Screen1@Screen>
    name:'screen1'  
    figure_wgt:figure_wgt                  
    MatplotFigureSubplot:
        id:figure_wgt
        fast_draw:True
        interactive_axis:True

<Screen2@Screen> 
    name:'screen2'  
    figure_wgt:figure_wgt                  
    MatplotFigureSubplot:
        id:figure_wgt
        fast_draw:True
        interactive_axis:True
        draw_all_axes:True

<Screen3@Screen> 
    name:'screen3'  
    figure_wgt:figure_wgt                  
    MatplotFigureSubplot:
        id:figure_wgt
        fast_draw:True
        interactive_axis:True
        draw_all_axes:True

'''

class Test(App):
    def build(self):
        self.graph_app = Builder.load_string(KV)
        return self.graph_app

    def on_start(self, *args):

# =============================================================================
#         figure 1 - screen1 - example with twin axis
# =============================================================================
        fig, ax1 = plt.subplots(1, 1)

        plt.title('Twin axis legend')

        ax1.plot([0,1,2,3,4], [1,2,8,9,4],label='line1')
        ax1.scatter([2,8,10,15], [15,0,2,4],label='line2')
        ax2=ax1.twinx()
        ax2.plot([2,8,10,15], [15,0,2,4],c='r',label='line3')

        lines, labels = ax1.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        leg=ax2.legend(lines + lines2, labels + labels2, loc=4)

        screen1=self.graph_app.ids.sm.get_screen('screen1')
        screen1.figure_wgt.figure = fig

        MatplotlibInteractiveLegend(screen1.figure_wgt,
                                    legend_instance=leg)
# =============================================================================
#         figure 2 - screen2 - example with 2 legends in same axis
# =============================================================================
        fig2, ax3 = plt.subplots()
        plt.title('2 legends in same axis')

        line1, = ax3.plot([1, 2, 3], label="Line 1", linestyle='--')
        line2, = ax3.plot([3, 2, 1], label="Line 2", linewidth=4)

        # Create a legend for the first line.
        first_legend = ax3.legend(handles=[line1], loc='upper right')

        # Add the legend manually to the Axes.
        ax3.add_artist(first_legend)

        # Create another legend for the second line.
        second_legend = ax3.legend(handles=[line2], loc='lower right')

        screen2=self.graph_app.ids.sm.get_screen('screen2')
        screen2.figure_wgt.figure = fig2

        MatplotlibInteractiveLegend(screen2.figure_wgt,
                                    legend_instance=first_legend,
                                    custom_handlers=[line1])

        MatplotlibInteractiveLegend(screen2.figure_wgt,
                                    legend_instance=second_legend,
                                    custom_handlers=[line2],multi_legend=True)  

# =============================================================================
#         figure 3 - screen3 - group legend
# =============================================================================

        # create all axes we need
        fig3, ax4 = plt.subplots()
        plt.title('Group legend')

        line1, = ax4.plot([1, 2, 3], c='b', label="Line 1", linestyle='--')
        line2, = ax4.plot([3, 2, 1], c='b', label="Line 2", linewidth=4)
        line3, = ax4.plot([2, 3, 4], c='b', label="Line 3", linestyle='--')

        line4, = ax4.plot([0.5,1, 6], c='r', label="Line 4", linestyle='--')
        line5, = ax4.plot([2, 4.5, 5.5], c='r',label="Line 5", linewidth=4)

        import matplotlib.patches as mpatches
        blue_patch = mpatches.Patch(color='blue', label='The bue data')
        red_patch = mpatches.Patch(color='red', label='The red data')

        # Create a legend 
        leg3 = ax4.legend(handles=[blue_patch,red_patch],labels=['blue','red'], loc='upper right')

        screen3=self.graph_app.ids.sm.get_screen('screen3')
        screen3.figure_wgt.figure = fig3

        MatplotlibInteractiveLegend(screen3.figure_wgt,
                                    legend_instance=leg3,
                                    custom_handlers=[[line1,line2,line3],[line4,line5]])

    def set_touch_mode(self,mode):
        for screen in self.graph_app.ids.sm.screens:
            if hasattr(screen,'figure_wgt'):
                screen.figure_wgt.touch_mode=mode

    def home(self):
        screen=self.graph_app.ids.sm.current_screen
        screen.figure_wgt.main_home()

    def previous_screen(self):
        screen_name=self.graph_app.ids.sm.current
        screen_number = int(screen_name[-1])
        if screen_number<=1:
            screen_number=3
        else:
            screen_number-=1

        self.graph_app.ids.sm.current = 'screen' + str(screen_number)        

    def next_screen(self):
        screen_name=self.graph_app.ids.sm.current
        screen_number = int(screen_name[-1])
        if screen_number>=3:
            screen_number=1
        else:
            screen_number+=1

        self.graph_app.ids.sm.current = 'screen' + str(screen_number)


Test().run()