Проверьте, что элемент виден в окне просмотра без плагина:
Сначала определите верхнее и нижнее положения элемента. Затем определите положение нижней части окна просмотра (относительно верхней части страницы), добавив положение прокрутки в высоту окна просмотра.
Если нижнее положение окна просмотра больше, чем верхнее положение элемента, и верхнее положение окна просмотра меньше, чем нижнее положение элемента, элемент находится в окне просмотра (по крайней мере частично). Проще говоря, когда какая-либо часть элемента находится между верхней и нижней границами вашего окна просмотра, элемент отображается на вашем экране.
Теперь вы можете написать оператор if / else, где оператор if выполняется только при выполнении вышеуказанного условия.
В приведенном ниже коде выполняется то, что было описано выше:
//this function runs every time you are scrolling
$(window).scroll(function() {
var top_of_element = $("#element").offset().top;
var bottom_of_element = $("#element").offset().top + $("#element").outerHeight();
var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
var top_of_screen = $(window).scrollTop();
if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
// The element is visible, do something
}
else {
// The element is not visible, do something else
}
});
Этот ответ представляет собой краткое изложение того, что обсуждали далее Крис Бир и Энди. Надеюсь, это поможет кому-то еще, кто сталкивается с этим вопросом во время исследований, как я. Я также использовал ответ на следующий вопрос, чтобы сформулировать свой ответ: Показывать Div при прокрутке позиции .
Вот рабочая версия рассматриваемого кода (требуется, по крайней мере, версия Matplotlib 1.1.0 с 2011-11-14):
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()
Обратите внимание на некоторые изменения:
plt.pause(0.05)
для вывода новых данных, и он запускает цикл событий GUI (что позволяет взаимодействовать с мышью). Если вы заинтересованы в построении в реальном времени, я бы рекомендовал заглянуть в анимационный API matplotlib . В частности, использование blit
во избежание перерисовки фона на каждом кадре может дать вам существенную прирост скорости (~ 10x):
#!/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()
. Я добавил эти изменения в код выше.
– ali_m
2 February 2015 в 11:41
blit()
, похоже, очень «улучшением графика в реальном времени»? Если у вас есть разработчик / блог matplotlib, обсуждающий, почему / цель / намерение / мотивация были бы замечательными. (похоже, что эта новая blit-операция превратит Matplotlib только для автономных или очень медленно меняющихся данных, теперь вы можете использовать Matplotlib с очень быстрыми данными по обновлению ... почти как осциллограф).
– Trevor Boyd Smith
14 April 2016 в 13:43
show
, вероятно, не лучший выбор для этого. Вместо этого я буду использовать pyplot.draw()
. Вы также можете включить небольшую задержку (например, time.sleep(0.05)
) в цикле, чтобы вы могли видеть сюжеты. Если я сделаю эти изменения в вашем примере, это сработает для меня, и я вижу, что каждый пункт появляется по одному.
Ни один из методов не работал для меня. Но я нашел, что это . Графический график 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()
, но это был старый способ анимации сюжета в matplotlib.
TL; DR: вы можете захотеть использовать matplotlib.animation
(, как указано в документации ).
После того, как вы разыграли различные ответы и фрагменты кода, на самом деле это был плавный способ бесконечного рисования входящих данных.
Вот мой код для быстрого запуска. Он отображает текущее время со случайным числом в [0, 100) каждые 200 мс бесконечно, одновременно обрабатывая автоматическое масштабирование вида:
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()
Вы также можете исследовать blit
для еще большей производительности , как в документации FuncAnimation .
Я знаю, что немного опоздаю, чтобы ответить на этот вопрос. Тем не менее, я сделал код некоторое время назад для построения живых графиков, которые я хотел бы поделиться:
###################################################################
# #
# PLOTTING A LIVE GRAPH #
# ---------------------------- #
# 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_())
''''''
Просто попробуйте. Скопируйте этот код в новый файл python и запустите его. Вы должны получить красивый, плавно движущийся график:
dataSendLoop
продолжал работать в фоновом режиме при закрытии окна. Поэтому я решил добавить ключевое слово daemon = True
, чтобы решить эту проблему.
– K.Mulier
26 September 2016 в 09:21
conda install pyqt=4
сделал трюк.
– Reb.Cabin
29 June 2018 в 04:20
Проблема заключается в том, что вы ожидаете, что plt.show()
отобразит окно, а затем вернется. Это не так. Программа остановится в этот момент и возобновится только после закрытия окна. Вы должны проверить это: если вы закроете окно, а затем появится другое окно.
Чтобы решить эту проблему, просто вызовите plt.show()
один раз после вашего цикла. Затем вы получите полный сюжет. (Но не «построение в реальном времени»)
Вы можете попробовать установить ключевое слово-аргумент block
следующим образом: plt.show(block=False)
один раз в начале, а затем использовать .draw()
для обновления.
Я знаю, что этот вопрос старый, но теперь есть доступный пакет под названием drawow на GitHub как «python-drawow». Это дает интерфейс, подобный приводу MATLAB - вы можете легко обновить фигуру.
Пример для вашего варианта использования:
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- drawow - тонкая обертка вокруг plt.draw
, но обеспечивает возможность подтверждения (или отладки) после отображения фигуры.
Вот версия, которую я получил для работы в моей системе.
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)
Линия pullow (makeFig) может быть заменена на makeFig (); plt.draw (), и он все еще работает нормально.
Если вы хотите нарисовать и не замораживать свою нить при увеличении количества точек, вы должны использовать plt.pause () not time.sleep ()
im, используя следующий код, чтобы построить серию координат 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)
plt.axis()
, а вместо этого создавайте два списка x и y и вызывайтеplt.plot(x,y)
2. в своем цикле , добавьте новые значения данных в два списка. 3. вызовите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);
– Trevor Boyd Smith 13 April 2016 в 18:09