Is it possible to package matplotlib code into a custom widget?

724 views
Skip to first unread message

David Daiku Trowbridge

unread,
Jul 15, 2016, 11:35:08 AM7/15/16
to Kivy users support
Using the kivy-matplotlib program test_backend.py as a model, I can display a graph in a BoxLayout with other widgets.

However, I would like to package the matplotlib code into a custom widget, class GT(Widget): with instance gt = GT().

When I run my test program,
import matplotlib
matplotlib
.use('module://kivy.garden.matplotlib.backend_kivy')
from matplotlib.figure import Figure
from numpy import arange, sin, pi
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ReferenceListProperty,\
   
ObjectProperty
from kivy.clock import Clock

import numpy as np
#from kivy.garden.matplotlib.backend_kivyagg import FigureCanvas
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from matplotlib.transforms import Bbox
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.graphics import Color, Line, Rectangle

import matplotlib.pyplot as plt


class GT(Widget):
    N
= 5
    menMeans = (20, 35, 30, 35, 27)
    menStd
= (2, 3, 4, 1, 2)
    ind
= np.arange(N)  # the x locations for the groups
#    width = 1  # the width of the bars
#    width = 0.35  # the width of the bars


    fig, ax = plt.subplots()
    rects1
= ax.bar(ind, menMeans, 0.3, color='r', yerr=menStd)
#    rects1 = ax.bar(ind, menMeans, width, color='r', yerr=menStd)

    womenMeans = (25, 32, 34, 20, 25)
    womenStd
= (3, 5, 2, 3, 3)

   
# add some text for labels, title and axes ticks
    ax.set_ylabel('Scores')
    ax
.set_title('Scores by group and gender')
    ax
.set_xticks(ind + 0.3)
#    ax.set_xticks(ind + width)
    ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))

    canvas
= fig.canvas

    fl
= BoxLayout(orientation="vertical")
    a
= Button(text="Run", height=40, size_hint_y=None)
    b
= Label(text="Feedback goes here", height=100, size_hint_y=0.2)
    fl
.add_widget(canvas)  # Graph drawing area
    fl.add_widget(b)  # Feedback text area
    fl.add_widget(a)  # Run button


class MatplotlibTest(App):
    title
= 'Simpler Matplotlib Test'

    def build(self):
        gt
= GT()
       
#Clock.schedule_interval(gt.update, 1.0 / 10.0)
        return gt

if __name__ == '__main__':
   
MatplotlibTest().run()

I get,

Traceback (most recent call last):
   File "C:/Users/David/PycharmProjects/plt/test_backend7A.py", line 65, in <module>
     MatplotlibTest().run()
   File "C:\Anaconda27\lib\site-packages\kivy\app.py", line 810, in run
     Window.add_widget(self.root)
   File "C:\Anaconda27\lib\site-packages\kivy\core\window\__init__.py", line 936, in add_widget
     canvas.add(widget.canvas)
 TypeError: Argument 'c' has incorrect type (expected kivy.graphics.instructions.Instruction, got FigureCanvasKivy)

(Note: I have commented out some lines involving 'width' because I was getting errors about unable to convert float.)

How can I create a custom widget for matplotlib?

Thank you.

Bill Janssen

unread,
Jul 19, 2016, 10:36:51 PM7/19/16
to Kivy users support
A couple of things:

1.  FigureCanvasKivy is broken, till matplotlib 2.0 comes out.  Some lines aren't drawn.  Use FigureCanvasKivyAgg instead.

2.  The magic formula you want is

    fl.add_widget(FigureCanvasKivyAgg(fig))

instead of


    fl.add_widget(canvas)  # Graph drawing area

So you'd better uncomment the line which imports FigureCanvasKivyAgg :-).

Bill
Reply all
Reply to author
Forward
0 new messages