本科毕设被研导要求添加可视化界面展示结果功能以填补实验室的需求,同时需要做好来自MatLab与python的接口。由于实验室大量项目工作在演示时需要使用界面,常有同门前来问询,而此工作中有大量踩坑踩雷需要注意,空口说自然不如图文来的明白完整,故写此系列博客,以避免不必要的时间浪费。
文章并非专业的界面设计教程,唯一写作目的为帮助不希望透彻理解PyQt5的人能够制作界面以回应导师/领导等人的期待,满足教学/项目等需求,为避免误导,以入职软件公司为目的请勿借鉴本博客。
上一篇:实验室项目展示用PyQt系列(3)如何调用MATLAB中的.m脚本文件
https://blog.csdn.net/pyc0551/article/details/131302317https://blog.csdn.net/pyc0551/article/details/131302317考虑到实时演示的需求,需要将结果图片输出在界面中,同时图片内容可能需要更新。实现这一需求,目前通过摸索,并参考其他博主,仅找到了一种方法。
PyQt的输出需要通过QGroupBox来实现,因此需要进行显示图片的需求下,需要放置QGroupBox固件于界面中。
在主程序中,首先需要在引用matplotlib之后,将plt设置为Qt5模式,再声明一个继承于FigureCanvas的MyFigure类。
import matplotlib.image as mpimg
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
class MyFigure(FigureCanvas):
def __init__(self,width=5, height=4, dpi=100):
plt.rcParams['font.family'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
self.fig = Figure(figsize=(width, height), dpi=dpi)
super(MyFigure,self).__init__(self.fig)
self.axes = self.fig.add_subplot(111)
#此部分代码撰写时参考自其他博主,但由于年代久远,未能找到原帖,未能标注原博客地址。
上述代码在初始化MyFigure的设置中,对plt的两个参数进行了更改,规定了其显示的字体、负号的类别,用于避免出现部分情况下图片中显示不出字符的问题。如果出现相关问题,可以着手从此处进行更改调试。
在界面初始化中,需要将用于图片输出的QGroupBox控件被继承为QGridLayout类,在生成用于输出的图片时,由于这一方法仅能对子图像进行输出,而plt中子图的部分函数可能会使用上与普通图像不同、甚至缺少部分功能,因此建议的做法是先通过plt输出一个普通的图像,将其保存为一个临时文件temp.png,再通过子图读入这一临时图像,实现输出。
class CNNEntry(QMainWindow, CNN):#神经网络目标识别界面
def __init__(self):
。。。(其他初始化的代码)
self.gridlayout = QGridLayout(self.groupBox)
self.gridlayout2 = QGridLayout(self.groupBox_2)
self.gridlayout3 = QGridLayout(self.groupBox_3)
self.gridlayout5 = QGridLayout(self.groupBox_5)
self.gridlayout6 = QGridLayout(self.groupBox_6)
def cnn_process():
Fig3 = MyFigure(width=100, height=100, dpi=100)
fig, ax = plt.subplots(1, 1)
temp_img = mpimg.imread(self.tgt_test_loader_test.dataset.imgs[self.graph_num][0])
ax.imshow(temp_img)
ax.axis('off')
ax.set_title(self.labels[self.tgt_test_loader_test.dataset.imgs[self.graph_num][1]],
fontsize='medium', y=0.91)
plt.savefig('./temp.png', bbox_inches='tight', dpi=100, pad_inches=0.0)
plt.close(fig=fig)
temp_img = mpimg.imread('./temp.png')
Fig3.axes.imshow(temp_img)
Fig3.axes.axis('off')
self.gridlayout3.removeWidget(Fig3)
self.gridlayout3.addWidget(Fig3, 0, 1)
需要注意的是,cnn_process部分第一行是将一个MyFigure类初始化,该函数中的第二块代码是将图片绘制并保存为临时文件,此处代码根据具体情况可能会有所不同。第三块代码用于输出图片,即通过子图像读入这一图片,将其送入QGridLayout进行显示。如果要实现图片的更新,仅需要在addWidget之前加上removeWidget这一函数即可。如果图片无法更新,可以尝试将addWidget中的第二三个参数改为(..., 0, 0)。
另外,由于是将普通的plt图像通过plt的子图像读入,因此原先图像可能会出现超框、字体较小等情况,建议在对图像的设置上直接套用cnn_process中的第二块代码,再根据具体情况修改参数调整。