【发布时间】:2014-05-14 22:36:31
【问题描述】:
我想在 kivy 中创建一个实时图表。我怎样才能做到这一点?我是 kivy 的新手。请帮我。
【问题讨论】:
标签: python-2.7 graph kivy
我想在 kivy 中创建一个实时图表。我怎样才能做到这一点?我是 kivy 的新手。请帮我。
【问题讨论】:
标签: python-2.7 graph kivy
定义你的情节
例如
plot = MeshLinePlot(color=next(colors))
定义图表
例如
graph = Graph(
xlabel='Iteration',
ylabel='Value',
x_ticks_minor=1,
x_ticks_major=5,
y_ticks_major=1,
y_grid_label=True,
x_grid_label=True,
padding=5,
xlog=False,
ylog=False,
x_grid=True,
y_grid=True,
ymin=0,
ymax=11,
**graph_theme)
更新图形和更新x轴:
例如
def update_xaxis(self,*args):
global graph
global cnt
graph.xmin = cnt - 50
graph.xmax = cnt
def update_points(self, *args):
global i
global MYLIST
global cnt
#self.plot.points = [(i,i)]
self.plot.points = [z for z in MYLIST]
调用时钟
例如
Clock.schedule_interval(self.update_points, 1/60.)
Clock.schedule_interval(self.update_xaxis, 1/60.)
并添加小部件:
b.add_widget(graph)
我希望我没有忘记任何事情。它为您提供 kivy Garden 的运行图。
【讨论】:
kivy garden 中有一个图表小部件。您可以在 kivy 的 documentation 中阅读有关使用花园小部件的信息。
【讨论】:
我也在尝试在 Kivy 中制作实时图表。
我从 Youscope 开始。您可以在以下 youtube 视频 https://www.youtube.com/watch?v=-1E0DpQ_cFo
中看到 youscope 的演示源代码在这里:https://code.google.com/p/felipesanches/source/browse/trunk/youscope-emu/youscope-emu.py
它是用 Pygame 编写的,使用波形音频文件作为输入源,但您也可以使用其他源(例如串行数据或计算曲线)。
Youscope 的问题是我无法从中构建适用于 Android 的 APK。我尝试为 android 安装 python 子集,但在构建时总是收到错误消息。 (不知道怎么回事。)
所以我决定将 Youscope 代码移植到 Kivy,因为使用 Buildozer 我可以制作 Android APK。 (尚未测试构建图形应用程序,但应该可以。)
绘图在 kivy 中的运行速度似乎与原始代码一样快,但目前我正忙于重新绘制曲线。但我认为绘图应该更快,也许计算点需要太长时间。 我想我应该检查一个 WAV 文件作为输入,如果它更快。
Kivy 的源代码与 pygame 代码非常相似,但在 Kivy 中没有带有 while 循环的游戏循环。 在 Kivy 中,您使用带有 Clock.schedule_intervall(callback, time_in_sec) 的回调(参见 http://kivy.org/docs/api-kivy.clock.html)来更新/绘制屏幕。
对于绘图,您需要使用添加到画布的帧缓冲区。见http://kivy.org/docs/api-kivy.graphics.fbo.html
曲线是从左到右逐点绘制的。 重绘是指我在帧缓冲区上绘制第一条曲线(我正在使用计算出的正弦波),当我到达屏幕的右边缘后,我开始使用新曲线从左侧再次绘制。
现在仍然需要清除之前绘制的曲线。您可以在此处重新绘制整个屏幕,但这可能比逐点删除旧行要慢。
这里的困难在于恢复旧曲线下方的背景颜色。看起来我得到了错误像素的颜色,但我不确定出了什么问题。
使用 Framebuffer.get_pixel_color(wx,wy)(需要 Kivy 1.8.0),您可以获得 rgba 中像素的颜色,但无法正常工作。也许这是一个更新问题,但我不确定。
使用黑色像素(没有 get_pixel_color)进行清除工作,但会删除背景网格。
【讨论】:
这是我写的代码,需要一个趋势曲线。
class TrendCurve(BoxLayout):
def __init__(self, **kwargs):
super(TrendCurve, self).__init__(**kwargs)
#self size and position
self.size = (1000, 500)
self.pos = (60,1)#((Window.width / 2) - ((self.size[0] / 2) - 80) , (Window.height / 2) - (self.size[1] / 2))
self.text = ""
self.number_labels = {}
#This is the point where the trend starts
self.point_zero = (self.pos[0] + 10, self.pos[1] + 10)
self.point_zero_x = self.pos[0] + 10
self.point_zero_y = self.pos[1] + 10
#Points for drawing the line around the rectangle
#"border line"
self.x1 = self.pos[0] - 50
self.y1 = self.pos[1]
self.x2 = self.pos[0] - 50
self.y2 = self.pos[1] + self.size[1]
self.x3 = self.pos[0] + self.size[0]
self.y3 = self.y2
self.x4 = self.x3
self.y4 = self.pos[1]
self.x5 = self.pos[0] - 50
self.y5 = self.y4
self.box_points = [self.x1, self.y1, self.x2, self.y2, self.x3, self.y3, self.x4, self.y4, self.x5, self.y5]
#Trend line
self.trend_points = []
#Trend starts at point zero
self.trend_points = [self.point_zero_x, self.point_zero_y]
#Variable for setting resolution of points and numbers
self.resolution = 10
#Lines for x and y on the trend.
self.xline_points = [self.pos[0] + 10, self.pos[1] + 10, self.pos[0] + 10, (self.pos[1] + self.size[1] - 10)]
self.yline_points = [self.pos[0] + 10, self.pos[1] + 10, (self.pos[0] + self.size[0] - 10), self.pos[1] + 10]
self.pointlinesx = {}
self.pointlinesy = {}
self.r = 0
self.g = 1
self.b = 0
#This is the resolution for how far forward we go for each update that comes.
self.x_update = 1
#This is to be rendered before
with self.canvas.before:
Color(0.4, 0.4, 0.4, 1)
self.rectangle = Rectangle(size=self.size, pos=self.pos)
self.left_addon_rectangle = Rectangle(size=(50, self.size[1]), pos=(self.pos[0] - 50, self.pos[1]))
#This is the main canvas
with self.canvas:
Color(0.2, 0.2, 0.2)
self.box = Line(points=self.box_points, width=1)
Color(1, 1, 1)
self.xline = Line(points=self.xline_points)
self.yline = Line(points=self.yline_points)
#These are the small lines for value_y, changing color as it goes upwards
#red gets more powerful and green gets less powerful
for i in range(0, self.size[1] - self.resolution, self.resolution):
if self.r < 1:
self.r += 0.03
if self.g > 0:
self.g -= 0.04
Color(self.r,self.g, 0)
if i >= 20:
self.pointlinesx[i] = Line(points=(self.point_zero_x - 3, self.point_zero_y + i, self.point_zero_x + 3, self.point_zero_y + i), width=0.8)
self.number_labels[i] = Label(size=(50, 20),font_size= 8, pos=(self.point_zero_x - 40, (self.point_zero_y + i) - 10), text=str(0 + i))
self.top_label = Label(text=self.text, size=(100, 50), pos=(self.center[0] - 50, self.center[1] + (self.size[1] / 2) - 50))
self.ms_label = Label(text="ms", size=(100,50), font_size= 11, pos=(self.point_zero_x - 90, self.point_zero_y + (self.size[1] / 2) - 25))
#These are the small lines for value_x, only white colored.
Color(1,1,1)
for i in range(0, self.size[0], 20):
if i >= 20:
self.pointlinesy[i] = Line(points=(self.point_zero_x + i, self.point_zero_y - 3, self.point_zero_x + i, self.point_zero_y + 3), width=0.8)
#This is to be rendered after
with self.canvas.after:
Color(0.3,0.6,1)
self.trend = Line(points=self.trend_points, width=0.8)
def add_points_test(self, dt):
new_num = randint(50, 200)
self.add_point(new_num)
def update(self):
self.trend.points = self.trend_points
def add_point(self, y):
try:
y = int(y)
except ValueError:
pass
if type(y) == int:
#The x is updated x pixels forth at a time
x = self.trend_points[len(self.trend_points) - 2] + self.x_update
self.trend_points.append(x)
#y must be between max and min
if y < 500 > 0:
self.trend_points.append(self.point_zero_y + y)
if y > 500:
self.trend_points.append(500)
if y < 0:
self.trend_points.append(0)
if x > (self.rectangle.size[0] - 10):
new_point_list = []
count = 0
for i in self.trend_points:
if (count % 2) != 1:
i -= self.x_update
new_point_list.append(i)
count += 1
del (new_point_list[0])
del (new_point_list[1])
new_point_list[0] = self.point_zero_x + 20
self.trend_points = new_point_list
self.update()
【讨论】: