[英]Kivy: update matplotlib canvas with a slider
I need to create a slider which updates a matplotlib figure. 我需要创建一个更新matplotlib图形的滑块。 So far I have this, main.py:
到目前为止,我有这个main.py:
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
import numpy as np
import matplotlib.pyplot as plt
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
class Container(BoxLayout):
display = ObjectProperty()
def __init__(self, *args, **kwargs):
global canvas
super(Container, self).__init__(**kwargs)
lum_img = np.random.rand(10,10)
plt.imshow(lum_img, cmap="gray")
plt.colorbar()
canvas = FigureCanvasKivyAgg(plt.gcf())
self.ids.box_display.add_widget(canvas)
canvas.draw()
def add_one(self, value):
lum_img = np.random.rand(10,10)
plt.imshow(lum_img, cmap="gray")
plt.colorbar()
canvas.draw()
self.display.text = str(round(value,2))
class MainApp(App):
def build(self):
self.title = 'Image and slider app'
return Container()
if __name__ == "__main__":
app = MainApp()
app.run()
And the main.kv: 和main.kv:
<Container>:
display: display
id: main_display
orientation: "vertical"
BoxLayout:
id: box_display
orientation: "vertical"
Slider:
id: slider_image
min: 0
max: 1
value: 0.5
on_value: root.add_one(value = slider_image.value)
Label:
id: display
font_size: dp(50)
text: '0'
The behaviour is not as expected, instead of updating the image canvas it just move it! 该行为不符合预期,它只是移动图像而不是更新图像画布! I think that the error is to declare the canvas as a global variable, but I do not know how to update it without doing this.
我认为错误是将画布声明为全局变量,但不执行此操作我不知道如何更新它。
Any idea? 任何想法?
You code is actually creating new plots, but they are not positioned well and overlap each other. 您的代码实际上是在创建新的图,但是它们的位置不正确并且彼此重叠。 One way to correct that problem is to use
plt.subplot()
. 解决该问题的一种方法是使用
plt.subplot()
。 That requires knowing in advance how many subplots you will add. 这需要预先知道要添加多少个子图。 Here is a modified version of your code that uses this approach (I included the
.kv
as a string just for my own convenience): 这是使用此方法的代码的修改版本(为方便起见,我将
.kv
作为字符串包含在内):
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
import numpy as np
import matplotlib.pyplot as plt
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
Builder.load_string('''
<Container>:
display: display
id: main_display
orientation: "vertical"
BoxLayout:
id: box_display
orientation: "vertical"
Slider:
id: slider_image
min: 0
max: 1
value: 0.0
on_value: root.add_one(value = slider_image.value)
Label:
id: display
font_size: dp(50)
text: '0'
''')
class Container(BoxLayout):
display = ObjectProperty()
def __init__(self, *args, **kwargs):
global canvas
super(Container, self).__init__(**kwargs)
self.index = 1 # index of the current plot
self.max_plots = 5 # maximum number of subplots
self.old_slider_value = 0.0 # starting value of the slider
lum_img = np.random.rand(10,10)
plt.subplot(1, self.max_plots, self.index) # create the first subplot
plt.imshow(lum_img, cmap="gray")
plt.colorbar()
canvas = FigureCanvasKivyAgg(plt.gcf())
self.ids.box_display.add_widget(canvas)
canvas.draw()
def add_one(self, value):
# only make a new subplot if the slider has moved at least 0.2
if (value - self.old_slider_value) > 1.0/self.max_plots and self.index < self.max_plots:
self.old_slider_value = value
self.index += 1
plt.subplot(1, self.max_plots, self.index) # make new subplot
lum_img = np.random.rand(10,10)
plt.imshow(lum_img, cmap="gray")
plt.colorbar()
plt.tight_layout() # arrange the subplots a bit to eliminate overlaps
canvas.draw()
self.display.text = str(round(value,2))
class MainApp(App):
def build(self):
self.title = 'Image and slider app'
return Container()
if __name__ == "__main__":
app = MainApp()
app.run()
Misunderstood what you wanted (my error). 误解了您想要的东西(我的错误)。 If you do not want to create new plots, but just update the existing one, you only need to add a call to
plt.clf()
in your add_one()
method before you do any additional plotting. 如果您不想创建新的绘图,而只是更新现有的绘图,则只需在执行其他绘图之前在
add_one()
方法中添加对plt.clf()
的调用即可。 This clears the current figure, and allows you to replace it with a new one. 这将清除当前图形,并允许您将其替换为新图形。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.