'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 |