向PYQT图表添加新值以按需更新图表
我正在尝试在Pyqt5中使用Pyqtgraph制作烛台图,每次调用方法都会使用新数据更新图形。 我命名了DPoint_Var类中的New_dpoint,该方法将每次激活的数组中添加了另一行随机数据,将由烛台类读取。
经过很长时间,我正在刷我的python,我才刚刚开始学习PYQT库并试图理解它。
截至目前,我对此脚本的结果有一个问题。 由于某种原因,当我运行脚本时,我会收到此错误
------------------------------------------------------------------------
---
IndexError Traceback (most recent call last)
Input In [5], in <cell line: 99>()
96 dpoint = dpoint_var()
97 dpoint.new_dpoint()
---> 99 item = CandlestickItem(dpoint_var.data2)
100 plt = pg.plot()
101 plt.addItem(item)
Input In [5], in CandlestickItem.__init__(self, data)
64 pg.GraphicsObject.__init__(self)
65 self.data = data ## data must have fields: time, open, close, min, max
---> 66 self.generatePicture()
Input In [5], in CandlestickItem.generatePicture(self)
72 p = QtGui.QPainter(self.picture)
73 p.setPen(pg.mkPen('w'))
---> 74 width = (self.data[1][0] - self.data[0][0]) / 3.
75 for (t, open, close, min, max) in self.data:
76 p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
IndexError: index 1 is out of bounds for axis 0 with size 0
,这似乎表明dpoint.new_dpoint方法未被激活,但我不明白为什么不。
另外,我还试图找到一种方法来从外部函数而不是从QTimer函数内部更新PyqtGraph,因为我只希望在从外部源可用的新数据(而不是定期间隔)中刷新数据。 在不重新绘制整个图表的情况下,正确执行此操作的方法是什么?
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot, QtCore, QtGui
import sys
import os
from random import randint
class dpoint_var:
dpoint = 20
data = np.empty((0,5), dtype = float)
data2 = np.empty((0,5), dtype = float)
def __init__(self):
def return_dpoint():
return self.dpoint
def new_dpoint(self):
self.data = np.random.uniform(low=0.0005, high=0.01, size=(self.dpoint,5))
self.data2 = np.empty((self.dpoint,5), dtype = float)
#set the first column to an ordered number line
x = 0
for i in range(len(self.data[:,0])):
self.data2[i][0] = x
x += 1
#set the second column to the opening data
for i in range(len(self.data[:,1])):
if i > 10:
self.data2[i][1] = self.data[i-10][1]
else:
self.data2[i][1] = self.data[i][1]
#set the third column to the closing data
for i in range(len(self.data[:,2])):
self.data2[i][2] = self.data[i][1]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,3])):
if i > 10:
self.data2[i][3] = self.data[i-10:i, 1].min()
else:
for i in range(len(self.data[:,3])):
self.data2[i][3] = self.data[i][3]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,4])):
if i > 10:
self.data2[i][4] = self.data[i-1:i, 1].max()
else:
for i in range(len(self.data[:,4])):
self.data2[i][4] = self.data[i][4]
dpoint.dpoint +=1
--------------------------------------------------------------------------------------
## Create a subclass of GraphicsObject.
## The only required methods are paint() and boundingRect()
## (see QGraphicsItem documentation)
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data):
pg.GraphicsObject.__init__(self)
self.data = data ## data must have fields: time, open, close, min, max
self.generatePicture()
def generatePicture(self):
## pre-computing a QPicture object allows paint() to run much more quickly,
## rather than re-drawing the shapes every time.
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('w'))
width = (self.data[1][0] - self.data[0][0]) / 3.
for (t, open, close, min, max) in self.data:
p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
if open > close:
p.setBrush(pg.mkBrush('r'))
else:
p.setBrush(pg.mkBrush('g'))
p.drawRect(QtCore.QRectF(t-width, open, width*2, close-open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
## boundingRect _must_ indicate the entire area that will be drawn on
## or else we will get artifacts and possibly crashing.
## (in this case, QPicture does all the work of computing the bouning rect for us)
return QtCore.QRectF(self.picture.boundingRect())
--------------------------------------------------------------------------------------
dpoint = dpoint_var()
dpoint.new_dpoint()
item = CandlestickItem(dpoint_var.data2)
plt = pg.plot()
plt.addItem(item)
plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
app = QtWidgets.QApplication(sys.argv)
timer = QtCore.QTimer()
timer.timeout.connect(dpoint.new_dpoint)
timer.start(1000)
w = MainWindow()
w.show()
sys.exit(app.exec_())
编辑:
多亏了MusicAmante的建议,我设法解决了错误。先生,谢谢您的宝贵建议:)
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot, QtCore, QtGui
import sys
import os
from random import randint
class Dpoint_var:
dpoint = 20
def __init__(self):
def return_dpoint():
data = np.empty((0,5), dtype = float)
data2 = np.empty((0,5), dtype = float)
return self.dpoint
def new_dpoint(self):
self.data = np.random.uniform(low=0.0005, high=0.01, size=(self.dpoint,5))
self.data2 = np.empty((self.dpoint,5), dtype = float)
#set the first column to an ordered number line
x = 0
for i in range(len(self.data[:,0])):
self.data2[i][0] = x
x += 1
#set the second column to the opening data
for i in range(len(self.data[:,1])):
if i > 10:
self.data2[i][1] = self.data[i-10][1]
else:
self.data2[i][1] = self.data[i][1]
#set the third column to the closing data
for i in range(len(self.data[:,2])):
self.data2[i][2] = self.data[i][1]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,3])):
if i > 10:
self.data2[i][3] = self.data[i-10:i, 1].min()
else:
for i in range(len(self.data[:,3])):
self.data2[i][3] = self.data[i][3]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,4])):
if i > 10:
self.data2[i][4] = self.data[i-1:i, 1].max()
else:
for i in range(len(self.data[:,4])):
self.data2[i][4] = self.data[i][4]
dpoint.dpoint +=1
## Create a subclass of GraphicsObject.
## The only required methods are paint() and boundingRect()
## (see QGraphicsItem documentation)
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data):
pg.GraphicsObject.__init__(self)
self.data = data ## data must have fields: time, open, close, min, max
self.generatePicture()
def generatePicture(self):
## pre-computing a QPicture object allows paint() to run much more quickly,
## rather than re-drawing the shapes every time.
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('w'))
width = (self.data[1][0] - self.data[0][0]) / 3.
for (t, open, close, min, max) in self.data:
p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
if open > close:
p.setBrush(pg.mkBrush('r'))
else:
p.setBrush(pg.mkBrush('g'))
p.drawRect(QtCore.QRectF(t-width, open, width*2, close-open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
## boundingRect _must_ indicate the entire area that will be drawn on
## or else we will get artifacts and possibly crashing.
## (in this case, QPicture does all the work of computing the bouning rect for us)
return QtCore.QRectF(self.picture.boundingRect())
dpoint = Dpoint_var()
dpoint.new_dpoint()
item = CandlestickItem(dpoint.data2)
plt = pg.plot()
plt.addItem(item)
plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
app = QtWidgets.QApplication(sys.argv)
timer = QtCore.QTimer()
timer.timeout.connect(dpoint.new_dpoint)
timer.start(10)
sys.exit(app.exec_())
但是,我仍然很难找到更新图表的正确方法。 我希望TP能够从外部信号而不是QTimer更新图表,但是即使在QTimer中,我也找不到可以重新加载图表的正确语法。 据说计时器正在为数组添加新数据,但没有加载图表。 但是,我无法弄清楚这是这样做的。 QT库是如此之大,非结构化和深奥。
有建议吗?
I am trying to make a candlestick chart with pyqtgraph in PyQt5 that updates the graph with new data every time a method is called.
I have named this method dpoint.new_dpoint in the dpoint_var class which adds another row of randomized data to an array every time it is activated, to be read by the candlestick class.
I'm brushing up on my python after a long absence from it and I am just beginning to learn the PyQt library and trying to make sense of it.
As of right now I am having an issue with the result of this script.
For some reason when I run the script I get this error
------------------------------------------------------------------------
---
IndexError Traceback (most recent call last)
Input In [5], in <cell line: 99>()
96 dpoint = dpoint_var()
97 dpoint.new_dpoint()
---> 99 item = CandlestickItem(dpoint_var.data2)
100 plt = pg.plot()
101 plt.addItem(item)
Input In [5], in CandlestickItem.__init__(self, data)
64 pg.GraphicsObject.__init__(self)
65 self.data = data ## data must have fields: time, open, close, min, max
---> 66 self.generatePicture()
Input In [5], in CandlestickItem.generatePicture(self)
72 p = QtGui.QPainter(self.picture)
73 p.setPen(pg.mkPen('w'))
---> 74 width = (self.data[1][0] - self.data[0][0]) / 3.
75 for (t, open, close, min, max) in self.data:
76 p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
IndexError: index 1 is out of bounds for axis 0 with size 0
which seems to indicate that the dpoint.new_dpoint method was not activated but I don't see why not.
Also I am trying to find a way to update the pyqtgraph from an external function rather than from inside the Qtimer function as I only want the data to refresh when new data is available from an external source, not at a regular interval.
What is the correct way to do this without redrawing the entire chart?
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot, QtCore, QtGui
import sys
import os
from random import randint
class dpoint_var:
dpoint = 20
data = np.empty((0,5), dtype = float)
data2 = np.empty((0,5), dtype = float)
def __init__(self):
def return_dpoint():
return self.dpoint
def new_dpoint(self):
self.data = np.random.uniform(low=0.0005, high=0.01, size=(self.dpoint,5))
self.data2 = np.empty((self.dpoint,5), dtype = float)
#set the first column to an ordered number line
x = 0
for i in range(len(self.data[:,0])):
self.data2[i][0] = x
x += 1
#set the second column to the opening data
for i in range(len(self.data[:,1])):
if i > 10:
self.data2[i][1] = self.data[i-10][1]
else:
self.data2[i][1] = self.data[i][1]
#set the third column to the closing data
for i in range(len(self.data[:,2])):
self.data2[i][2] = self.data[i][1]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,3])):
if i > 10:
self.data2[i][3] = self.data[i-10:i, 1].min()
else:
for i in range(len(self.data[:,3])):
self.data2[i][3] = self.data[i][3]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,4])):
if i > 10:
self.data2[i][4] = self.data[i-1:i, 1].max()
else:
for i in range(len(self.data[:,4])):
self.data2[i][4] = self.data[i][4]
dpoint.dpoint +=1
--------------------------------------------------------------------------------------
## Create a subclass of GraphicsObject.
## The only required methods are paint() and boundingRect()
## (see QGraphicsItem documentation)
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data):
pg.GraphicsObject.__init__(self)
self.data = data ## data must have fields: time, open, close, min, max
self.generatePicture()
def generatePicture(self):
## pre-computing a QPicture object allows paint() to run much more quickly,
## rather than re-drawing the shapes every time.
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('w'))
width = (self.data[1][0] - self.data[0][0]) / 3.
for (t, open, close, min, max) in self.data:
p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
if open > close:
p.setBrush(pg.mkBrush('r'))
else:
p.setBrush(pg.mkBrush('g'))
p.drawRect(QtCore.QRectF(t-width, open, width*2, close-open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
## boundingRect _must_ indicate the entire area that will be drawn on
## or else we will get artifacts and possibly crashing.
## (in this case, QPicture does all the work of computing the bouning rect for us)
return QtCore.QRectF(self.picture.boundingRect())
--------------------------------------------------------------------------------------
dpoint = dpoint_var()
dpoint.new_dpoint()
item = CandlestickItem(dpoint_var.data2)
plt = pg.plot()
plt.addItem(item)
plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
app = QtWidgets.QApplication(sys.argv)
timer = QtCore.QTimer()
timer.timeout.connect(dpoint.new_dpoint)
timer.start(1000)
w = MainWindow()
w.show()
sys.exit(app.exec_())
EDIT:
Thanks to suggestions from musicamante I managed to resolve the error. Thank you sir for your valuable advice :)
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot, QtCore, QtGui
import sys
import os
from random import randint
class Dpoint_var:
dpoint = 20
def __init__(self):
def return_dpoint():
data = np.empty((0,5), dtype = float)
data2 = np.empty((0,5), dtype = float)
return self.dpoint
def new_dpoint(self):
self.data = np.random.uniform(low=0.0005, high=0.01, size=(self.dpoint,5))
self.data2 = np.empty((self.dpoint,5), dtype = float)
#set the first column to an ordered number line
x = 0
for i in range(len(self.data[:,0])):
self.data2[i][0] = x
x += 1
#set the second column to the opening data
for i in range(len(self.data[:,1])):
if i > 10:
self.data2[i][1] = self.data[i-10][1]
else:
self.data2[i][1] = self.data[i][1]
#set the third column to the closing data
for i in range(len(self.data[:,2])):
self.data2[i][2] = self.data[i][1]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,3])):
if i > 10:
self.data2[i][3] = self.data[i-10:i, 1].min()
else:
for i in range(len(self.data[:,3])):
self.data2[i][3] = self.data[i][3]
#set the fourth column to the minimum bat value for the time period
for i in range(len(self.data[:,4])):
if i > 10:
self.data2[i][4] = self.data[i-1:i, 1].max()
else:
for i in range(len(self.data[:,4])):
self.data2[i][4] = self.data[i][4]
dpoint.dpoint +=1
## Create a subclass of GraphicsObject.
## The only required methods are paint() and boundingRect()
## (see QGraphicsItem documentation)
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data):
pg.GraphicsObject.__init__(self)
self.data = data ## data must have fields: time, open, close, min, max
self.generatePicture()
def generatePicture(self):
## pre-computing a QPicture object allows paint() to run much more quickly,
## rather than re-drawing the shapes every time.
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('w'))
width = (self.data[1][0] - self.data[0][0]) / 3.
for (t, open, close, min, max) in self.data:
p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
if open > close:
p.setBrush(pg.mkBrush('r'))
else:
p.setBrush(pg.mkBrush('g'))
p.drawRect(QtCore.QRectF(t-width, open, width*2, close-open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
## boundingRect _must_ indicate the entire area that will be drawn on
## or else we will get artifacts and possibly crashing.
## (in this case, QPicture does all the work of computing the bouning rect for us)
return QtCore.QRectF(self.picture.boundingRect())
dpoint = Dpoint_var()
dpoint.new_dpoint()
item = CandlestickItem(dpoint.data2)
plt = pg.plot()
plt.addItem(item)
plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
app = QtWidgets.QApplication(sys.argv)
timer = QtCore.QTimer()
timer.timeout.connect(dpoint.new_dpoint)
timer.start(10)
sys.exit(app.exec_())
However I am still having trouble finding the correct method to update the chart.
I want to be able tp update the chart from an external signal rather than from the Qtimer, however even in Qtimer I can't find the proper syntax to reload the chart.
The timer is supposedly adding new data to the array but it is not loading the chart.
However I can't figure out the syntax to do so. Qt library is so large, unstructured, and esoteric.
Any advice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论