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

plotting with matplotlib in kivy screenshot

results matching ""

    No results matching ""