matplotlib - 按下按钮时替换 Kivy 中的 DataFrame 图
问题描述
我正在编写一个 Kivy 应用程序,它将通过 kivy.garden.matplotlib.backend_kivyagg 显示 Pandas DataFrame 的图形,并在按下按钮时根据 UI 中的其他输入重新生成图形(显示不同的数据)。当我运行我的程序时,它会生成第一个图就好了。但是按下按钮并不会改变图形,即使我调用了 plt.clf(),生成了一个新的 DataFrame,并在该 DataFrame 上调用了 plot()。任何指针将不胜感激!
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
class MyApp(App):
def plot_random_data(self):
df = pd.DataFrame(np.random.randint(0, 100, size=(10, 2)), columns=list('AB'))
df.plot()
def on_plot_button_press(self, instance):
# TODO: This does not actually refresh graph with the new random data!
print('Plot button pressed')
plt.clf()
self.plot_random_data()
def build(self):
box = BoxLayout(orientation='vertical')
# The first plot of data works ...
self.plot_random_data()
box.add_widget(FigureCanvasKivyAgg(plt.gcf()))
button_area = BoxLayout(size_hint=(1, 0.10))
box.add_widget(button_area)
btn1 = Button(text='Plot')
btn1.bind(on_press=self.on_plot_button_press)
button_area.add_widget(btn1)
return box
MyApp().run()
更新:下面约翰安德森的回答使图表用新数据刷新。但是,在按下按钮 20 次后,您会收到以下错误:
/Users/rougex/Library/Python/3.7/lib/python/site-packages/pandas/plotting/_matplotlib/core.py:320: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
fig = self.plt.figure(figsize=self.figsize)
我发现解决这个问题的方法是调用 plt.close(self.plot.figure),所以 on_plot_button_press 的最终工作代码是:
def on_plot_button_press(self, instance):
plt.close(self.plot.figure)
self.plot_random_data()
self.root.remove_widget(self.plot)
self.plot = FigureCanvasKivyAgg(plt.gcf())
self.root.add_widget(self.plot, index=1)
解决方案
似乎没有任何方法可以更改显示在FigureCanvasKivyAgg
. 因此,您必须FigureCanvasKivyAgg
改为替换。这是您的修改版本MyApp
:
class MyApp(App):
def plot_random_data(self):
df = pd.DataFrame(np.random.randint(0, 100, size=(10, 2)), columns=list('AB'))
df.plot()
def on_plot_button_press(self, instance):
# TODO: This does not actually refresh graph with the new random data!
print('Plot button pressed')
plt.clf()
self.plot_random_data()
self.root.remove_widget(self.plot)
self.plot = FigureCanvasKivyAgg(plt.gcf())
self.root.add_widget(self.plot, index=1)
def build(self):
box = BoxLayout(orientation='vertical')
# The first plot of data works ...
self.plot_random_data()
self.plot = FigureCanvasKivyAgg(plt.gcf())
box.add_widget(self.plot)
button_area = BoxLayout(size_hint=(1, 0.10))
box.add_widget(button_area)
btn1 = Button(text='Plot')
btn1.bind(on_press=self.on_plot_button_press)
button_area.add_widget(btn1)
return box
该build()
方法保存对 的引用,用于从方法中FigureCanvasKivyAgg
删除它。然后该方法创建一个新图(保存参考),创建一个新图并将其添加到. 该方法使用参数将其插入到.BoxLayout
on_plot_button_press()
FigureCanvasKivyAgg
BoxLayout
add_widget()
index
BoxLayout