【问题标题】:How to create real time graph in kivy?如何在kivy中创建实时图表?
【发布时间】:2014-05-14 22:36:31
【问题描述】:

我想在 kivy 中创建一个实时图表。我怎样才能做到这一点?我是 kivy 的新手。请帮我。

【问题讨论】:

    标签: python-2.7 graph kivy


    【解决方案1】:

    定义你的情节

    例如

    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 的运行图。

    【讨论】:

      【解决方案2】:

      kivy garden 中有一个图表小部件。您可以在 kivy 的 documentation 中阅读有关使用花园小部件的信息。

      【讨论】:

      • 是否支持直方图?
      • 我不这么认为。不过今年我们可能有一个支持 matplotlib 的 gsoc 项目。
      【解决方案3】:

      我也在尝试在 Kivy 中制作实时图表。

      Youscope

      我从 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。 (尚未测试构建图形应用程序,但应该可以。)

      Youscope 与 Kivy

      绘图在 kivy 中的运行速度似乎与原始代码一样快,但目前我正忙于重新绘制曲线。但我认为绘图应该更快,也许计算点需要太长时间。 我想我应该检查一个 WAV 文件作为输入,如果它更快。

      Clock.schedule_intervall (Kivy) 与游戏循环 (Pygame)

      Kivy 的源代码与 pygame 代码非常相似,但在 Kivy 中没有带有 while 循环的游戏循环。 在 Kivy 中,您使用带有 Clock.schedule_intervall(callback, ti​​me_in_sec) 的回调(参见 http://kivy.org/docs/api-kivy.clock.html)来更新/绘制屏幕。

      使用帧缓冲进行绘图

      对于绘图,您需要使用添加到画布的帧缓冲区。见http://kivy.org/docs/api-kivy.graphics.fbo.html

      曲线是从左到右逐点绘制的。 重绘是指我在帧缓冲区上绘制第一条曲线(我正在使用计算出的正弦波),当我到达屏幕的右边缘后,我开始使用新曲线从左侧再次绘制。

      现在仍然需要清除之前绘制的曲线。您可以在此处重新绘制整个屏幕,但这可能比逐点删除旧行要慢。

      这里的困难在于恢复旧曲线下方的背景颜色。看起来我得到了错误像素的颜色,但我不确定出了什么问题。

      Get_pixel_color() 用于刷新屏幕

      使用 Framebuffer.get_pixel_color(wx,wy)(需要 Kivy 1.8.0),您可以获得 rgba 中像素的颜色,但无法正常工作。也许这是一个更新问题,但我不确定。

      使用黑色像素(没有 get_pixel_color)进行清除工作,但会删除背景网格。

      【讨论】:

        【解决方案4】:

        这是我写的代码,需要一个趋势曲线。

        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()
        

        【讨论】:

          猜你喜欢
          • 2019-07-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-15
          • 1970-01-01
          • 2014-04-18
          • 2020-10-27
          • 1970-01-01
          相关资源
          最近更新 更多