文章目录
1 下载安装:
pip install QCustomPlot2
升级python版本后(3.12)前面好像无对应版本,下载另一个类似的,接口都完全一样
pip install QCustomPlot_PyQt5
2 基本折线图
效果如下:
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime
from PyQt5.QtGui import QBrush,QPen,QColor
import sys,random
import QCustomPlot2
from QCustomPlot2 import QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPGraph
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(600,600)
self.setWindowTitle("QCustomPlot折线图Demo")
self.layout = QVBoxLayout(self)
self.m_plot = QCustomPlot()
self.layout.addWidget(self.m_plot)
self.x = [ i for i in range(20)]
self.y = [random.randint(0,20) for i in range(20)]
self.m_plot.addGraph()
self.pen = QPen()
#self.pen.setStyle(Qt.DotLine)
self.pen.setWidth(2)
self.pen.setColor(QColor(255,0,0))
self.m_plot.graph(0).setPen(self.pen)
self.m_plot.graph(0).setLineStyle(QCPGraph.lsLine )
#self.m_plot.graph(0).setBrush(QBrush(QColor(0, 0, 255, 20)))
self.m_plot.graph(0).setData(self.x, self.y)
self.m_plot.xAxis.setVisible(True)
self.m_plot.yAxis.setVisible(True)
self.m_plot.xAxis.setLabel("x")
self.m_plot.yAxis.setLabel("y")
self.m_plot.xAxis.setRange(0,20)
self.m_plot.yAxis.setRange(0,20)
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())
3 设置点样式
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime
from PyQt5.QtGui import QBrush,QPen,QColor
import sys,random
import QCustomPlot2
from QCustomPlot2 import QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPGraph,QCPScatterStyle
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(600,600)
self.setWindowTitle("ScatterStyleDemo")
self.layout = QVBoxLayout(self)
self.m_plot = QCustomPlot()
self.layout.addWidget(self.m_plot)
self.m_plot.legend.setVisible(True)
self.m_plot.legend.setRowSpacing(-3)
self.shapes = [QCPScatterStyle.ssCross,
QCPScatterStyle.ssPlus,
QCPScatterStyle.ssCircle,
QCPScatterStyle.ssDisc,
QCPScatterStyle.ssSquare,
QCPScatterStyle.ssDiamond,
QCPScatterStyle.ssStar,
QCPScatterStyle.ssTriangle,
QCPScatterStyle.ssTriangleInverted,
QCPScatterStyle.ssCrossSquare,
QCPScatterStyle.ssPlusSquare,
QCPScatterStyle.ssCrossCircle,
QCPScatterStyle.ssPlusCircle,
QCPScatterStyle.ssPeace,
QCPScatterStyle.ssCustom ]
self.names = [
"ssCross", "ssPlus", "ssCircle", "ssDisc", "ssSquare", "ssDiamond", "ssStar", "ssTriangle",
"ssTriangleInverted", "ssCrossSquare", "ssPlusSquare", "ssCrossCircle", "ssPlusCircle", "ssPeace", "ssCustom"]
self.pen = QPen()
for i in range(len(self.shapes)):
self.m_plot.addGraph()
self.pen.setColor(QColor( int(math.sin(i*0.3)*100+100), int(math.sin(i*0.6+0.7)*100+100), int(math.sin(i*0.4+0.6)*100+100)))
x,y = [],[]
for k in range(0,10):
#x[k] = k/10*4*3.14 + 0.01
#y[k] = 7*math.sin(x[k])/x[k] + (len(self.shapes) - i)*5
x.append(k/10*4*3.14 + 0.01)
y.append(7*math.sin(x[k])/x[k] + (len(self.shapes) - i)*5)
self.m_plot.graph().setData(x, y)
self.m_plot.graph().rescaleAxes(True)
self.m_plot.graph().setPen(self.pen)
self.m_plot.graph().setName(self.names[i])
self.m_plot.graph().setLineStyle(QCPGraph.lsLine)
if self.shapes != QCPGraph.lsLine:
self.m_plot.graph().setScatterStyle(QCPScatterStyle(self.shapes[i], 10))
else:
pass
#set blank axis lines:
self.m_plot.rescaleAxes()
self.m_plot.xAxis.setTicks(False)
self.m_plot.yAxis.setTicks(False)
self.m_plot.xAxis.setTickLabels(False)
self.m_plot.yAxis.setTickLabels(False)
self.m_plot.axisRect().setupFullAxesBox()
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())
4 Plot Screenshots: Item Demo
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime, QMargins,QTimer
from PyQt5.QtGui import QBrush,QPen,QColor,QFont
import sys,random
import QCustomPlot2
from QCustomPlot2 import QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPGraph,QCPScatterStyle,QCPItemBracket,QCPItemText,QCPItemTracer
from QCustomPlot2 import *
M_PI = 3.14159265358979323846
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(600,600)
self.setWindowTitle("ItemDemo")
self.layout = QVBoxLayout(self)
self.m_plot = QCustomPlot()
self.layout.addWidget(self.m_plot)
self.m_plot.setInteractions(QCP.iRangeDrag | QCP.iRangeZoom)
graph = self.m_plot.addGraph()
n = 500
phase = 0
k = 3
x,y = [],[]
for i in range(n):
x.append(i/(n-1)*34-17)
y.append(math.exp( (-x[i]*x[i]/20))*math.sin(k*x[i]+phase))
graph.setData(x, y)
graph.setPen(QPen(Qt.blue))
graph.rescaleKeyAxis()
self.m_plot.yAxis.setRange(-1.45, 1.65)
#self.m_plot.xAxis.grid().setZeroLinePen(Qt.NoPen)
#add the bracket at the top:
bracket = QCPItemBracket(self.m_plot)
bracket.left.setCoords(-8, 1.1)
bracket.right.setCoords(8, 1.1)
bracket.setLength(13)
#add the text label at the top:
wavePacketText = QCPItemText(self.m_plot)
wavePacketText.position.setParentAnchor(bracket.center)
wavePacketText.position.setCoords(0, -10)
wavePacketText.setPositionAlignment(Qt.AlignBottom|Qt.AlignHCenter)
wavePacketText.setText("Wavepacket")
#add the phase tracer (red circle) which sticks to the graph data (and gets updated in bracketDataSlot by timer event):
phaseTracer = QCPItemTracer(self.m_plot)
itemDemoPhaseTracer = phaseTracer
phaseTracer.setGraph(graph)
phaseTracer.setGraphKey((M_PI*1.5-phase)/k)
phaseTracer.setInterpolating(True)
phaseTracer.setStyle(QCPItemTracer.tsCircle)
phaseTracer.setPen(QPen(Qt.red))
phaseTracer.setBrush(Qt.red)
phaseTracer.setSize(7)
#add label for phase tracer:
phaseTracerText = QCPItemText(self.m_plot)
phaseTracerText.position.setType(QCPItemPosition.ptAxisRectRatio)
phaseTracerText.setPositionAlignment(Qt.AlignRight|Qt.AlignBottom)
phaseTracerText.position.setCoords(1.0, 0.95)
phaseTracerText.setText("Points of fixed\nphase define\nphase velocity vp")
phaseTracerText.setTextAlignment(Qt.AlignLeft)
phaseTracerText.setPadding(QMargins(8, 0, 0, 0))
#add arrow pointing at phase tracer, coming from label:
phaseTracerArrow = QCPItemCurve(self.m_plot)
phaseTracerArrow.start.setParentAnchor(phaseTracerText.left)
phaseTracerArrow.startDir.setParentAnchor(phaseTracerArrow.start)
phaseTracerArrow.startDir.setCoords(-40, 0) # direction 30 pixels to the left of parent anchor (tracerArrow.start)
phaseTracerArrow.end.setParentAnchor(phaseTracer.position)
phaseTracerArrow.end.setCoords(10, 10)
phaseTracerArrow.endDir.setParentAnchor(phaseTracerArrow.end)
phaseTracerArrow.endDir.setCoords(30, 30)
headarrow = QCPLineEnding()
headarrow.setStyle(QCPLineEnding.esSpikeArrow)
phaseTracerArrow.setHead(headarrow)
tailarrow = QCPLineEnding( QCPLineEnding.esBar, phaseTracerText.bottom.pixelPosition().y()-phaseTracerText.top.pixelPosition().y()*0.85)
phaseTracerArrow.setTail(tailarrow)
#add the group velocity tracer (green circle):
groupTracer = QCPItemTracer(self.m_plot)
groupTracer.setGraph(graph)
groupTracer.setGraphKey(5.5)
groupTracer.setInterpolating(True)
groupTracer.setStyle(QCPItemTracer.tsCircle)
groupTracer.setPen(QPen(Qt.green))
groupTracer.setBrush(Qt.green)
groupTracer.setSize(7)
#add the group velocity tracer (green circle):
groupTracer = QCPItemTracer(self.m_plot)
groupTracer.setGraph(graph)
groupTracer.setGraphKey(5.5)
groupTracer.setInterpolating(True)
groupTracer.setStyle(QCPItemTracer.tsCircle)
groupTracer.setPen(QPen(Qt.green))
groupTracer.setBrush(Qt.green)
groupTracer.setSize(7)
#add label for group tracer:
groupTracerText = QCPItemText(self.m_plot)
groupTracerText.position.setType(QCPItemPosition.ptAxisRectRatio)
groupTracerText.setPositionAlignment(Qt.AlignRight|Qt.AlignTop)
groupTracerText.position.setCoords(1.0, 0.20) # lower right corner of axis rect
groupTracerText.setText("Fixed positions in\nwave packet define\ngroup velocity vg")
groupTracerText.setTextAlignment(Qt.AlignLeft)
#groupTracerText.setFont(QFont(font().family(), 9))
groupTracerText.setPadding(QMargins(8, 0, 0, 0))
#add arrow pointing at group tracer, coming from label:
groupTracerArrow = QCPItemCurve(self.m_plot)
groupTracerArrow.start.setParentAnchor(groupTracerText.left)
groupTracerArrow.startDir.setParentAnchor(groupTracerArrow.start)
groupTracerArrow.startDir.setCoords(-40, 0) # direction 30 pixels to the left of parent anchor (tracerArrow.start)
groupTracerArrow.end.setCoords(5.5, 0.4)
groupTracerArrow.endDir.setParentAnchor(groupTracerArrow.end)
groupTracerArrow.endDir.setCoords(0, -40)
groupTracerArrow.setHead(QCPLineEnding(QCPLineEnding.esSpikeArrow))
groupTracerArrow.setTail(QCPLineEnding(QCPLineEnding.esBar, (groupTracerText.bottom.pixelPosition().y()-groupTracerText.top.pixelPosition().y())*0.85))
#add dispersion arrow:
arrow = QCPItemCurve(self.m_plot)
arrow.start.setCoords(1, -1.1)
arrow.startDir.setCoords(-1, -1.3)
arrow.endDir.setCoords(-5, -0.3)
arrow.end.setCoords(-10, -0.2)
arrow.setHead(QCPLineEnding(QCPLineEnding.esSpikeArrow))
#add the dispersion arrow label:
dispersionText = QCPItemText(self.m_plot)
dispersionText.position.setCoords(-6, -0.9)
dispersionText.setRotation(40)
dispersionText.setText("Dispersion with\nvp < vg")
#dispersionText.setFont(QFont(font().family(), 10))
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())
5 RealtimeDataDemo
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime, QMargins,QTimer,QTime
from PyQt5.QtGui import QBrush,QPen,QColor,QFont
import sys,random
import QCustomPlot2
from QCustomPlot2 import QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPGraph,QCPScatterStyle,QCPItemBracket,QCPItemText,QCPItemTracer
from QCustomPlot2 import *
timeStart = QTime.currentTime()
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(600,600)
self.setWindowTitle("Real Time Data Demo")
self.layout = QVBoxLayout(self)
self.customPlot = QCustomPlot(self)
self.layout.addWidget(self.customPlot)
self.customPlot.addGraph() # blue line
self.customPlot.graph(0).setPen(QPen(QColor(40, 110, 255)))
self.customPlot.addGraph() # red line
self.customPlot.graph(1).setPen(QPen(QColor(255, 110, 40)))
timeTicker = QCPAxisTickerTime()
timeTicker.setTimeFormat("%h:%m:%s")
self.customPlot.xAxis.setTicker(timeTicker)
self.customPlot.axisRect().setupFullAxesBox()
self.customPlot.yAxis.setRange(-1.2, 1.2)
# make left and bottom axes transfer their ranges to right and top axes:
self.customPlot.xAxis.rangeChanged[QCPRange].connect(self.customPlot.xAxis2.setRange)
self.customPlot.yAxis.rangeChanged[QCPRange].connect(self.customPlot.yAxis2.setRange)
dataTimer = QTimer(self)
dataTimer.timeout.connect(self.realtimeDataSlot)
dataTimer.start(10)
def realtimeDataSlot(self):
key = timeStart.msecsTo(QTime.currentTime())/1000.0
self.customPlot.graph(0).addData(key, math.sin(key))
#print(key, math.sin(key)+ random.randint(0,5))
self.customPlot.graph(1).addData(key, math.cos(key))
self.customPlot.xAxis.setRange(key, 8, Qt.AlignRight)
self.customPlot.replot()
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())
6 Simple Demo
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime
from PyQt5.QtGui import QBrush,QPen,QColor
import sys,random,math
import QCustomPlot_PyQt5
from QCustomPlot_PyQt5 import QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPGraph
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(800,600)
self.setWindowTitle("Simple Demo")
self.layout = QVBoxLayout(self)
self.customPlot = QCustomPlot()
self.layout.addWidget(self.customPlot)
self.customPlot.addGraph()
self.customPlot.graph(0).setPen(QPen(Qt.blue))
self.customPlot.graph(0).setBrush(QBrush(QColor(0, 0, 255, 20)))
self.customPlot.addGraph()
self.customPlot.graph(1).setPen(QPen(Qt.red))
x, y0,y1 = [], [], []
for i in range(251):
x.append(i)
y0.append(math.exp(-i/150.0)*math.cos(i/10.0))
y1.append(math.exp(-i/150.0))
self.customPlot.xAxis2.setVisible(True)
self.customPlot.xAxis2.setTickLabels(False)
self.customPlot.graph(0).setData(x,y0)
self.customPlot.graph(1).setData(x,y1)
self.customPlot.graph(0).rescaleAxes()
self.customPlot.graph(1).rescaleAxes(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())
7 Sinc Scatter Demo
#!/usr/bin/env python3
# -*- coding:GBK -*-
import os,sys,re
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QDateTime
from PyQt5.QtGui import QBrush,QPen,QColor,QFont
import sys,random,math
import QCustomPlot_PyQt5
from QCustomPlot_PyQt5 import *
class QCustomPlotDemo(QWidget):
def __init__(self):
super(QCustomPlotDemo, self).__init__()
self.resize(800,600)
self.setWindowTitle("Sinc Scatter Demo")
self.layout = QVBoxLayout(self)
self.customPlot = QCustomPlot()
self.layout.addWidget(self.customPlot)
self.customPlot.legend.setVisible(True)
self.customPlot.legend.setFont(QFont("Helvetica",9))
# set locale to english, so we get english decimal separator:
#self.customPlot.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom))
#add confidence band graphs:
self.customPlot.addGraph()
self.pen = QPen()
self.pen.setStyle(Qt.DotLine)
self.pen.setWidth(1)
self.pen.setColor(QColor(180,180,180))
self.customPlot.graph(0).setName("Confidence Band 68%")
self.customPlot.graph(0).setPen(self.pen)
self.customPlot.graph(0).setBrush(QBrush(QColor(255,50,30,20)))
self.customPlot.addGraph()
self.customPlot.legend.removeItem(self.customPlot.legend.itemCount()-1) # don't show two confidence band graphs in legend
self.customPlot.graph(1).setPen(self.pen)
self.customPlot.graph(0).setChannelFillGraph(self.customPlot.graph(1))
# add theory curve graph:
self.customPlot.addGraph()
self.pen.setStyle(Qt.DashLine)
self.pen.setWidth(2)
self.pen.setColor(Qt.red)
self.customPlot.graph(2).setPen(self.pen)
self.customPlot.graph(2).setName("Theory Curve")
# generate ideal sinc curve data and some randomly perturbed data for scatter plot:
x0, y0 = [], []
yConfUpper, yConfLower = [], []
for i in range(250):
temp = (i/249.0-0.5)*30+0.01
y0.append(math.sin(temp)/temp)
yConfUpper.append(y0[i]+0.15)
yConfLower.append(y0[i]-0.15)
x0.append(temp*1000)
x1, y1, y1err = [], [],[]
for i in range(50):
temp1 = 0
#pass data to graphs and let QCustomPlot determine the axes ranges so the whole thing is visible:
self.customPlot.graph(0).setData(x0, yConfUpper)
self.customPlot.graph(1).setData(x0, yConfLower)
self.customPlot.graph(2).setData(x0, y0)
#self.customPlot.graph(3).setData(x1, y1)
self.customPlot.graph(2).rescaleAxes()
#self.customPlot.graph(3).rescaleAxes(True)
# setup look of bottom tick labels:
self.customPlot.xAxis.setTickLabelRotation(30)
self.customPlot.xAxis.ticker().setTickCount(9)
self.customPlot.xAxis.setNumberFormat("ebc")
self.customPlot.xAxis.setNumberPrecision(1)
self.customPlot.xAxis.moveRange(-10)
# make top right axes clones of bottom left axes. Looks prettier:
self.customPlot.axisRect().setupFullAxesBox()
if __name__ == "__main__":
app = QApplication(sys.argv)
test = QCustomPlotDemo()
test.show()
sys.exit(app.exec_())