做项目报告的时候,有这么一个想法,就是能通过UI随时调用matplotlib进行二维图和三维图的绘制。
因此就诞生了做这么一个小模块的想法。
这里先上一下最终结果:
pyqt5内嵌matploblib画布。
matplotlib画布中有一个FigureCanvasQTAgg的模块可以用于UI绘制
模块设计思路: 1. ui文件
ui文件是通过qtdesigner直接生成的ui源码,与图表绘制相独立。
该文件用于设计一个matplotlib图表绘制类,存放我们需要做报告的任何图图表,以及我们的一些数据导入。
运行文件继承上面两个文件,运行实例。
UI模块
这个模块没什么好说的,基于QTdesigner进行图形绘制,图形界面已经每个组件定义如下。
(这个模块在教程中只是用于演示)
1.1 UI图形类类: | Ui_matplot_demo | 图形绘制类 |
---|---|---|
实例化方式 | 不需要入参 | |
方法 | ||
self.setupUi | 构建一个UI窗口 |
绘制的界面样式
界面控件属性
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui_ut.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_matplot_demo(object):
def setupUi(self, matplot_demo):
matplot_demo.setObjectName("matplot_demo")
matplot_demo.resize(1133, 721)
self.gridLayout = QtWidgets.QGridLayout(matplot_demo)
self.gridLayout.setObjectName("gridLayout")
self.bt_close = QtWidgets.QPushButton(matplot_demo)
self.bt_close.setObjectName("bt_close")
self.gridLayout.addWidget(self.bt_close, 1, 1, 1, 1)
self.bt_open = QtWidgets.QPushButton(matplot_demo)
self.bt_open.setObjectName("bt_open")
self.gridLayout.addWidget(self.bt_open, 1, 0, 1, 1)
self.plt3d_module = QtWidgets.QWidget(matplot_demo)
self.plt3d_module.setMinimumSize(QtCore.QSize(1111, 611))
self.plt3d_module.setObjectName("plt3d_module")
self.gridLayout.addWidget(self.plt3d_module, 0, 0, 1, 2)
self.retranslateUi(matplot_demo)
QtCore.QMetaObject.connectSlotsByName(matplot_demo)
def retranslateUi(self, matplot_demo):
_translate = QtCore.QCoreApplication.translate
matplot_demo.setWindowTitle(_translate("matplot_demo", "Form"))
self.bt_close.setText(_translate("matplot_demo", "按一下就可以关闭图片"))
self.bt_open.setText(_translate("matplot_demo", "按一下就可以画图"))
图表绘制模块
这个模块是核心的图表绘制模块,主要结构如下
1.1 依赖包包名 | 含义 | 安装方式 |
---|---|---|
numpy | 数学运算包 | pip install numpy |
matplotlilb | 数学绘图包 | pip install matplotlib |
类: | MyFigure | 图形绘制类 |
---|---|---|
实例化方式 | 入参 | 含义 |
width=5 | 控制画布宽度 | |
height=4 | 控制画布高度 | |
dpi=100 | 控制画布分辨率 | |
属性 | 含义 | 初值 |
self.fig | 实例化一个matplotlib的Figure类 | |
self.axes | 坐标系,可以是二维,也可以是三维 | |
方法 | ||
plot_sin | 画一个正弦函数 | |
plot_cos | 画一个余弦函数 | |
plot_3d | 画一个3D的图(基于leetcode218 天际线) |
import numpy as np
import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
matplotlib.use("Qt5Agg") # 声明使用QT5
# 创建一个matplotlib图形绘制类
class MyFigure(FigureCanvas):
def __init__(self, width=5, height=4, dpi=100):
# 第一步:创建一个创建Figure
self.fig = Figure(figsize=(width, height), dpi=dpi)
# 第二步:在父类中激活Figure窗口
super(MyFigure, self).__init__(self.fig) # 此句必不可少,否则不能显示图形
# 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1)
self.axes = None
# 第四步:就是画图,【可以在此类中画,也可以在其它类中画】
def plot_sin(self):
self.axes = self.fig.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
self.axes.plot(t, s)
def plot_cos(self):
self.axes = self.fig.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
self.axes.plot(t, s)
def plot_3d(self):
self.axes = self.fig.add_subplot(111, projection='3d')
x_edges = np.array([[10, 20], [10, 20], [10, 20], [10, 20],
[20, 30], [20, 30], [20, 30], [20, 30],
[30, 40], [30, 40], [30, 40], [30, 40],
[40, 50], [40, 50], [40, 50], [40, 50]])
# 设置y轴取值
y_edges = np.array([[10, 20], [20, 30], [30, 40], [40, 50],
[10, 20], [20, 30], [30, 40], [40, 50],
[10, 20], [20, 30], [30, 40], [40, 50],
[10, 20], [20, 30], [30, 40], [40, 50],
[10, 20], [20, 30], [30, 40], [40, 50]])
# 设置X,Y对应点的值。
即原始数据。
hist = np.array([[3.0], [0.0], [8.0], [4.0],
[2.0], [4.0], [5.0], [7.0],
[9.0], [2.0], [6.0], [3.0],
[0.0], [3.0], [1.0], [0.0]])
color_list = ['skyblue', 'lightgreen', 'bisque', 'gold',
'lightgreen', 'bisque', 'gold', 'lightpink',
'bisque', 'gold', 'lightpink', 'plum',
'gold', 'lightpink', 'plum', 'lightgray']
for i in range(len(x_edges)):
# 设置作图点的坐标
xpos, ypos = np.meshgrid(x_edges[i][:-1] - 2.5, y_edges[i][:-1] - 2.5)
xpos = xpos.flatten('F')
ypos = ypos.flatten('F')
zpos = np.zeros_like(xpos)
# 设置柱形图大小
dx = 5 * np.ones_like(zpos)
dy = dx.copy()
dz = hist[i].flatten()
# 设置坐标轴标签
self.axes.set_xlabel('front')
self.axes.set_ylabel('side')
self.axes.set_zlabel('height')
self.axes.bar3d(xpos, ypos, zpos, dx, dy, dz, color=color_list[i], zsort='average')
运行模块
1.1 依赖包
包名 | 含义 | 安装方式 |
---|---|---|
sys | 系统包 | - |
PyQt5 | UI包 | pip install pyqt5 |
项目包 | ||
ui_ut | UI模块 | |
leetcode218_figure | 图表绘制模块 |
类: | myWindow | 运行窗口类 |
---|---|---|
继承父类 | ||
QWidget | ||
Ui_matplot_demo | ||
实例化方式 | 入参 | 含义 |
不需要入参实例化 | ||
属性 | 含义 | 初值 |
self.F | 实例化一个MyFigure的图表绘制类 | |
方法 | ||
open_pic | 在UI中画图,绑定bt_open控件 | |
close_pic | 关闭图片,绑定bt_close控件 |
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from ui_ut import Ui_matplot_demo
from leetcode218_figure import MyFigure
class myWindow(QWidget, Ui_matplot_demo):
def __init__(self):
super(myWindow, self).__init__()
self.setupUi(self)
self.setWindowTitle("显示matplotlib绘制图形")
self.setMinimumSize(0, 0)
# 第五步:定义MyFigure类的一个实例
self.F = MyFigure(width=10, height=6, dpi=100)
self.F.plot_cos()
# 第六步:在GUI的groupBox中创建一个布局,用于添加MyFigure类的实例(即图形)后其他部件。
# 在容器中添加一个groupbox对象,在groupbox对象中创建布局
self.groupBox = QGroupBox(self.plt3d_module)
self.groupBox.setMinimumSize(QSize(1100, 610))
self.groupBox.setTitle("画图demo")
def connect_bind():
self.bt_open.clicked.connect(self.open_pic)
self.bt_close.clicked.connect(self.close_pic)
connect_bind()
self.glo_plt_figure = QGridLayout(self.groupBox)
def open_pic(self):
self.F = MyFigure(width=10, height=6, dpi=100)
self.F.plot_3d()
self.glo_plt_figure.addWidget(self.F, 0, 0)
print("here")
self.show()
self.glo_plt_figure.addWidget(self.F, 0, 0)
def close_pic(self):
self.glo_plt_figure.removeWidget(self.F)
self.show()
def main():
app = QApplication(sys.argv)
win = myWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)