Kivy and Matplotlib trying to update plot on button callback

蹲街弑〆低调 提交于 2020-01-31 19:35:07

问题


I can generate a 2D surface plot very nicely with Kivy and Matplotlib. I am trying to update the Z values on a button click. How may this be accomplished?

I noticed that I can issue a plt.clf() which will clear the plot but doing the plt.gcf() to display the current plot doesn't work.

Any suggestions would be really appreciated.

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

import numpy as np
from matplotlib.mlab import griddata
from kivy.garden.matplotlib.backend_kivy import FigureCanvas,\
                                                NavigationToolbar2Kivy

# from backend_kivy import FigureCanvasKivy as 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.graphics import Color, Line, Rectangle

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

fig, ax = plt.subplots()

X = np.arange(-508, 510, 203.2)
Y = np.arange(-508, 510, 203.2)
X, Y = np.meshgrid(X, Y)

Z = np.random.rand(6, 6)

plt.contourf(X, Y, Z, 100, zdir='z', offset=1.0, cmap=cm.hot)
plt.colorbar()

ax.set_ylabel('Y [mm]')
ax.set_title('NAILS surface')
ax.set_xlabel('X [mm]')

canvas = fig.canvas


def callback(instance):


    fig, ax = plt.subplots()

    X = np.arange(-508, 510, 203.2)
    Y = np.arange(-508, 510, 203.2)
    X, Y = np.meshgrid(X, Y)

    Z = np.random.rand(6, 6)

    plt.contourf(X, Y, Z, 100, zdir='z', offset=1.0, cmap=cm.hot)
    plt.colorbar()

    ax.set_ylabel('Y [mm]')
    ax.set_title('NAILS surface')
    ax.set_xlabel('X [mm]')

    canvas = fig.canvas
    canvas.draw()


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

    def build(self):
        fl = BoxLayout(orientation="vertical")
        a = Button(text="press me", height=40, size_hint_y=None)
        a.bind(on_press=callback)

        fl.add_widget(canvas)
        fl.add_widget(a)
        return fl

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

回答1:


Line 45 of your code:

fig, ax = plt.subplots()

creates a new figure and hence a new canvas. This canvas is never added to the BoxLayout and hence never shown. It's probably a better idea to re-use the old canvas. Change the callback function to this:

def callback(instance):
    # Clear the existing figure and re-use it
    plt.clf()

    X = np.arange(-508, 510, 203.2)
    Y = np.arange(-508, 510, 203.2)
    X, Y = np.meshgrid(X, Y)

    Z = np.random.rand(6, 6)

    plt.contourf(X, Y, Z, 100, zdir='z', offset=1.0, cmap=cm.hot)
    plt.colorbar()

    ax.set_ylabel('Y [mm]')
    ax.set_title('NAILS surface')
    ax.set_xlabel('X [mm]')

    canvas.draw_idle()



回答2:


Need to make the fig and ax variables global. Call plt.clf() to clear the current figure and re-plot with appropriate colorbar.

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

import numpy as np
from matplotlib.mlab import griddata
from kivy.garden.matplotlib.backend_kivy import FigureCanvas,\
                                                NavigationToolbar2Kivy

# from backend_kivy import FigureCanvasKivy as 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.graphics import Color, Line, Rectangle

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

# fig, ax = plt.subplots()
fig, ax = plt.subplots()

X = np.arange(-508, 510, 203.2)
Y = np.arange(-508, 510, 203.2)
X, Y = np.meshgrid(X, Y)

Z = np.random.rand(6, 6)

plt.contourf(X, Y, Z, 100, zdir='z', offset=1.0, cmap=cm.hot)
plt.colorbar()

ax.set_ylabel('Y [mm]')
ax.set_title('NAILS surface')
ax.set_xlabel('X [mm]')

canvas = fig.canvas



def callback(instance):

    global fig, ax
    # fig, ax = plt.subplots()

    X = np.arange(-508, 510, 203.2)
    Y = np.arange(-508, 510, 203.2)
    X, Y = np.meshgrid(X, Y)

    Z = 1000*np.random.rand(6, 6)
    plt.clf()
    plt.contourf(X, Y, Z, 100, zdir='z', offset=1.0, cmap=cm.hot)
    plt.colorbar()

    # ax.set_ylabel('Y [mm]')
    # ax.set_title('NAILS surface')
    # ax.set_xlabel('X [mm]')

    # canvas = fig.canvas
    canvas.draw()


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

    def build(self):
        fl = BoxLayout(orientation="vertical")
        a = Button(text="press me", height=40, size_hint_y=None)
        a.bind(on_press=callback)

        fl.add_widget(canvas)
        fl.add_widget(a)
        return fl

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


来源:https://stackoverflow.com/questions/38624168/kivy-and-matplotlib-trying-to-update-plot-on-button-callback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!