从不同的文件向实时图表添加点

Add points to a live graph from a different file

我正在尝试在我的代码中使用实时图表。

当一切都在同一个 python 文件中时,我可以获得一个实时图表,尽管当我尝试将图表 class 分离到它自己的 python 文件中时,图表不更新。我没有真正说明为什么图表没有更新,但我想我可能正在创建一堆 LogGraph 对象,而不是向 my.kv 中的实际 LogGraph 添加点,但我不确定如何不要那样做。

我的实际代码有点复杂和混乱,所以我在这里模拟了一个示例代码,它的行为应该完全相同:

main.py

from math import sin
import kivy
from kivy_garden.graph import Graph, MeshLinePlot
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from data import startdata

class MainWindow(Screen):

    def pressrun(self):
        self.ids.runlbl.text = 'Started'
        startdata()

    pass

class MyApp(App):
    def build(self):
        wm.add_widget(MainWindow())
        return wm

class WindowManager(ScreenManager):
    def __init__(self, **kwargs):
        super(WindowManager, self).__init__(**kwargs)

wm = WindowManager()
kv = Builder.load_file("my.kv")

MyApp().run()

my.kv

#: import LogGraph graphs.LogGraph
<MainWindow>:
    id: main
    BoxLayout:
        orientation: "vertical"
        LogGraph:
        BoxLayout:
            orientation: "horizontal"
            Button:
                text: "Start Data Gen"
                on_release:
                    root.pressrun()
            Label:
                id: runlbl
                text: "Not Started"

graphs.py

from kivy_garden.graph import Graph, MeshLinePlot

class LogGraph(Graph):
    def __init__(self, **kwargs):
        super(LogGraph, self).__init__(**kwargs)
        self.xlabel = 'X'
        self.ylabel = 'Y'
        self.x_ticks_major = 25
        self.x_ticks_minor = 5
        self.x_grid_label = True
        self.y_ticks_major = 1
        self.y_grid_label = True
        self.xmin = 0
        self.xmax = 100
        self.ymin = 0.1
        self.ymax = 10
        self.ylog = True
        self.x_grid = True
        self.y_grid = True
        self.plot = MeshLinePlot(color=[1, 0, 0, 1])
        self.add_plot(self.plot)
        self.plot.points = [(1,1)]

    def update_xaxis(self,xmin = 0):
        self.xmin = xmin
        self.xmax = xmin + 10

    def update_yaxis(self,ymin = 0):
        self.ymin = ymin
        self.ymax = ymin + 10

    def update_points(self, point, *args):
        self.plot.points.append([point,point])
        # x axis resize
        if point > self.xmax:
            self.update_xaxis(self.xmax)
        # y axis resize
        if point > self.ymax:
            self.update_yaxis(self.ymax)

data.py

from kivy.clock import Clock
from functools import partial
from graphs import LogGraph

class DataStore():
    def __init__(self):
        self.i = 1
        self.dataarray = []

    def start(self):
        self.clock = Clock.schedule_interval(self.getData, 1/60)

    def cancel(self):
        self.clock.cancel()

    def wait(self):
        print('Waited!')

    def getData(self):
        i = self.i + 1/60
        LogGraph.update_points(LogGraph(), i)
        pass

def startdata():
    ds = DataStore()
    ds.start()

您的代码存在三个主要问题:

  1. 您的代码 kv = Builder.load_file("my.kv") 正在第二次加载 my.kv 文件。它将自动加载,因为该文件已正确命名以便发生这种情况。您应该删除该代码。
  2. 您对 DataStore.getData() 的预定调用将无法工作,因为您的 DataStore 实例未保存在任何地方,因此它会被垃圾收集。
  3. DataStoregetData() 方法每次运行时都会创建一个 LogGraph 的新实例,但不使用 GUI 中的 LogGraph 实例.

要解决这些问题,请先添加到您的 kv 以允许访问:

#: import LogGraph graphs.LogGraph
<MainWindow>:
    id: main
    name: 'main'  # added to enable access
    BoxLayout:
        orientation: "vertical"
        LogGraph:
            id: graph  # added to enable access
        BoxLayout:
            orientation: "horizontal"
            Button:
                text: "Start Data Gen"
                on_release:
                    root.pressrun()
            Label:
                id: runlbl
                text: "Not Started"

然后在startdata()方法中,添加一个return

def startdata():
    ds = DataStore()
    ds.start()

    # return the DataStore instance so it can be saved
    return ds

然后在pressrun()方法中保存returned DataStore

def pressrun(self):
    self.ids.runlbl.text = 'Started'
    self.dataStore = startdata()

并且必须修改 getData() 方法以访问 GUI 中的 LogGraph

def getData(self, dt):  # time interval argument is required
    self.i += dt

    # access the LogGraph instance in the GUI
    lg = App.get_running_app().root.get_screen('main').ids.graph
    lg.update_points(self.i)
    # LogGraph.update_points(LogGraph(), i)