我对python世界很陌生,很不幸,我还没有找到任何解决方案。
我在Mac OS X 10.13.2上运行python 3.6和matplotlib==1.3.1。
目前,我正试图建立一个小软件,以4Hz的速度获取数据,并以1Hz的速度将获取的数据显示在图中。因此,我创建了一个在线程中运行的类来获取数据,另一个类来更新实际的绘图。在这两者之间有一个数据类,它将保存数据,并作为两个类之间的接口。
import matplotlib.pyplot as plt
import numpy as np
import threading
import random
import time
class MyDataClass():
def __init__(self):
self.XData = [0]
self.YData = [0]
class MyPlotClass(threading.Thread):
def __init__(self, dataClass):
threading.Thread.__init__(self)
self._dataClass = dataClass
self._period = 1
self._nextCall = time.time()
self.hLine, = plt.plot(0, 0)
plt.ion()
def run(self):
while True:
self.hLine.set_data(self._dataClass.XData, self._dataClass.YData)
plt.draw()
print("updated %i datapoints" % len(self._dataClass.XData))
# sleep until next execution
self._nextCall = self._nextCall + self._period
time.sleep(self._nextCall - time.time())
class MyDataFetchClass(threading.Thread):
def __init__(self, dataClass):
threading.Thread.__init__(self)
self._dataClass = dataClass
self._period = 0.25
self._nextCall = time.time()
def run(self):
while True:
# add data to data class
self._dataClass.XData.append(self._dataClass.XData[-1] + 1)
self._dataClass.YData.append(random.randint(0, 256))
print("Added (%i, %i)" % (self._dataClass.XData[-1], self._dataClass.YData[-1]))
# sleep until next execution
self._nextCall = self._nextCall + self._period
time.sleep(self._nextCall - time.time())
data = MyDataClass()
fetcher = MyDataFetchClass(data)
plotter = MyPlotClass(data)
fetcher.start()
plotter.start()
fetcher.join()
plotter.join()
由于命令行的输出,我可以看到线程正在运行。但由于某些原因,持有图的数字不会显示出来。
火箭符号只会上下跳动,而不会显示出来。见附件截图。
简单的例子中,情节只有创建的,使用plt.show()命令可以正常工作。
我想不通我到底做错了什么。我希望你们中的任何人可能有一个想法。
谢谢
编辑:这里提出的解决方案 如何在matplotlib中更新一个情节? 对我来说是行不通的,因为我不想被限制在一定的帧数内(使用Matplotlib的动画框架)。我需要以1Hz的速度持续更新情节。
我不认为你可以在主线程之外运行matplotlib GUI。因此,在主线程中保持绘图,并使用一个 FuncAnimation
来引导绘图,下面的方法似乎很有效。
由于 while True
循环,它将永远运行,甚至在关闭窗口后,所以对于任何现实世界的应用,这仍然应该调整。
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
import threading
import random
import time
class MyDataClass():
def __init__(self):
self.XData = [0]
self.YData = [0]
class MyPlotClass():
def __init__(self, dataClass):
self._dataClass = dataClass
self.hLine, = plt.plot(0, 0)
self.ani = FuncAnimation(plt.gcf(), self.run, interval = 1000, repeat=True)
def run(self, i):
print("plotting data")
self.hLine.set_data(self._dataClass.XData, self._dataClass.YData)
self.hLine.axes.relim()
self.hLine.axes.autoscale_view()
class MyDataFetchClass(threading.Thread):
def __init__(self, dataClass):
threading.Thread.__init__(self)
self._dataClass = dataClass
self._period = 0.25
self._nextCall = time.time()
def run(self):
while True:
print("updating data")
# add data to data class
self._dataClass.XData.append(self._dataClass.XData[-1] + 1)
self._dataClass.YData.append(random.randint(0, 256))
# sleep until next execution
self._nextCall = self._nextCall + self._period;
time.sleep(self._nextCall - time.time())
data = MyDataClass()
plotter = MyPlotClass(data)
fetcher = MyDataFetchClass(data)
fetcher.start()
plt.show()
#fetcher.join()