ython 的主要优势之一是探索性数据科学和可视化生态体系。一般的工具链为Pandas、numpy、sklearn 进行数据分析和使用matplotlib进行绘图。
但是如果需要自己自定义一个个性化的图形界面工具,则可能不是很合适。为了实现这种需求,可以使用PyQt构建GUI应用程序,但是可以使用上面的生态系工具构建自定义的复杂的数据驱动应用程序和交互式仪表板。
对于简单且高度交互的绘图,本文介绍一个Python GUI的绘图PyQtGraph。
PyQtGraph建立在Qt QGraphicsScene的原生库,可提供更好更高性能绘图能力,特别是对于实时数据,可以提供交互性和使用Qt图形小部件轻松自定义绘图的能力。
PyQtGraphzh主要特点有:
各种线图和散点图;
数据平移/缩放鼠标;
实时数据更新和显示,交互数据的快速绘制;
图像显示与互动的查找表和水平控制;
支持完全的类型(常见类型和Qt类型,比如RGB,RGBA,或亮度,QColor)
2D交互视图绘制;
交互式视窗旋转/缩放鼠标;
视频流的显示和实时交互;
网格的等值面渲染;
三维图形系统;
三维表面图和散点图;
实验数据切片的多维图像任意角度的函数(比如,对MRI数据处理);
更容易编程的基本的3D场景图;
对感兴趣的控制区选择和数据显示;
交互标记垂直/水平的地块的位置和区域;
从图像中选择任意区域的部件和自动切片数据匹配;
为了使用PyQtGraph做图,必须先安装该模块。PyQtGraph依赖Pyhon 3.7和PyQt,所以需要先安装这些库。
在Pyhon 3.7环境下,可以用:
pip install qt
pip install pyqt
然后
pip install pyqtgraph
为了方便可以使用anaconda环境,这样只需安装
conda install qt
conda install pyqt
然后
conda install pyqtgraph
在PyQtGraph中,所有图都是使用PlotWidget小部件。小部件提供了canvas,可以在其上添加和配置任何类型的绘图。在hood下,绘图小部件使用本机Qt QGraphicsScene。例如,我们创建一个PlotWidget至于任何其他小部件的例子:
from PyQt6 import QtWidgets
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget=pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
x=[1, 2, 3, 4, 5, 6, 7, 8]
y=[3567.44,3462.95,3309.75,3167.13,3508.70,3284.83,3313.58,3268.02]
self.graphWidget.plot(x, y)
def main():
app=QtWidgets.QApplication(sys.argv)
main=MainWindow()
main.show()
sys.exit(app.exec())
if __name__=='__main__':
main()
PyQtGraph 的默认绘图样式非常简单——黑色背景和细(几乎不可见)白线。在下一节中,我们将看看 PyQtGraph 中有哪些可用选项来改善绘图的外观和可用性。
PyQtGraph继承了Qt的QGraphicsScene渲染图表,可以实现使用所有标准Qt线条和形状样式选项。PyQtGraph提供了一个API用于使用这些来绘制绘图和管理绘图画布。
下面我们将介绍创建和自定义绘图所需的最常见的样式功能。
可以通过调用.setBackground来改变背景颜色。PlotWidget实例(在 self.graphWidget)。下面的代码将通过传入字符串“w”将背景设置为白色。
self.graphWidget.setBackground('w')
可以随时设置(和更新)绘图的背景颜色。
from PyQt5 import QtWidgets
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget=pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
x=[1, 2, 3, 4, 5, 6, 7, 8]
y=[3567.44,3462.95,3309.75,3167.13,3508.70,3284.83,3313.58,3268.02]
self.graphWidget.setTitle("Chongchong", color="b", size="30pt")
self.graphWidget.plot(x, y)
def main():
app=QtWidgets.QApplication(sys.argv)
main=MainWindow()
main.show()
sys.exit(app.exec())
if __name__=='__main__':
main()
有许多使用单个字母的简单颜色表示,这是基于matplotlib. 主意这种表示中表示黑色的是“k”。
除了这些单字母代码之外,还可以使用十六进制的RGB和RGBA 设置更复杂的颜色,
比如 #672922
self.graphWidget.setBackground('#bbccaa')
RGB和RGBA值可以分别作为3元组或4元组传入,使用值 0-255。
self.graphWidget.setBackground((100,50,255)) # RGB each 0-255
self.graphWidget.setBackground((100,50,255,25))
最后,还可以使用Qt的颜色表示法QColor:
from PyQt5 import QtGui
self.graphWidget.setBackground(QtGui.QColor(100,50,254,25))
如果使用特定的QColor应用程序中其他位置的对象,或将绘图背景设置为默认的GUI背景颜色。
color=self.palette().color(QtGui.QPalette.Window)
self.graphWidget.setBackground(color)
PyQtGraph中的线条也是使用标准Qt绘制的 QPen类型,可以像在任何其他操作中一样完全控制线条绘制QGraphicsScene绘画。要使用笔绘制一条线,只需创建一个新的QPen实例并将其传递给 plot方法。
下面的代码创建一个QPen对象,传入一个3元组int指定 GB值(全红色)的值。也可以通过传递 'r' 或 Qcolor。然后通过pen参数将其它传入plot。
pen=pg.mkPen(color=(255, 0, 0))
self.graphWidget.plot(hour, temperature, pen=pen)
效果如下:
通过改变QPen可以改变线条的外观,包括以像素为单位的线条宽度和使用标准Qt线条样式的样式(虚线、点线等)。比如创建一条15像素宽的红色虚线,代码为:
pen=pg.mkPen(color=(255, 0, 0), width=15, style=QtCore.Qt.DashLine)
结果如下:
标准Qt线条样式都可以使用,包括Qt.SolidLine, Qt.DashLine, Qt.DotLine, Qt.DashDotLine和 Qt.DashDotDotLine,起对样样式官方图如下
对于许多绘图,在绘图上添加标记或代替线条放置标记可能会有所帮助。要在绘图上绘制标记,请在调用时传递符号以用作标记.plot。
self.graphWidget.plot(hour, temperature, symbol='+')
此外symbol你也可以传入symbolSize,symbolBrush和 ymbolPen参数。传递的值作为 symbolBrush可以是任何颜色或QBrush样式,symbolPen中可以中使用颜色参数或QPen实例。
画用于绘制形状的轮廓,用于填充。
下面的代码将在粗红线上给出一个大小为30的蓝色十字标记。
pen=pg.mkPen(color=(255, 0, 0), width=15, style=QtCore.Qt.DashLine)
self.graphWidget.plot(hour, temperature, pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))
也支持传入任何 QPainterPath对象,然后完全自定义的标记形状。
画板标题对于为给定图表上显示的内容提供上下文非常重要。在 PyQtGraph中,可以使用 PlotWidget对象的setTitle()方法,设定标题字符串。
self.graphWidget.setTitle("Chongchong")
可以通过传递其他参数将文本样式(包括颜色、字体大小和粗细)应用于标题(以及 PyQtGraph中的任何其他标签)。
比如设置标题蓝色,字体大小为 30px。
self.graphWidget.setTitle("Chongchong", color="b", size="30pt")
也支持使用HTML标记语法来设置标题的样式,比如:
self.graphWidget.setTitle("<span style=\"color:blue;font-size:30pt\">Chongchong</span>")
与标题类似,可以使用setLabel()方法来创建我们的轴标识。这需要两个参数, position和text。position参数可以设置'left,'right','top','bottom'的值,用来支指出放置文本的轴的位置。参数text是要显示标题的文本。
可以将其他样式参数传递给该方法。但与标题略有不同,必须是有效的CSS名称-值对。例如,大小为font-size. 因为名字font-size有连字符,不能直接作为参数传递,必须使用 **dictionary方法。
styles={'color':'r', 'font-size':'20px'}
self.graphWidget.setLabel('left', '上证指数', **styles)
self.graphWidget.setLabel('bottom', '月', **styles)
也支持HTML样式的语法,比如
self.graphWidget.setLabel('left', "<span style=\"color:red;font- size:20px\">上证指数</span>")
self.graphWidget.setLabel('bottom', "<span style=\"color:red;font-size:20px\">月</span>")
除了轴和绘图标题之外,通常会要显示一个图例来标识给定线所代表的内容。比如添加了多条线时,可以通过调用来为绘图添加图例。可以通过PlotWidget对象的.addLegent。但是需要在调用时为每一行提供一个名称 .plot()。比如,以下代码在绘制的线分配了一个名称“2022年” .plot(). 此名称将用于标识图例中的行。
self.graphWidget.plot(x, y, name="2022年", pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))
self.graphWidget.addLegend()
图例默认显示在左上角。可以通过将2元组传递给offset创建图例时的参数。
添加背景网格可以让绘图更易于阅读,尤其是在尝试将相对x和y值相互比较时。可以通过调用PlotWidget的.showGrid为打开背景网格,可以独立切换x和y网格。
self.graphWidget.showGrid(x=True, y=True)
有时候会有限制绘图上可见的数据范围或将轴锁定在一致的范围内。在 PyQtGraph 中,这可以使用.setXRange()和.setYRange()方法来强制绘图仅显示轴上指定范围内的数据。
self.graphWidget.setXRange(2, 5, padding=0)
self.graphWidget.setYRange(3300, 3500, padding=0)
一个可选的填充参数导致范围设置为大于指定的分数(默认情况下在0.02和0.1之间,取决于ViewBox的大小)。如果要完全删除此填充,请传递0。
一个图中绘制多条线是很常见的。在PyQtGraph中,只需在PlotWidget中多次调用.plot()即可. 下面的例子,我绘制两条相似的数据线,每条线使用相同的线型、粗细等,但改变线的颜色。为了方便,定义一个plot函数,接受x和y要绘制的参数、线的名称(用于图例)和颜色。将颜色用于线条和标记颜色。
def plot(self, x, y, plotname, color):
pen=pg.mkPen(color=color)
self.graphWidget.plot(x, y, name=plotname, pen=pen, symbol='+', symbolSize=30, symbolBrush=(color))
self.plot(x, y1, "2021", 'r')
self.plot(x, y, "2022", 'b')
其结果如下图:
有事可能希望定期清除和刷新绘图可以通过.clear()调用来实现。
self.graphWidget.clear()
将会从图中删除线条,但保持所有其他属性相同。
虽然简单地清除画板并重新绘制所有元素,这样一来Qt必须销毁并重新创建 QGraphicsScene对象和所有元素。对于小型或简单的绘图,这没什么问题,但对一个比较复杂耗时的图,可能更好的方法是跟新局部数据,而不是从头来一遍。PyQtGraph 获取新数据并更新绘制的线,而不会影响画板的其他部分。
要更新画线,需要对线条对象的引用。首次使用创建行时返回此引用.plot可以简单地将它存储在一个变量中。请注意,这是对线不是对画板的引用。
my_line_ref=graphWidget.plot(x, y)
有了引用变量,只需其.setData关更新数据。
from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
from random import randint
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget=pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
self.x=list(range(100))
self.y=[randint(0,100) for _ in range(100)]
self.graphWidget.setBackground('w')
pen=pg.mkPen(color=(255, 0, 0))
self.data_line=self.graphWidget.plot(self.x, self.y, pen=pen)
app=QtWidgets.QApplication(sys.argv)
w=MainWindow()
w.show()
sys.exit(app.exec())
每50毫秒更新一次数据,尽管 PyQtGraph 绘制数据的速度比这快得多,但很难观察!为此,可以定义了一个Qt计时器,并将其设置为调用自定义方法update_plot_data更改数据,这样就会生成滚动的动态图:
self.timer=QtCore.QTimer()
self.timer.setInterval(50)
self.timer.timeout.connect(self.update_plot_data)
self.timer.start()
def update_plot_data(self):
self.x=self.x[1:]
self.x.append(self.x[-1] + 1)
self.y=self.y[1:]
self.y.append( randint(0,100))
self.data_line.setData(self.x, self.y)
本文我们介绍了,使用PyQtGraph绘制简单的图并自定义线条、标记和标签。实际上PyQtGraph是一个强大的绘图工具,作为一个入门介绍,想更深入一步的研究和使用可以参考PyQtGraph官方更详细的文档和实例程序。
天将和大家分享HTML5中canvas元素的使用,有一定参考价值,希望对大家有所帮助。
【推荐课程:HTML5教程】
canvas元素
主要使用 JavaScript 在网页上绘制图像画布是一个矩形区域,可以控制其每一像素而且canvas 拥有多种绘制路径、矩形、圆形、以及添加图像的方法,接下来将在文章中为大家详细介绍
html代码
<canvas id="demo"></canvas>
矩形
fillStyle:用来给图形添加色彩的
fillRect(x,y,width,height)
x:距离左上角的x值
y:距离左上角的y值
width,height:就是图形的宽高
<script type="text/javascript">
var demo=document.getElementById("demo");
var fang=demo.getContext("2d");
fang.fillStyle="pink";
fang.fillRect(0,0,200,50);
</script>
线条
moveTo:线条开始位置
lineTo:结束位置
lineWidth:线条宽度
strokeStyle:颜色
stroke:开始绘制
var demo=document.getElementById("demo");
var xian=demo.getContext("2d");
xian.moveTo(10,10);
xian.lineTo(100,100);
xian.lineWidth=2;
xian.strokeStyle="pink";
xian.stroke();
圆形
beginPath():开始路径
arc(x,y,r,sAngle,eAngle,counterclockwise)
x,y:为圆的中心点坐标
r:圆的半径
sAngle,eAngle:圆的起始角和结束角
counterclockwise:可写可不写规定应该逆时针还是顺时针绘图。False=顺时针,true=逆时针。
var demo=document.getElementById("demo");
var yuan=demo.getContext("2d");
yuan.beginPath();
yuan.arc(100,100,50,0,2*Math.PI);
yuan.strokeStyle="pink";
yuan.stroke();
图形插入
drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
sx,sy:剪切的 x,y 坐标位置
swidth,sheight:被剪切图像的宽度和高度
x,y:在画布上放置图像的 x,y 坐标位置
width,height:要使用的图像的宽度和高度
var demo=document.getElementById("demo");
var img1=document.getElementById("img1");
var img=demo.getContext("2d");
img1.onload=function(){
img.drawImage(img1,10,10,100,120)
总结:以上就是本篇文章的全部内容了,希望通过本篇文章对大家有所帮助。
以上就是HTML5中canvas元素如何绘制图形的详细内容,更多请关注其它相关文章!
更多技巧请《转发 + 关注》哦!
d3.js是一个用于绘图的JavaScript 库。 它可以可视化展示任何类型的数据。 d3.js允许绘制形状,然后将各种形状构建一个图形。本文档描述了一些函数,可以更有效地从数据中绘制svg。
在svg中绘制圆形。需要三个参数:分别代表圆心x位置的cx、圆心y位置的cy和半径的r。基础调用函数如下:
<circle style="fill: #69b3a2" stroke="black" cx=100 cy=100 r=40></circle>
现在,让我们用javascript来实现它,这基本上是相同的过程。
<!-- 直接绘图 -->
<svg>
<circle style="fill: #69b3a2" stroke="black" cx=100 cy=100 r=40></circle>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="circle"></svg>
<script>
// 创建svg元素
var svg=d3.select("#circle").append("svg").attr("width", 200).attr("height", 200)
// 设置属性
// stroke设置轮廓颜色
svg.append('circle').attr('cx', 100).attr('cy', 100).attr('r', 30).attr('stroke', 'black').attr('fill', 'red')
</script>
其中蓝色圆是由html绘图元素创建,红色圆是通过js创建
在svg中绘制矩形,四个参数是必需的:x,y,width和height。
<rect style="fill: #69b3a2" stroke="black" x=10 y=100, width=300 height=40></rect>
现在,让我们用javascript来实现它,这基本上是相同的过程。
<!-- 直接绘图 -->
<svg>
<rect style="fill: #69b3a2" stroke="black" x=10 y=100, width=300 height=40></rect>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="rect"></svg>
<script>
// 创建svg元素
var svg=d3.select("#rect").append("svg").attr("width", 800).attr("height", 200)
// 设置属性
svg.append('rect')
.attr('x', 10)
.attr('y', 120)
.attr('width', 600)
.attr('height', 40)
.attr('stroke', 'black')
.attr('fill', 'red');
其中蓝色矩形是由html绘图元素创建,红色矩形是通过js创建
在svg中绘制线段,四个参数是必需的:x0,y0,x1和y1(线段的两个顶点坐标)。
<line stroke="#69b3a2" x0=10 y0=10, x1=500 y1=100></line>
现在,让我们用javascript来实现它,这基本上是相同的过程。
<!-- 直接绘图 -->
<svg>
<line stroke="#69b3a2" x0=10 y0=10, x1=300 y1=100></line>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="segment"></svg>
<script>
// 创建svg元素
var svg=d3.select("#segment").append("svg").attr("width", 800).attr("height", 200)
// 设置属性
svg.append('line')
.attr('x1', 10)
.attr('y1', 10)
.attr('x2', 700)
.attr('y2', 100)
.attr('stroke', 'red')
</script>
其中蓝色线段是由html绘图元素创建,红色线段是通过js创建
在svg中添加文本,需要三个参数:x,y和text。
<text stroke="#69b3a2" style="font-size: 19px" x=100 y=50>I'm a piece of text</text>
现在,让我们用javascript来实现它,这基本上是相同的过程。
<!-- 直接绘图 -->
<svg>
<text stroke="#69b3a2" style="font-size: 19px" x=100 y=80>I'm a piece of text</text>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="text"></svg>
<script>
// 创建svg元素
var svg=d3.select("#text").append("svg").attr("width", 800).attr("height", 200)
//设置属性
svg.append('text')
.attr('x', 60)
.attr('y', 50)
.attr('stroke', 'red')
.style("font-size", 19)
.text("I'm another piece of text")
</script>
其中蓝色文本是由html绘图元素创建,红色文本是通过js创建
在svg添加文本,参数比较复杂。具体如下:
<path style="fill: none" stroke="black" d="M0 20 L150 150 L300 100 L450 20 L600 130"></path>
幸运的是,d3.js提供可以更有效地绘制折线的函数
<!-- 直接绘图 -->
<svg height=200 width=600>
<path style="fill: none" stroke="#69b3a2" d="M0 20 L150 150 L300 100 L450 20 L600 130"></path>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="line" height=200 width=600></svg>
<script>
// 创建svg元素
var svg=d3.select("#line").append("svg")
// 创建数据,多个点连接成折线
var data=[{ x: 0, y: 20 }, { x: 150, y: 150 }, { x: 300, y: 100 }, { x: 450, y: 20 }, { x: 600, y: 130 }]
// 创建连接函数
var lineFunc=d3.line()
.x(function (d) { return d.x })
.y(function (d) { return d.y })
// 添加元素
svg.append('path')
.attr('d', lineFunc(data))
.attr('stroke', 'red')
.attr('fill', 'none');
</script>
其中蓝色线条是由html绘图元素创建,红色线条是通过js创建
当然可以设置线条类型,如下所示
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="curve" height=300 width=600></svg>
<script>
// 创建数据
var data=[{ x: 0, y: 20 }, { x: 150, y: 150 }, { x: 300, y: 100 }, { x: 450, y: 20 }, { x: 600, y: 130 }]
// 创建svg元素
var svg=d3.select("#curve").append("svg").attr("width", 1800).attr("height", 200)
// 创建辅助函数
var curveFunc=d3.line()
// 设置线条类型,具体设置参考官方文档,可以尝试curveStep.
.curve(d3.curveBasis)
.x(function (d) { return d.x })
.y(function (d) { return d.y })
svg.append('path')
.attr('d', curveFunc(data))
.attr('stroke', 'black')
.attr('fill', 'none');
</script>
html的svg标签原生语法画区域很麻烦,还是用js容易。原生代码如下所示:
<path style="fill: #69b3a2" stroke="black" d="M0 200 L0 20 L150 150 L300 100 L450 20 L600 130 L600 200"></path>
js代码如下:
<!-- 原生绘图 -->
<svg height=300 width=800>
<path style="fill: #69b3a2" stroke="black" d="M0 200 L0 20 L150 150 L300 100 L450 20 L600 130 L600 200"></path>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="area" height=300 width=800></svg>
<script>
// 创建数据
var data=[{ x: 0, y: 20 }, { x: 150, y: 150 }, { x: 300, y: 100 }, { x: 450, y: 20 }, { x: 600, y: 130 }]
// 创建svg元素
var svg=d3.select("#area").append("svg")
// 创建辅助函数
var curveFunc=d3.area()
.x(function (d) { return d.x })
.y1(function (d) { return d.y }) // 区域上边界坐标
.y0(200) // 区域下边界坐标
// 添加属性
svg.append('path')
.attr('d', curveFunc(data))
.attr('stroke', 'black')
.attr('fill', 'red');
</script>
圆弧的添加也是一样,js最好。原生代码如下:
<path style="fill: #69b3a2" stroke="black" transform="translate(400,200)" d="M0,149 A150,150,0,0,1,-0.47,-149.9 L-0.3,-99.9 A100,100,0,0,0,0.15,99.9Z"></path>
现在,让我们使用d3.arc()辅助函数来绘制相同类型的形状。我们需要提供4个参数:innerRadius、outerRadius、startAngle、endAngle
<!-- 原生绘图 -->
<svg height=400 width=400>
<path style="fill: #69b3a2" stroke="black" transform="translate(400,200)"
d="M0,149 A150,150,0,0,1,-0.47,-149.9 L-0.3,-99.9 A100,100,0,0,0,0.15,99.9Z"></path>
</svg>
<!-- 加载d3 -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- 添加一个空的svg图片 -->
<svg id="arc" height=400 width=400></svg>
<script>
// 创建svg元素
var svg=d3.select("#arc").append("svg")
// 添加弧形
svg
.append("path")
.attr("transform", "translate(400,100)") // 平移距离
.attr("d", d3.arc()
.innerRadius(100) // 内圈半径
.outerRadius(150) // 外圈半径
.startAngle(3.14) // 开始角度(弧度),最下方为3.14
.endAngle(3.14 * 1.6) // 结束角度(弧度)
)
.attr('stroke', 'black')
.attr('fill', 'red');
</script>
其中蓝色圆弧是由html绘图元素创建,红色圆弧是通过js创建
*请认真填写需求信息,我们会在24小时内与您取得联系。