快速学会绘制Pyqt5中的所有图(下)
Pyqt5相关文章:
快速掌握Pyqt5的三种主窗口
快速掌握Pyqt5的2种弹簧
快速掌握Pyqt5的5种布局
快速弄懂Pyqt5的5种项目视图(Item View)
快速弄懂Pyqt5的4种项目部件(Item Widget)
快速掌握Pyqt5的6种按钮
快速掌握Pyqt5的10种容器(Containers)
快速掌握Pyqt5的20种输入控件(Input Widgets)
快速掌握Pyqt5的9种显示控件
详细学习Pyqt5中的5种布局方式
详细学习Pyqt5中的6种按钮
详细学习Pyqt5中的2种弹簧
详细学习Pyqt5的5种项目视图(Item View)
详细学习Pyqt5的4种项目部件(Item Widget)
详细学习Pyqt5的20种输入控件(Input Widgets)
详细学习Pyqt5的9种显示控件
详细学习Pyqt5的10种容器(Containers)
详细学习PyQt5与数据库交互
详细学习PyQt5中的多线程
快速学习PyQt5的动画和图形效果
快速学习PyQt5的高级自定义控件
快速学会绘制Pyqt5中的所有图(上)
快速学会绘制Pyqt5中的所有图(下)
通过“待办事项列表项目”快速学习Pyqt5的一些特性
待续。。。
雷达图
PyQtGraph 并不直接支持雷达图(也称为蜘蛛网图或极坐标图),但您可以使用 PyQt 的绘图能力手动创建一个。要在 PyQt 中绘制雷达图,您需要使用 QPainter
类来在 QWidget
或类似对象上进行自定义绘图。
以下是一个使用 PyQt5 创建简单雷达图的示例:
编写代码绘制雷达图:
import sys
import math
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPolygon, QPen
from PyQt5.QtCore import Qt, QPoint
class RadarWidget(QWidget):
def __init__(self, data):
super().__init__()
self.data = data
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# 雷达图的中心点
center = QPoint(int(self.width() / 2), int(self.height() / 2))
radius = min(int(self.width() / 2), int(self.height() / 2)) - 10
# 绘制雷达图的轴
num_axes = len(self.data)
for i in range(num_axes):
angle = 2 * math.pi * i / num_axes
x =int( center.x() + radius * math.cos(angle))
y =int( center.y() + radius * math.sin(angle))
painter.drawLine(center, QPoint(x, y))
# 绘制雷达图的数据多边形
polygon = QPolygon()
for i in range(num_axes):
angle = 2 * math.pi * i / num_axes
value = self.data[i]
x = int(center.x() + value * radius * math.cos(angle))
y = int(center.y() + value * radius * math.sin(angle))
polygon << QPoint(x, y)
painter.setPen(QPen(Qt.blue, 2))
painter.drawPolygon(polygon)
# 创建一个 QApplication 实例
app = QApplication(sys.argv)
# 创建雷达图窗口
radar_data = [0.7, 0.8, 0.5, 0.6, 0.9] # 示例数据
radarWidget = RadarWidget(radar_data)
radarWidget.resize(400, 400)
radarWidget.show()
# 启动应用程序的事件循环
sys.exit(app.exec_())
在这个例子中,我们创建了一个继承自 QWidget
的 RadarWidget
类来显示雷达图。数据以列表形式传递给 RadarWidget
,每个元素表示雷达图上一个轴的值。
流程图
在 PyQtGraph 中绘制流程图需要使用图形和线条来手动创建图形元素。PyQtGraph 主要专注于数据可视化,并不直接支持流程图的绘制。但是,您可以使用 PyQt5 的图形视图框架(QGraphicsScene
和 QGraphicsView
)来创建流程图。
以下是使用 PyQt5 创建简单流程图的示例代码:
编写代码绘制流程图:
import sys
import math
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsTextItem, QGraphicsLineItem,QGraphicsPolygonItem
from PyQt5.QtCore import Qt, QRectF, QPointF, QLineF
from PyQt5.QtGui import QPen, QBrush, QColor, QPolygonF
class Arrow(QGraphicsLineItem):
def __init__(self, start_item, end_item, parent=None):
super().__init__(parent)
# 计算起始点和结束点
start_point = start_item.mapToScene(start_item.rect().bottomLeft() + QPointF(start_item.rect().width() / 2, 0))
end_point = end_item.mapToScene(end_item.rect().topLeft() + QPointF(end_item.rect().width() / 2, 0))
# 设置线条
line = QLineF(start_point, end_point)
self.setLine(line)
self.setPen(QPen(Qt.black, 2))
# 箭头头部尺寸
arrow_size = 9.0
# 计算箭头角度
angle = math.atan2(-line.dy(), line.dx())
# 创建箭头头部
arrow_head = QPolygonF()
arrow_head.append(line.p2())
arrow_head.append(line.p2() - QPointF(math.sin(angle + math.pi / 3) * arrow_size,
math.cos(angle + math.pi / 3) * arrow_size))
arrow_head.append(line.p2() - QPointF(math.sin(angle + math.pi - math.pi / 3) * arrow_size,
math.cos(angle + math.pi - math.pi / 3) * arrow_size))
# 添加箭头头部到场景
arrow_head_item = QGraphicsPolygonItem(arrow_head, self)
arrow_head_item.setBrush(Qt.black)
arrow_head_item.setPen(QPen(Qt.black, 2))
class FlowChartNode(QGraphicsRectItem):
def __init__(self, text, x, y, width, height, parent=None):
super().__init__(x, y, width, height, parent)
self.setBrush(QBrush(QColor(200, 200, 255)))
self.setPen(QPen(Qt.black, 2))
# 添加文本标签
text_item = QGraphicsTextItem(text, self)
text_item.setPos(x + 10, y + 10)
text_item.setTextWidth(width - 20)
app = QApplication(sys.argv)
scene = QGraphicsScene()
node1 = FlowChartNode("开始", 50, 50, 100, 50)
node2 = FlowChartNode("步骤1", 50, 150, 100, 50)
node3 = FlowChartNode("结束", 50, 250, 100, 50)
scene.addItem(node1)
scene.addItem(node2)
scene.addItem(node3)
arrow1 = Arrow(node1, node2)
arrow2 = Arrow(node2, node3)
scene.addItem(arrow1)
scene.addItem(arrow2)
view = QGraphicsView(scene)
view.show()
sys.exit(app.exec_())
在这个例子中,我们定义了一个 FlowChartNode
类来表示流程图中的节点,该类继承自 QGraphicsRectItem
。然后,我们创建了一个 QGraphicsScene
来容纳这些节点,并使用 QGraphicsView
显示它们。
树状图
在 PyQtGraph 中创建树状图(或树形结构图)通常不是直接支持的,因为 PyQtGraph 主要用于数据可视化,如绘制折线图、散点图等。但是,您可以使用 PyQt5 的 QTreeView
和 QStandardItemModel
来创建一个树状图界面。
以下是使用 PyQt5 创建树状图的示例代码:
编写代码以创建树状图:
import sys
from PyQt5.QtWidgets import QApplication, QTreeView
from PyQt5.QtGui import QStandardItem, QStandardItemModel
app = QApplication(sys.argv)
# 创建标准项模型
model = QStandardItemModel()
rootNode = model.invisibleRootItem()
# 创建节点
parent1 = QStandardItem('父节点1')
child1 = QStandardItem('子节点1')
child2 = QStandardItem('子节点2')
parent1.appendRow(child1)
parent1.appendRow(child2)
parent2 = QStandardItem('父节点2')
child3 = QStandardItem('子节点3')
parent2.appendRow(child3)
rootNode.appendRow(parent1)
rootNode.appendRow(parent2)
# 创建树视图并设置模型
treeView = QTreeView()
treeView.setHeaderHidden(True)
treeView.setModel(model)
treeView.expandAll() # 展开所有节点
# 显示树视图
treeView.show()
sys.exit(app.exec_())
在这个例子中,我们创建了一个 QStandardItemModel
来存储树形数据,然后向模型中添加了几个 QStandardItem
作为节点。QTreeView
用于展示这个模型。每个节点都可以有子节点,形成树形结构。
网络图
在 PyQtGraph 中直接绘制网络图(Graph Visualization)并不直接支持,因为 PyQtGraph 主要用于绘制二维和三维的数据可视化图形,如折线图、散点图等。但是,您可以结合使用 PyQt 和其他 Python 图形库,如 NetworkX,来创建和显示网络图。
以下是一个使用 PyQt5 和 NetworkX 创建网络图的示例:
编写代码以创建网络图:
import sys
import networkx as nx
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import QApplication, QMainWindow, QSizePolicy, QWidget, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class NetworkGraph(QWidget):
def __init__(self, parent=None):
super(NetworkGraph, self).__init__(parent)
self.figure, self.ax = plt.subplots()
self.canvas = FigureCanvas(self.figure)
self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.canvas.updateGeometry()
layout = QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.draw_graph()
def draw_graph(self):
# 创建一个网络图
G = nx.karate_club_graph()
# 绘制网络图
pos = nx.spring_layout(G)
nx.draw(G, pos, ax=self.ax, with_labels=True, node_color='skyblue', edge_color='gray')
# 更新画布
self.canvas.draw()
app = QApplication(sys.argv)
mainWindow = QMainWindow()
mainWindow.setCentralWidget(NetworkGraph())
mainWindow.show()
sys.exit(app.exec_())
在这个示例中,我们创建了一个名为 NetworkGraph
的自定义 QWidget,用于显示由 NetworkX 生成的网络图。使用 NetworkX 创建并配置图形,然后使用 Matplotlib 进行绘图。最后,将 Matplotlib 图形嵌入到 PyQt5 应用程序窗口中。
气泡图
在 PyQtGraph 中绘制气泡图可以通过使用 ScatterPlotItem
类并调整点的大小来实现。气泡图是散点图的一种变体,其中每个点的大小可以代表数据的一个额外维度。
以下是使用 PyQtGraph 创建气泡图的步骤和示例代码:
编写代码以绘制气泡图:
import sys
import numpy as np
from PyQt5 import QtWidgets
import pyqtgraph as pg
# 创建一个应用程序实例
app = QtWidgets.QApplication(sys.argv)
# 创建一个主窗口
mainWindow = QtWidgets.QMainWindow()
# 创建一个绘图控件
plotWidget = pg.PlotWidget()
plotWidget.setBackground("w")
mainWindow.setCentralWidget(plotWidget)
# 准备数据
x = np.random.rand(100) * 10
y = np.random.rand(100) * 10
sizes = np.random.rand(100) * 50 # 气泡的大小
# 创建散点图项目
scatterPlotItem = pg.ScatterPlotItem(pen=pg.mkPen(None), brush="#dcbeff")
# 现在使用 setData 设置点的坐标和大小
scatterPlotItem.setData(x, y, size=sizes)
# 将散点图添加到绘图控件
plotWidget.addItem(scatterPlotItem)
# 显示主窗口
mainWindow.show()
# 启动应用程序的事件循环
sys.exit(app.exec_())
在这个例子中,我们使用 ScatterPlotItem
创建了一个散点图,并通过改变每个点的大小(size
参数)来创建一个气泡图效果。x
和 y
是数据点的坐标,sizes
数组决定了每个点的大小。
地图图表
在 PyQt 中绘制地图图表通常需要结合使用地理信息系统(GIS)相关的库,例如 GeoPandas、Folium 或 PyQGIS。这些库可以处理地理数据并生成地图,但是它们不是 PyQtGraph 的一部分。另一种选择是使用 QGIS,这是一个完整的地理信息系统平台,它可以与 PyQt 结合使用。
以下是一个使用 Python、PyQt5 和 Folium 创建交互式地图图表的基本示例:
编写代码以创建地图图表:
import sys
import os
import folium
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
class MapWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.view = QWebEngineView(self)
self.init_ui()
def init_ui(self):
# 创建一个 Folium 地图,您可以调整 zoom_start 来设置初始缩放级别
m = folium.Map(location=[45.5236, -122.6750], zoom_start=13)
# 获取当前文件夹的绝对路径
dirname = os.path.abspath(os.path.dirname(__file__))
# 保存地图为 HTML 文件
map_path = os.path.join(dirname, 'map.html')
m.save(map_path)
# 在 QWebEngineView 中加载 HTML self.view.load(QUrl.fromLocalFile(map_path))
# 设置 QWebEngineView 控件的最小尺寸
self.view.setMinimumSize(800, 600) # 例如,设置为宽800像素,高600像素
self.view.show()
app = QApplication(sys.argv)
mainWindow = QMainWindow()
mapWidget = MapWidget()
# 设置主窗口的初始大小
mainWindow.resize(800, 600) # 可以根据需要调整这个尺寸
mainWindow.setCentralWidget(mapWidget)
mainWindow.show()
sys.exit(app.exec_())
在这个示例中,我们使用 Folium 创建了一个简单的地图,并将其保存为一个 HTML 文件。然后我们使用 PyQt5 的 QWebEngineView
小部件加载并显示这个 HTML 文件,从而在 PyQt 应用程序中嵌入了地图。
桑基图
桑基图是一种特殊的流程图,它用于表示数据流和传输。在 PyQtGraph 中直接绘制桑基图并不支持,因为它主要用于绘制二维和三维的数据可视化图形,如折线图、散点图等。然而,您可以使用其他的Python库,如 matplotlib
,来创建桑基图,并将其嵌入到 PyQt 应用程序中。
以下是一个使用 Python、PyQt5 和 Matplotlib 创建桑基图的基本示例:
编写代码以创建桑基图:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey
class SankeyWidget(QWidget):
def __init__(self, parent=None):
super(SankeyWidget, self).__init__(parent)
self.figure, self.ax = plt.subplots()
self.canvas = FigureCanvas(self.figure)
layout = QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.draw_sankey()
def draw_sankey(self):
# 创建桑基图
sankey = Sankey(ax=self.ax)
sankey.add(flows=[1, -1, 0.5, -0.5], labels=['', '', '', ''], orientations=[0, 0, 1, -1])
sankey.finish()
# 更新画布
self.canvas.draw()
app = QApplication(sys.argv)
mainWindow = QMainWindow()
mainWindow.setCentralWidget(SankeyWidget())
mainWindow.show()
sys.exit(app.exec_())
在这个示例中,我们定义了一个 SankeyWidget
类来展示桑基图。使用 Matplotlib 创建桑基图,并将其嵌入到 PyQt5 应用程序中。
组合图
在 PyQtGraph 中创建组合图(例如,将折线图和柱状图组合在一起)可以通过在同一个绘图控件(PlotWidget
)中添加多个图表元素来实现。这样,您可以在同一个坐标轴上或在相互关联的坐标轴上展示不同类型的数据。
以下是一个示例,展示如何在 PyQtGraph 中创建一个组合了折线图和柱状图的组合图:
编写代码以创建组合图:
import sys
import numpy as np
from PyQt5 import QtWidgets
import pyqtgraph as pg
# 创建一个应用程序实例
app = QtWidgets.QApplication(sys.argv)
# 创建一个主窗口
mainWindow = QtWidgets.QMainWindow()
# 创建一个绘图控件
plotWidget = pg.PlotWidget()
plotWidget.setBackground('w')
mainWindow.setCentralWidget(plotWidget)
# 准备数据
x = np.arange(10)
y1 = np.random.randint(1, 20, size=10) # 柱状图的数据
y2 = np.random.randint(1, 20, size=10) # 折线图的数据
# 创建柱状图项目
barGraphItem = pg.BarGraphItem(x=x, height=y1, width=0.6, brush='#fffac8')
plotWidget.addItem(barGraphItem)
# 创建折线图项目
plotWidget.plot(x, y2, pen=pg.mkPen(color='#dcbeff', width=2))
# 显示主窗口
mainWindow.show()
# 启动应用程序的事件循环
sys.exit(app.exec_())
在这个示例中,我们首先创建了一个包含柱状图和折线图的 PlotWidget
。BarGraphItem
用于柱状图,而 plot
方法用于折线图。通过将它们添加到同一个 PlotWidget
中,我们可以将两种图表组合在一起显示。
股票图
在 PyQtGraph 中绘制股票图(通常指蜡烛图或OHLC图)需要一些额外的步骤,因为这需要特殊的图表来表示股票的开盘价、最高价、最低价和收盘价。PyQtGraph 提供了 CandlestickItem
类来创建这种类型的图表。
以下是使用 PyQtGraph 创建股票图的步骤和示例代码:
编写代码以绘制股票图:
import sys
import numpy as np
from PyQt5 import QtWidgets
import pyqtgraph as pg
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data):
pg.GraphicsObject.__init__(self)
self.data = data # data应该是一个包含(open, high, low, close)的列表
self.generatePicture()
def generatePicture(self):
self.picture = pg.QtGui.QPicture()
p = pg.QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('b')) # 设置蜡烛图的颜色
w = 0.3
for (t, open, high, low, close) in self.data:
p.drawLine(pg.QtCore.QPointF(t, low), pg.QtCore.QPointF(t, high))
if open > close:
p.setBrush(pg.mkBrush('g'))
else:
p.setBrush(pg.mkBrush('r'))
p.drawRect(pg.QtCore.QRectF(t - w, open, w * 2, close - open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
return pg.QtCore.QRectF(self.picture.boundingRect())
# 创建一个应用程序实例
app = QtWidgets.QApplication(sys.argv)
# 创建一个主窗口
mainWindow = QtWidgets.QMainWindow()
# 创建一个绘图控件
plotWidget = pg.PlotWidget()
plotWidget.setBackground("w")
mainWindow.setCentralWidget(plotWidget)
# 准备数据
data = [ # 示例数据:(时间, 开盘价, 最高价, 最低价, 收盘价)
(1, 10, 15, 5, 13),
(2, 13, 20, 10, 15),
(3, 15, 17, 13, 16),
(4, 16, 19, 14, 10),
# ...
]
# 创建蜡烛图项目
item = CandlestickItem(data)
plotWidget.addItem(item)
# 显示主窗口
mainWindow.show()
# 启动应用程序的事件循环
sys.exit(app.exec_())
在这个示例中,我们首先定义了一个 CandlestickItem
类来创建股票图。该类继承自 GraphicsObject
,并且重写了绘图方法来绘制蜡烛图。数据格式是一个元组列表,每个元组代表一个时间点上的开盘价、最高价、最低价和收盘价。
甘特图
在 PyQtGraph 中创建甘特图需要一些额外的工作,因为它主要用于绘制二维和三维的数据可视化图形,如折线图、散点图等,而不直接支持甘特图。但是,您可以使用 PyQt 的基本图形功能来手动绘制甘特图。
以下是使用 PyQt5 创建简单甘特图的示例代码:
编写代码以创建甘特图:
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsTextItem
from PyQt5.QtGui import QColor, QPen, QFont
from PyQt5.QtCore import QRectF
class GanttChartItem(QGraphicsRectItem):
def __init__(self, text, start, duration, row, color, parent=None):
super(GanttChartItem, self).__init__(parent)
# 设置矩形的尺寸和位置
self.setRect(QRectF(start, row * 50, duration, 30))
self.setBrush(QColor(color))
self.setPen(QPen(QColor('black'), 2)) # 添加边框
# 添加文本标签
text_item = QGraphicsTextItem(text, self)
text_item.setFont(QFont('Arial', 10))
text_item.setDefaultTextColor(QColor('black'))
text_item.setPos(start + 2, row * 50 + 5)
app = QApplication(sys.argv)
# 创建场景
scene = QGraphicsScene()
# 创建甘特图条目
ganttItem1 = GanttChartItem("项目1", 0, 100, 0, '#78C0A8')
ganttItem2 = GanttChartItem("项目2", 50, 150, 1, '#F4D35E')
ganttItem3 = GanttChartItem("项目3", 120, 100, 2, '#EE964B')
# 将条目添加到场景
scene.addItem(ganttItem1)
scene.addItem(ganttItem2)
scene.addItem(ganttItem3)
# 创建视图
view = QGraphicsView(scene)
# 设置合适的视图尺寸
view.setSceneRect(0, 0, 400, 200)
view.setMinimumSize(600, 400)
# 设置窗口标题
view.setWindowTitle("python")
# 显示视图窗口
view.show()
sys.exit(app.exec_())
在这个示例中,我们定义了一个 GanttChartItem
类来表示甘特图中的单个任务。每个任务在水平方向上表示其持续时间,在垂直方向上表示不同的任务行。QGraphicsScene
用于容纳这些任务,而 QGraphicsView
用于显示它们。
平行坐标图
在 PyQtGraph 中直接绘制平行坐标图(Parallel Coordinates)并不直接支持,因为 PyQtGraph 主要用于绘制二维和三维的数据可视化图形,如折线图、散点图等。然而,您可以使用其他的Python库,如 matplotlib
或 pandas
,来创建平行坐标图,并将其嵌入到 PyQt 应用程序中。
以下是一个使用 Python、PyQt5 和 Matplotlib 创建平行坐标图的基本示例:
编写代码以创建平行坐标图:
import sys
import pandas as pd
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from pandas.plotting import parallel_coordinates
class ParallelCoordinatesWidget(QWidget):
def __init__(self, parent=None):
super(ParallelCoordinatesWidget, self).__init__(parent)
self.figure, self.ax = plt.subplots()
self.canvas = FigureCanvas(self.figure)
layout = QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.draw_parallel_coordinates()
def draw_parallel_coordinates(self):
# 创建数据
data = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [4, 3, 2, 1],
'C': [2, 3, 4, 1],
'D': [4, 1, 3, 2]
})
# 绘制平行坐标图
parallel_coordinates(data, 'A', ax=self.ax)
# 更新画布
self.canvas.draw()
app = QApplication(sys.argv)
mainWindow = QMainWindow()
mainWindow.setCentralWidget(ParallelCoordinatesWidget())
mainWindow.show()
sys.exit(app.exec_())
在这个示例中,我们定义了一个 ParallelCoordinatesWidget
类来展示平行坐标图。使用 Pandas 和 Matplotlib 创建平行坐标图,并将其嵌入到 PyQt5 应用程序中。
通过本系列教程,我们了解了如何使用PyQt5结合PyQtGraph和其他库来创建一系列不同的图表,从而使数据更加生动且易于理解。从基础的图表到复杂的GIS表示,PyQt5提供了广泛的功能,以帮助开发者在Python中构建专业的数据可视化解决方案。