Starting to learn Kivy and can not update the graph on the button. Ideally, in the future, data should come from outside and be added to the graph without pressing any keys.Tried to use Clock.schedule_interval but it didn't work.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
import matplotlib.pyplot as plt
from kivy.clock import Clock
x=2
y=4
lst=[x,y]
plt.ylabel('some numbers')
class MainApp(App):
def update(self):
Clock.schedule_interval(self.plot,1)
def on_press_button(self, instance):
for i in range(20):
global y
global x
global lst
x=x*2
y=y*2
lst.append(x)
lst.append(y)
print(lst)
return MainApp.build(self)
print('Button pressed!')
def build(self):
plt.cla()
plt.plot(lst)
plt.ylabel('some numbers')
main_layout = BoxLayout(orientation='horizontal')
grid_layout=GridLayout(cols=1,
row_force_default=True,
row_default_height=100,
size_hint=(.2,1)
)
main_layout.add_widget(grid_layout)
grid_layout.add_widget(Label(text='Hello from Kivy'))
button1=grid_layout.add_widget(Button(text='Hello 1', on_press=self.on_press_button))
main_layout.add_widget(FigureCanvasKivyAgg(plt.gcf(), size_hint=(.8,1)))
print ('build called')
return main_layout
if __name__ == '__main__':
app = MainApp()
app.run()
The build()
method of an App
is called automatically when you call the run()
method of the App
, and the widget returned by build()
is set as the root
widget of the App
. If you call that same build()
method directly, it does not affect the root
widget of the App
.
One way to accomplish what you want is to create a new method that does the plotting and returns an instance of FigureCanvasKivyAgg
. This new method can be called inside the build()
method, and can also be called in the on_press_button()
method and the returned FigureCanvasKivyAgg
can then be used to replace the original. Here is a modified version of your code that does that:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
import matplotlib.pyplot as plt
x = 2
y = 4
lst = [x, y]
plt.ylabel('some numbers')
class MainApp(App):
def build_plt(self):
plt.cla()
plt.plot(lst)
plt.ylabel('some numbers')
return FigureCanvasKivyAgg(plt.gcf(), size_hint=(.8,1))
def on_press_button(self, instance):
for i in range(20):
global y
global x
global lst
x = x * 2
y = y * 2
lst.append(x)
lst.append(y)
print(lst)
# return MainApp.build(self)
self.root.remove_widget(self.fcka) # remove the current plot
self.fcka = self.build_plt() # create the updated plot
self.root.add_widget(self.fcka) # insert the new plot
print('Button pressed!')
def build(self):
main_layout = BoxLayout(orientation='horizontal')
grid_layout=GridLayout(cols=1,
row_force_default=True,
row_default_height=100,
size_hint=(.2,1)
)
main_layout.add_widget(grid_layout)
grid_layout.add_widget(Label(text='Hello from Kivy'))
button1=grid_layout.add_widget(Button(text='Hello 1', on_press=self.on_press_button))
self.fcka = self.build_plt()
main_layout.add_widget(self.fcka)
print ('build called')
return main_layout
if __name__ == '__main__':
app = MainApp()
app.run()