提问人:Chris 提问时间:8/9/2012 最后编辑:Trenton McKinneyChris 更新时间:6/23/2023 访问量:832005
如何在 WHILE 循环中实时绘制?
How do I plot in real-time in a while loop?
问:
我正在尝试使用 OpenCV 实时绘制来自相机的一些数据。但是,实时绘图(使用 matplotlib)似乎不起作用。
我已将问题隔离到这个简单的示例中:
fig = plt.figure()
plt.axis([0, 1000, 0, 1])
i = 0
x = list()
y = list()
while i < 1000:
temp_y = np.random.random()
x.append(i)
y.append(temp_y)
plt.scatter(i, temp_y)
i += 1
plt.show()
我希望这个例子单独绘制 1000 个点。实际发生的情况是,窗口弹出并显示第一个点(可以),然后等待循环完成,然后再填充图形的其余部分。
有什么想法为什么我没有看到一次填充一个点?
答:
问题似乎是您希望显示窗口,然后返回。它不会那样做。程序将在此时停止,只有在您关闭窗口后才会恢复。您应该能够测试这一点:如果您关闭窗口,则应该会弹出另一个窗口。plt.show()
要解决该问题,只需在循环后调用一次即可。然后你得到完整的情节。(但不是“实时绘图”)plt.show()
您可以尝试像这样设置关键字参数:在开头一次,然后使用 .draw()
进行更新。block
plt.show(block=False)
评论
show
可能不是最好的选择。我会做的是改用。您可能还希望在循环中包含一个小的时间延迟(例如,),以便您可以看到正在发生的绘图。如果我对你的例子进行这些更改,它对我有用,我看到每个点一次出现一个。pyplot.draw()
time.sleep(0.05)
评论
以下是相关代码的工作版本(至少需要 2011-11-14 的 Matplotlib 1.1.0 版本):
import numpy as np
import matplotlib.pyplot as plt
plt.axis([0, 10, 0, 1])
for i in range(10):
y = np.random.random()
plt.scatter(i, y)
plt.pause(0.05)
plt.show()
请注意对 的调用,它既绘制新数据,又运行 GUI 的事件循环(允许鼠标交互)。plt.pause(0.05)
评论
plt.axis()
plt.plot(x,y)
plt.gca().lines[0].set_xdata(x); plt.gca().lines[0].set_ydata(y); plt.gca().relim(); plt.gca().autoscale_view(); plt.pause(0.05);
如果你对实时绘图感兴趣,我建议你看看 matplotlib 的动画 API。特别是,用于避免在每一帧上重新绘制背景可以为您提供显着的速度提升 (~10x):blit
#!/usr/bin/env python
import numpy as np
import time
import matplotlib
matplotlib.use('GTKAgg')
from matplotlib import pyplot as plt
def randomwalk(dims=(256, 256), n=20, sigma=5, alpha=0.95, seed=1):
""" A simple random walk with memory """
r, c = dims
gen = np.random.RandomState(seed)
pos = gen.rand(2, n) * ((r,), (c,))
old_delta = gen.randn(2, n) * sigma
while True:
delta = (1. - alpha) * gen.randn(2, n) * sigma + alpha * old_delta
pos += delta
for ii in xrange(n):
if not (0. <= pos[0, ii] < r):
pos[0, ii] = abs(pos[0, ii] % r)
if not (0. <= pos[1, ii] < c):
pos[1, ii] = abs(pos[1, ii] % c)
old_delta = delta
yield pos
def run(niter=1000, doblit=True):
"""
Display the simulation using matplotlib, optionally using blit for speed
"""
fig, ax = plt.subplots(1, 1)
ax.set_aspect('equal')
ax.set_xlim(0, 255)
ax.set_ylim(0, 255)
ax.hold(True)
rw = randomwalk()
x, y = rw.next()
plt.show(False)
plt.draw()
if doblit:
# cache the background
background = fig.canvas.copy_from_bbox(ax.bbox)
points = ax.plot(x, y, 'o')[0]
tic = time.time()
for ii in xrange(niter):
# update the xy data
x, y = rw.next()
points.set_data(x, y)
if doblit:
# restore background
fig.canvas.restore_region(background)
# redraw just the points
ax.draw_artist(points)
# fill in the axes rectangle
fig.canvas.blit(ax.bbox)
else:
# redraw everything
fig.canvas.draw()
plt.close(fig)
print "Blit = %s, average FPS: %.2f" % (
str(doblit), niter / (time.time() - tic))
if __name__ == '__main__':
run(doblit=False)
run(doblit=True)
输出:
Blit = False, average FPS: 54.37
Blit = True, average FPS: 438.27
评论
plt.show()
plt.draw()
blit()
我知道这个问题很老了,但现在 GitHub 上有一个名为 drawnow 的包,名为“python-drawnow”。这提供了一个类似于 MATLAB 的 drawnow 的界面——您可以轻松地更新图形。
您的用例示例:
import matplotlib.pyplot as plt
from drawnow import drawnow
def make_fig():
plt.scatter(x, y) # I think you meant this
plt.ion() # enable interactivity
fig = plt.figure() # make a figure
x = list()
y = list()
for i in range(1000):
temp_y = np.random.random()
x.append(i)
y.append(temp_y) # or any arbitrary update to your figure's data
i += 1
drawnow(make_fig)
python-drawnow 是一个薄包装器,但提供了在图形显示后确认(或调试)的功能。plt.draw
评论
没有一种方法对我有用。 但是我发现这个实时 matplotlib 图在循环中不起作用
您只需要添加
plt.pause(0.0001)
然后你可以看到新的地块。
所以你的代码应该看起来像这样,它会起作用
import matplotlib.pyplot as plt
import numpy as np
plt.ion() ## Note this correction
fig=plt.figure()
plt.axis([0,1000,0,1])
i=0
x=list()
y=list()
while i <1000:
temp_y=np.random.random();
x.append(i);
y.append(temp_y);
plt.scatter(i,temp_y);
i+=1;
plt.show()
plt.pause(0.0001) #Note this correction
评论
如果你想画而不是冻结你的线程,因为画了更多的点,你应该使用 plt.pause() 而不是 time.sleep()
我使用以下代码绘制一系列 XY 坐标。
import matplotlib.pyplot as plt
import math
pi = 3.14159
fig, ax = plt.subplots()
x = []
y = []
def PointsInCircum(r,n=20):
circle = [(math.cos(2*pi/n*x)*r,math.sin(2*pi/n*x)*r) for x in xrange(0,n+1)]
return circle
circle_list = PointsInCircum(3, 50)
for t in range(len(circle_list)):
if t == 0:
points, = ax.plot(x, y, marker='o', linestyle='--')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
else:
x_coord, y_coord = circle_list.pop()
x.append(x_coord)
y.append(y_coord)
points.set_data(x, y)
plt.pause(0.01)
这是我在我的系统上工作的一个版本。
import matplotlib.pyplot as plt
from drawnow import drawnow
import numpy as np
def makeFig():
plt.scatter(xList,yList) # I think you meant this
plt.ion() # enable interactivity
fig=plt.figure() # make a figure
xList=list()
yList=list()
for i in np.arange(50):
y=np.random.random()
xList.append(i)
yList.append(y)
drawnow(makeFig)
#makeFig() The drawnow(makeFig) command can be replaced
#plt.draw() with makeFig(); plt.draw()
plt.pause(0.001)
drawnow(makeFig) 线可以替换为 makeFig();plt.draw() 序列,它仍然可以正常工作。
评论
我知道我回答这个问题有点晚了。尽管如此,我不久前还是制作了一些代码来绘制实时图形,我想分享一下:
PyQt4 代码:
###################################################################
# #
# PLOT A LIVE GRAPH (PyQt4) #
# ----------------------------- #
# EMBED A MATPLOTLIB ANIMATION INSIDE YOUR #
# OWN GUI! #
# #
###################################################################
import sys
import os
from PyQt4 import QtGui
from PyQt4 import QtCore
import functools
import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt4Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import time
import threading
def setCustomSize(x, width, height):
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
x.setSizePolicy(sizePolicy)
x.setMinimumSize(QtCore.QSize(width, height))
x.setMaximumSize(QtCore.QSize(width, height))
''''''
class CustomMainWindow(QtGui.QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# Define the geometry of the main window
self.setGeometry(300, 300, 800, 400)
self.setWindowTitle("my first window")
# Create FRAME_A
self.FRAME_A = QtGui.QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name())
self.LAYOUT_A = QtGui.QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)
# Place the zoom button
self.zoomBtn = QtGui.QPushButton(text = 'zoom')
setCustomSize(self.zoomBtn, 100, 50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))
# Place the matplotlib figure
self.myFig = CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig, *(0,1))
# Add the callbackfunc to ..
myDataLoop = threading.Thread(name = 'myDataLoop', target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
myDataLoop.start()
self.show()
''''''
def zoomBtnAction(self):
print("zoom in")
self.myFig.zoomIn(5)
''''''
def addData_callbackFunc(self, value):
# print("Add data: " + str(value))
self.myFig.addData(value)
''' End Class '''
class CustomFigCanvas(FigureCanvas, TimedAnimation):
def __init__(self):
self.addedData = []
print(matplotlib.__version__)
# The data
self.xlim = 200
self.n = np.linspace(0, self.xlim - 1, self.xlim)
a = []
b = []
a.append(2.0)
a.append(4.0)
a.append(2.0)
b.append(4.0)
b.append(3.0)
b.append(4.0)
self.y = (self.n * 0.0) + 50
# The window
self.fig = Figure(figsize=(5,5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
# self.ax1 settings
self.ax1.set_xlabel('time')
self.ax1.set_ylabel('raw data')
self.line1 = Line2D([], [], color='blue')
self.line1_tail = Line2D([], [], color='red', linewidth=2)
self.line1_head = Line2D([], [], color='red', marker='o', markeredgecolor='r')
self.ax1.add_line(self.line1)
self.ax1.add_line(self.line1_tail)
self.ax1.add_line(self.line1_head)
self.ax1.set_xlim(0, self.xlim - 1)
self.ax1.set_ylim(0, 100)
FigureCanvas.__init__(self, self.fig)
TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)
def new_frame_seq(self):
return iter(range(self.n.size))
def _init_draw(self):
lines = [self.line1, self.line1_tail, self.line1_head]
for l in lines:
l.set_data([], [])
def addData(self, value):
self.addedData.append(value)
def zoomIn(self, value):
bottom = self.ax1.get_ylim()[0]
top = self.ax1.get_ylim()[1]
bottom += value
top -= value
self.ax1.set_ylim(bottom,top)
self.draw()
def _step(self, *args):
# Extends the _step() method for the TimedAnimation class.
try:
TimedAnimation._step(self, *args)
except Exception as e:
self.abc += 1
print(str(self.abc))
TimedAnimation._stop(self)
pass
def _draw_frame(self, framedata):
margin = 2
while(len(self.addedData) > 0):
self.y = np.roll(self.y, -1)
self.y[-1] = self.addedData[0]
del(self.addedData[0])
self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]
''' End Class '''
# You need to setup a signal slot mechanism, to
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QtCore.QObject):
data_signal = QtCore.pyqtSignal(float)
''' End Class '''
def dataSendLoop(addData_callbackFunc):
# Setup the signal-slot mechanism.
mySrc = Communicate()
mySrc.data_signal.connect(addData_callbackFunc)
# Simulate some data
n = np.linspace(0, 499, 500)
y = 50 + 25*(np.sin(n / 8.3)) + 10*(np.sin(n / 7.5)) - 5*(np.sin(n / 1.5))
i = 0
while(True):
if(i > 499):
i = 0
time.sleep(0.1)
mySrc.data_signal.emit(y[i]) # <- Here you emit a signal!
i += 1
###
###
if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
''''''
我最近重写了 PyQt5 的代码。
PyQt5 代码:
###################################################################
# #
# PLOT A LIVE GRAPH (PyQt5) #
# ----------------------------- #
# EMBED A MATPLOTLIB ANIMATION INSIDE YOUR #
# OWN GUI! #
# #
###################################################################
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import functools
import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import time
import threading
class CustomMainWindow(QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# Define the geometry of the main window
self.setGeometry(300, 300, 800, 400)
self.setWindowTitle("my first window")
# Create FRAME_A
self.FRAME_A = QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QColor(210,210,235,255).name())
self.LAYOUT_A = QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)
# Place the zoom button
self.zoomBtn = QPushButton(text = 'zoom')
self.zoomBtn.setFixedSize(100, 50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))
# Place the matplotlib figure
self.myFig = CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig, *(0,1))
# Add the callbackfunc to ..
myDataLoop = threading.Thread(name = 'myDataLoop', target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
myDataLoop.start()
self.show()
return
def zoomBtnAction(self):
print("zoom in")
self.myFig.zoomIn(5)
return
def addData_callbackFunc(self, value):
# print("Add data: " + str(value))
self.myFig.addData(value)
return
''' End Class '''
class CustomFigCanvas(FigureCanvas, TimedAnimation):
def __init__(self):
self.addedData = []
print(matplotlib.__version__)
# The data
self.xlim = 200
self.n = np.linspace(0, self.xlim - 1, self.xlim)
a = []
b = []
a.append(2.0)
a.append(4.0)
a.append(2.0)
b.append(4.0)
b.append(3.0)
b.append(4.0)
self.y = (self.n * 0.0) + 50
# The window
self.fig = Figure(figsize=(5,5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
# self.ax1 settings
self.ax1.set_xlabel('time')
self.ax1.set_ylabel('raw data')
self.line1 = Line2D([], [], color='blue')
self.line1_tail = Line2D([], [], color='red', linewidth=2)
self.line1_head = Line2D([], [], color='red', marker='o', markeredgecolor='r')
self.ax1.add_line(self.line1)
self.ax1.add_line(self.line1_tail)
self.ax1.add_line(self.line1_head)
self.ax1.set_xlim(0, self.xlim - 1)
self.ax1.set_ylim(0, 100)
FigureCanvas.__init__(self, self.fig)
TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)
return
def new_frame_seq(self):
return iter(range(self.n.size))
def _init_draw(self):
lines = [self.line1, self.line1_tail, self.line1_head]
for l in lines:
l.set_data([], [])
return
def addData(self, value):
self.addedData.append(value)
return
def zoomIn(self, value):
bottom = self.ax1.get_ylim()[0]
top = self.ax1.get_ylim()[1]
bottom += value
top -= value
self.ax1.set_ylim(bottom,top)
self.draw()
return
def _step(self, *args):
# Extends the _step() method for the TimedAnimation class.
try:
TimedAnimation._step(self, *args)
except Exception as e:
self.abc += 1
print(str(self.abc))
TimedAnimation._stop(self)
pass
return
def _draw_frame(self, framedata):
margin = 2
while(len(self.addedData) > 0):
self.y = np.roll(self.y, -1)
self.y[-1] = self.addedData[0]
del(self.addedData[0])
self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]
return
''' End Class '''
# You need to setup a signal slot mechanism, to
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QObject):
data_signal = pyqtSignal(float)
''' End Class '''
def dataSendLoop(addData_callbackFunc):
# Setup the signal-slot mechanism.
mySrc = Communicate()
mySrc.data_signal.connect(addData_callbackFunc)
# Simulate some data
n = np.linspace(0, 499, 500)
y = 50 + 25*(np.sin(n / 8.3)) + 10*(np.sin(n / 7.5)) - 5*(np.sin(n / 1.5))
i = 0
while(True):
if(i > 499):
i = 0
time.sleep(0.1)
mySrc.data_signal.emit(y[i]) # <- Here you emit a signal!
i += 1
###
###
if __name__== '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
试试吧。将此代码复制粘贴到新的 python 文件中,然后运行它。你应该得到一个漂亮、流畅的图形:
评论
dataSendLoop
daemon = True
conda install pyqt=4
顶部(和许多其他)答案是建立在 之上的,但这是在 matplotlib 中对情节进行动画处理的旧方法。它不仅速度慢,而且会导致每次更新时都会引起焦点(我很难停止绘制 python 过程)。plt.pause()
TL的;DR:您可能想要使用(如文档中所述)。matplotlib.animation
在挖掘了各种答案和代码片段之后,这实际上被证明是我无限绘制传入数据的一种流畅方式。
这是我的代码,用于快速入门。它每 200 毫秒以 [0, 100] 中的随机数无限绘制当前时间,同时还处理视图的自动重新缩放:
from datetime import datetime
from matplotlib import pyplot
from matplotlib.animation import FuncAnimation
from random import randrange
x_data, y_data = [], []
figure = pyplot.figure()
line, = pyplot.plot_date(x_data, y_data, '-')
def update(frame):
x_data.append(datetime.now())
y_data.append(randrange(0, 100))
line.set_data(x_data, y_data)
figure.gca().relim()
figure.gca().autoscale_view()
return line,
animation = FuncAnimation(figure, update, interval=200)
pyplot.show()
您还可以像 FuncAnimation 文档中那样探索更好的性能。blit
文档中的示例:blit
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
评论
for i in range(1000): x,y = some func_func()
some_func()
x,y
FuncAnimation
pyploy.show()
update
pyplot.show
update
interval
另一种选择是散景。IMO,至少对于实时绘图来说,它是一个很好的选择。以下是问题中代码的散景版本:
from bokeh.plotting import curdoc, figure
import random
import time
def update():
global i
temp_y = random.random()
r.data_source.stream({'x': [i], 'y': [temp_y]})
i += 1
i = 0
p = figure()
r = p.circle([], [])
curdoc().add_root(p)
curdoc().add_periodic_callback(update, 100)
为了运行它:
pip3 install bokeh
bokeh serve --show test.py
散景通过 WebSocket 通信在 Web 浏览器中显示结果。当数据由远程无头服务器进程生成时,它特别有用。
评论
实时绘制 CPU 使用率的示例用例。
import time
import psutil
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
i = 0
x, y = [], []
while True:
x.append(i)
y.append(psutil.cpu_percent())
ax.plot(x, y, color='b')
fig.canvas.draw()
ax.set_xlim(left=max(0, i - 50), right=i + 50)
fig.show()
plt.pause(0.05)
i += 1
评论
这是使用 while 循环绘制动态实时 matplot 绘图动画的正确方法
pip install celluloid # 这将捕获图像/动画
import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera # getting the camera
import matplotlib.animation as animation
from IPython import display
import time
from IPython.display import HTML
import warnings
%matplotlib notebook
warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')
fig = plt.figure() #Empty fig object
ax = fig.add_subplot() #Empty axis object
camera = Camera(fig) # Camera object to capture the snap
def f(x):
''' function to create a sine wave'''
return np.sin(x) + np.random.normal(scale=0.1, size=len(x))
l = []
while True:
value = np.random.randint(9) #random number generator
l.append(value) # appneds each time number is generated
X = np.linspace(10, len(l)) # creates a line space for x axis, Equal to the length of l
for i in range(10): #plots 10 such lines
plt.plot(X, f(X))
fig.show() #shows the figure object
fig.canvas.draw()
camera.snap() # camera object to capture teh animation
time.sleep(1)
并用于保存等:
animation = camera.animate(interval = 200, repeat = True, repeat_delay = 500)
HTML(animation.to_html5_video())
animation.save('abc.mp4') # to save
输出为:
保留线型的圆形缓冲区的实时绘图:
import os
import time
import psutil
import collections
import matplotlib.pyplot as plt
pts_n = 100
x = collections.deque(maxlen=pts_n)
y = collections.deque(maxlen=pts_n)
(line, ) = plt.plot(x, y, linestyle="--")
my_process = psutil.Process(os.getpid())
t_start = time.time()
while True:
x.append(time.time() - t_start)
y.append(my_process.cpu_percent())
line.set_xdata(x)
line.set_ydata(y)
plt.gca().relim()
plt.gca().autoscale_view()
plt.pause(0.1)
评论
我以略有不同的观点创建了此代码:
import numpy as np
from matplotlib import pyplot
figure = pyplot.figure()
# get current axes # If figure.axes == [], a new one is created
axes = figure.gca()
axes.axis([0, 1000, 0, 1])
figure.show()
x_val, x_values, y_values = 0, list(), list()
while x_val < 1000:
if not pyplot.fignum_exists(figure.number):
break # break when window is closed
y_val = np.random.random()
x_values.append(x_val)
y_values.append(y_val)
axes.scatter(x_val, y_val)
x_val += 1
figure.canvas.draw()
figure.canvas.flush_events()
评论