从不同的文件向实时图表添加点
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()
您的代码存在三个主要问题:
- 您的代码
kv = Builder.load_file("my.kv")
正在第二次加载 my.kv
文件。它将自动加载,因为该文件已正确命名以便发生这种情况。您应该删除该代码。
- 您对
DataStore.getData()
的预定调用将无法工作,因为您的 DataStore
实例未保存在任何地方,因此它会被垃圾收集。
DataStore
的 getData()
方法每次运行时都会创建一个 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)
我正在尝试在我的代码中使用实时图表。
当一切都在同一个 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()
您的代码存在三个主要问题:
- 您的代码
kv = Builder.load_file("my.kv")
正在第二次加载my.kv
文件。它将自动加载,因为该文件已正确命名以便发生这种情况。您应该删除该代码。 - 您对
DataStore.getData()
的预定调用将无法工作,因为您的DataStore
实例未保存在任何地方,因此它会被垃圾收集。 DataStore
的getData()
方法每次运行时都会创建一个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)