Matplotlib using kv language
Date: March 4th 2016
Last updated: March 4th 2016
Using the kv language to include a plot inside a widget was an absolute nightmare. It has taken me a number of days to get working. I had a breakthrough when I read this: https://mail.python.org/pipermail//matplotlib-users/2015-November/000168.html. The missing ingredient for me to convert my previous example to kv language was this: self.add_widget(canvas). In my original example, I included add_widget(canvas) in the build function. I was confused how I was going to translate this code into syntax that could be understood by the kv language. There is more information in main.py regarding this syntax.
main.py
# Import modules
import matplotlib
matplotlib.use('module://kivy.garden.matplotlib.backend_kivy')
import matplotlib.pyplot as plt
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvas
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
import matplotlib.mlab as mlab
from random import gauss
import numpy as np
class DrawPlot(BoxLayout):
def __init__(self, **kwargs):
super(DrawPlot, self).__init__(**kwargs)
def draw_my_plot(self):
fig, ax = plt.subplots()
x = [gauss(100, 15) for i in range(100)]
n, bins, patches = ax.hist(x, 50, normed=1, facecolor='white', alpha=0.3)
pdf = mlab.normpdf(bins, 100, 15)
ax.plot(bins, pdf, 'r-', linewidth=2)
ax.set_xlim([0, 200])
canvas = FigureCanvas(figure=fig)
# The '1' specifies the index position of the widget
# I had issues with the positioning using kv language
# This widget wouldnt adhere to the widget tree
# That is, the figure would always come last!
# Specifying index as 1 sets the position of this widget
# in second place of a boxlayout with vertical orientation.
self.add_widget(canvas, 1)
class SampleApp(App):
def build(self):
return DrawPlot()
if __name__ == '__main__':
SampleApp().run()
sample.kv
There is only one line here that calls the plotting function. I could have used an Image widget instead of Label. They both give the same result.
#:kivy 1.9.1
<DrawPlot>:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: main_title.height
Label:
id: main_title
text: "Plotting using Matplotlib in Kivy"
font_size: '35sp'
size_hint: 1, None
height: self.height
Label:
source: root.draw_my_plot()
BoxLayout:
orientation: 'horizontal'
size_hint: 1, None
height: playbutton.height
Button:
id: playbutton
text: 'play'
size_hint: 1, None
height: self.height
Button:
text: 'reset'
size_hint: 1, None
Button:
text: 'quit'
size_hint: 1, None
Output