'Python Kivy: adding a FigureCanvas widget through a custom event

I am new to Kivy and GUIs in general and I am having a hard time understanding some simple concepts of Kivy callbacks logic. I want to make a simple app to read a CSV and plot a graph from it, so I want the widget that opens the file to trigger a function that adds a FigureCanvaKivyAgg widget that shows the figure.

On my source code I disabled the plotting from the CSV readed as it does not add to the issue at hand. You will see that I tried different ways to trigger the callback, but I only accomplish to trigger the custom event, it does not communicate with the callback nor add the FigureCanva Widget to the Layout.

import pandas as pd
import matplotlib.pyplot as plt
 
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
 
from kivy.uix.button import Button
from kivy.uix.filechooser import FileChooserIconView
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg

 
from shark_plot import shark_plot

import os
 

csv = {'x':[1,2,3,4,5,6],'y':[2,4,6,8,6,12]}

class MyWidget(BoxLayout):
 
    def __init__(self, **kwargs):
        super(MyWidget, self).__init__(**kwargs)
        self.register_event_type('on_event')
 
        container = BoxLayout(orientation='vertical')
        
 
        filechooser = FileChooserIconView()
    
        filechooser.bind(on_selection=lambda x: self.selected(filechooser.selection))
        print(filechooser.selection,filechooser.path)
 
        open_btn = Button(text='open', size_hint=(1, .2))
        open_btn.bind(on_release=lambda x: self.open(filechooser.path, filechooser.selection))

        box = BoxLayout(size_hint=(1, .5))

        box.bind(on_event= self.action)
        
        # if len(filechooser.path[0])>0:
        #     # box.add_widget(FigureCanvasKivyAgg(plt.gcf()))
 
        container.add_widget(filechooser)
        container.add_widget(open_btn)
        container.add_widget(box)
        self.add_widget(container)
 
    def on_event(self):
        print("Event triggered?")
        plt.show()
        canva = (FigureCanvasKivyAgg(plt.gcf()))
        return canva

    def action(self):
        print('Action executed??')
        canva = (FigureCanvasKivyAgg(plt.gcf()))
        self.cb.ask_update()
        return canva
    
    def open(self, path, filename):
        print(filename)
        if len(filename) > 0:
            selected_path = os.path.join(path, filename[0])
            print(selected_path)
            df=pd.read_csv(selected_path)
            # fig = shark_plot(df)
            fig = plt.plot(csv['x'],csv['y'])
            g=self.dispatch('on_event')
            
            print(type(df))
            # print(f.read())
        return fig
 
    def selected(self, filename):
        print("selected: %s" % filename[0])
 
def on_event_callback():
        print("Action Triggered??")
        canva = (FigureCanvasKivyAgg(plt.gcf()))
        subbox = BoxLayout()
        subbox.add_widget(canva)
        return subbox


class MyApp(App):
    def build(self):
        return MyWidget()
 
 
if __name__ == '__main__':
    MyApp().run()

Hope that the question is clear, it is my first time making such here :)

Please reach out for any clarifications.



Solution 1:[1]

on_event() will run via the dispatch() statement, but there is no connection from on_event() to the add_widget() statement in on_event_callback(), so that never happens. You can either put add_widget() directly in on_event(), or, if you want a separate function, then call it directly from open() without using the kivy register and dispatch().

    def on_event(self):
        canva = FigureCanvasKivyAgg(plt.gcf())
        self.add_widget(canva)

    def on_event_callback(self,canva):
        self.add_widget(canva)

    def open(self, path, filename):
        # open data files here etc to load self.csv
        plt.plot(self.csv['x'],self.csv['y'])
        self.dispatch('on_event')
        canva2 = FigureCanvasKivyAgg(plt.gcf())
        self.on_event_callback(canva2)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 J B